From cf6e36b784f6ea845dcc52774d06682f30c1a183 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 15 Apr 2021 09:52:03 -0400 Subject: [PATCH 01/78] add vexp parser --- .gitmodules | 3 +++ extern/CMakeLists.txt | 33 +++++++++++++++++++++++++++++++++ extern/vexpparser | 1 + 3 files changed, 37 insertions(+) create mode 160000 extern/vexpparser diff --git a/.gitmodules b/.gitmodules index f2f3e286e..ae0b41cc0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "extern/smt-switch"] path = extern/smt-switch url = https://github.com/makaimann/smt-switch.git +[submodule "extern/vexpparser"] + path = extern/vexpparser + url = https://github.com/zhanghongce/vexpparser.git diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index c1aea656f..96ed94c94 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -126,6 +126,39 @@ if(NOT VERILOGPARSER_FOUND) endif() # VERILOGPARSER_FOUND +# ---------------------------------------------------------------------------- # +# Verilog Expression Parser +# +# TARGET vexpparser::vexpparser +# SOURCE https://github.com/zhanghongce/vexpparser.git +# PATH extern/vexpparser +# ---------------------------------------------------------------------------- # +# find installed package +find_package(vexpparser 1.1.0 QUIET) + +# embed to build tree if not installed +if(NOT VEXP_PARSER_FOUND) + + # fetch from git + if(${ILANG_FETCH_DEPS}) + + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init vexpparser + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE GIT_SUBMOD_RESULT + ) + + if(NOT GIT_SUBMOD_RESULT EQUAL "0") + message(FATAL_ERROR "Submodule update failed with ${GIT_SUBMOD_RESULT}") + endif() + + endif() # ILANG_FETCH_DEPS + + # embedded build + add_subdirectory(vexpparser) + +endif() # VERILOGPARSER_FOUND + # ---------------------------------------------------------------------------- # # Template-based ILA Synthesis # diff --git a/extern/vexpparser b/extern/vexpparser new file mode 160000 index 000000000..5c7786453 --- /dev/null +++ b/extern/vexpparser @@ -0,0 +1 @@ +Subproject commit 5c7786453033a16d36cd4081c36ce179286f4b92 From 426c2279e2c40e6323535e0722afbd647441285d Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 21 Apr 2021 15:35:10 -0400 Subject: [PATCH 02/78] update vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 5c7786453..3d959485a 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 5c7786453033a16d36cd4081c36ce179286f4b92 +Subproject commit 3d959485a8f039c3200304e82534b9563aef6a3c From b34f537804028b7bb98cba57bc3b8fbe2e0cb078 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 23 Apr 2021 16:27:57 -0400 Subject: [PATCH 03/78] rf parsing step 1 structure --- include/ilang/rfmap-in/verilog_rfmap.h | 218 ++++++++ src/CMakeLists.txt | 14 + src/rfmap-in/CMakeLists.txt | 7 + src/rfmap-in/verilog_rfmap.cc | 659 +++++++++++++++++++++++++ 4 files changed, 898 insertions(+) create mode 100644 include/ilang/rfmap-in/verilog_rfmap.h create mode 100644 src/rfmap-in/CMakeLists.txt create mode 100644 src/rfmap-in/verilog_rfmap.cc diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h new file mode 100644 index 000000000..9be9dfd07 --- /dev/null +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -0,0 +1,218 @@ +/// \file Verilog Verification Refinement Map Interface Class +/// External Refinement Map Interface Classe +/// --- Hongce Zhang (hongcez@princeton.edu) + + +#ifndef VERILOG_RFMAP_H__ +#define VERILOG_RFMAP_H__ + +#include +#include +#include +#include +#include +#include + +namespace ilang { +namespace rfmap { + + +// ---------------------- varmap ------------------------------- // + +/* +"model names" : { + "ILA" : "SomeNameHere", + "RTL" : "SomeNameHere" +} +*/ + +typedef verilog_expr::VExprAst::VExprAstPtr RfExpr; + +/// \class Module Name section (optional) +struct ModelNames { + std::string IlaModuleName; + std::string RtlModuleName; +}; + +/* +"ILA_mem_state_var_2" : { // case 4 : external RTL memory + "wen" : "", + "waddr" : "", + "wdata" : "", + "ren" : "", + "raddr" : "", + "rdata" : "" +}, +*/ + +struct SingleVarMap{ + /// a single refinement string + RfExpr single_map; + /// a list of pair of string + std::vector> cond_map; +}; + +struct ExternalMemPortMap { + SingleVarMap wen_map; + SingleVarMap waddr_map; + SingleVarMap wdata_map; + SingleVarMap ren_map; + SingleVarMap raddr_map; + SingleVarMap rdata_map; +}; // struct ExternalMemPortMap + +struct IlaStateVarMapping { + enum class StateVarMapType { + SINGLE, + CONDITIONAL, + EXTERNMEM + } type; + /// a single refinement string + SingleVarMap single_map; + /// the standard 6-port map + std::vector externmem_map; +}; // struct IlaStateVarMapping + +struct RtlInterfaceMapping{ + /// "CLOCK" : { "clkA" : "wclk", "clkB" : ["rclk", "clk"] } + // name of the clock domain -> list of clock pins + std::map> clock_domain_defs; + + // "RESET" : "reset", // you can have a list of signals here + std::vector reset_pins; + // "NRESET" : ["nreset1", "nreset2"], // like this + std::vector nreset_pins; + // "CUSTOMRESET" : {"name" : "input-pin", ...} + std::map> custom_reset_domain_defs; +}; // struct RtlInterfaceMapping + +typedef std::vector OneBitSignalSequence; + +struct ResetSpecification { + // rtl state var -> value map + std::map initial_state; + // reset cycle : unsigned int + unsigned reset_cycle; + // customized reset sequence + std::map custom_reset_sequence; +}; // ResetSpecification + +struct ClockSpecification { + struct factor { + unsigned high; + unsigned low; + unsigned offset; + }; + + unsigned gcm_period; + // per-clock domain specification, name -> sequence + std::map custom_clock_sequence; + // specified by the factor + std::map custom_clock_factor; +}; // ClockSpecification + +struct UninterpretedFunctionApplication{ + struct Apply { + RfExpr result_map; + std::vector arg_map; + }; + std::vector func_applications; +}; // UninterpretedFunctionApplication + +struct GeneralVerilogMonitor { + struct VarDef { + enum class var_type {REG, WIRE} type; + unsigned width; + }; // VarDef + + std::vector verilog_inline; + std::map var_defs; + std::set var_uses; +}; // GeneralVerilogMonitor + +struct ValueRecorder { + RfExpr condition; + RfExpr value; + unsigned width; +}; + +// this is not directly used +struct SignalDelay { + RfExpr signal; + unsigned num_cycle; +}; + +struct PhaseTracker { + struct Assignment { + std::string LHS; + RfExpr RHS; + }; + typedef std::vector Action; + struct Rule { + std::string stage_name; + RfExpr enter_rule; // this is not using Verilog signals + RfExpr exit_rule; + Action enter_action; + Action exit_action; + }; + + using VarDef = GeneralVerilogMonitor::VarDef; + // name to defs + std::map var_defs; + std::vector rules; +}; + +// ---------------------- inst-cond ------------------------------- // + +struct InstructionCompleteCondition{ + std::string instruction_name; + enum class ConditionType {BOUND, SIGNAL} type; + unsigned ready_bound; + unsigned max_bound; + std::vector start_condition; + RfExpr ready_signal; +}; // + +struct VerilogRefinementMap { + // ---------------------- varmap ------------------------------- // + /// model name section (optional) + ModelNames model_names; + /// State mapping section + std::map ila_state_var_map; + /// RTL interface connection specification + RtlInterfaceMapping rtl_interface_connection; + /// reset section + ResetSpecification reset_specification; + /// clock section + ClockSpecification clock_specification; + /// Uninterpreted function map : func-name -> applications + std::map uf_application; + /// "additional mapping" section + std::vector additional_mapping; + /// "assumptions" section + std::vector assumptions; + /// Customized Verilog Monitor + std::map phase_tracker; + std::map value_recorder; + std::map customized_monitor; + + // ---------------------- inst-cond ------------------------------- // + std::map inst_complete_cond; + std::vector global_invariants; + + // member function : return true if checking passed + bool SelfCheckField() const; + + // from JSON + VerilogRefinementMap(const std::string & varmap_json_file, + const std::string & instcond_json_file); + +private: + bool ParseRfExprErrFlag; +}; // VerilogRefinementMap + +} // namespace ilang +} // namespace rfmap + +#endif // VERILOG_RFMAP_H__ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b80acf95a..a03ca3786 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,6 +19,7 @@ add_subdirectory(verilog-in) add_subdirectory(verilog-out) add_subdirectory(vtarget-out) add_subdirectory(smt-inout) +add_subdirectory(rfmap-in) if(${ILANG_BUILD_SYNTH}) add_subdirectory(target-itsy) @@ -143,6 +144,19 @@ else() target_link_libraries(${ILANG_LIB_NAME} PRIVATE verilogparser::verilogparser) endif() +## +## refinement parser +## +if(NOT TARGET vexpparser::vexpparser) + find_package(vexpparser REQUIRED) +endif() + +if (${ILANG_BUILD_TEST} OR ${ILANG_INSTALL_DEV}) + target_link_libraries(${ILANG_LIB_NAME} PUBLIC vexpparser::vexpparser) +else() + target_link_libraries(${ILANG_LIB_NAME} PRIVATE vexpparser::vexpparser) +endif() + ## ## vcd parser ## diff --git a/src/rfmap-in/CMakeLists.txt b/src/rfmap-in/CMakeLists.txt new file mode 100644 index 000000000..ce38831d3 --- /dev/null +++ b/src/rfmap-in/CMakeLists.txt @@ -0,0 +1,7 @@ +# ---------------------------------------------------------------------------- # +# source +# ---------------------------------------------------------------------------- # +target_sources(${ILANG_LIB_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/verilog_rfmap.cc +) + diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc new file mode 100644 index 000000000..82dc4d8ab --- /dev/null +++ b/src/rfmap-in/verilog_rfmap.cc @@ -0,0 +1,659 @@ +/// \file verilog_rfmap.cc Verilog Refinement Map Handling +/// First pass : JSON -> rfmap object + +#include +#include +#include +#include + +#include + +#include "nlohmann/json.hpp" + +namespace ilang { +namespace rfmap { + +// return npos if no comments in +static size_t find_comments(const std::string& line) { + enum state_t { PLAIN, STR, LEFT } state, next_state; + state = PLAIN; + size_t ret = 0; + for (const auto& c : line) { + if (state == PLAIN) { + if (c == '/') + next_state = LEFT; + else if (c == '"') + next_state = STR; + else + next_state = PLAIN; + } else if (state == STR) { + if (c == '"' || c == '\n') + next_state = PLAIN; + // the '\n' case is in case we encounter some issue to find + // the ending of a string + else + next_state = STR; + } else if (state == LEFT) { + if (c == '/') { + ILA_CHECK(ret > 0); + return ret - 1; + } else + next_state = PLAIN; + } + state = next_state; + ++ret; + } + return std::string::npos; +} + +// load_json and remove the comment, if succeed return true +bool load_json(const std::string& fname, nlohmann::json& j) { + std::ifstream fin(fname); + + if (!fin.is_open()) { + ILA_ERROR << "Cannot read from file:" << fname; + return false; + } + + // remove the comments + std::string contents; + std::string line; + while (std::getline(fin, line)) { + auto comment_begin = find_comments(line); + if (comment_begin != std::string::npos) + contents += line.substr(0, comment_begin); + else + contents += line; + contents += "\n"; + } + j = nlohmann::json::parse(contents); +} // load_json + +RfExpr ParseRfMapExpr(const std::string & in) { + // TODO +} + +RfExpr ParseRfMapExprJson(nlohmann::json & in) { + return ParseRfMapExpr(in.get()); +} + +bool JsonRfmapParseCond(SingleVarMap & cond_map, nlohmann::json & json_array) { + assert(json_array.is_array()); + bool succ = true; + for (const auto & idx_array_pair : json_array.items()) { + succ = succ && idx_array_pair.value().is_array() && idx_array_pair.value().size() == 2; + if (!idx_array_pair.value().is_array() || idx_array_pair.value().size() != 2) + continue; + + RfExpr cond, mapping; + for (const auto & index_map_pair : idx_array_pair.value().items()) { + if (index_map_pair.key() == "0") { + cond = ParseRfMapExprJson(index_map_pair.value()); + } else if (index_map_pair.key() == "1") { + mapping = ParseRfMapExprJson(index_map_pair.value()); + } + } + assert(cond.get() != nullptr && mapping.get() != nullptr); + cond_map.cond_map.push_back(std::make_pair(cond,mapping)); + } // for each array_element + return succ; +} // JsonRfmapParseCond + +bool JsonRfmapParseMem(ExternalMemPortMap & mem_rfmap , nlohmann::json & json_obj) { + assert(json_obj.is_object()); + + bool succ = true; + + if (json_obj.contains("wen")) + succ = succ && JsonRfmapParseCond(mem_rfmap.wen_map, json_obj["wen"]); + if (json_obj.contains("waddr")) + succ = succ && JsonRfmapParseCond(mem_rfmap.waddr_map, json_obj["waddr"]); + if (json_obj.contains("wdata")) + succ = succ && JsonRfmapParseCond(mem_rfmap.wdata_map, json_obj["wdata"]); + if (json_obj.contains("ren")) + succ = succ && JsonRfmapParseCond(mem_rfmap.ren_map, json_obj["ren"]); + if (json_obj.contains("raddr")) + succ = succ && JsonRfmapParseCond(mem_rfmap.raddr_map, json_obj["raddr"]); + if (json_obj.contains("rdata")) + succ = succ && JsonRfmapParseCond(mem_rfmap.rdata_map, json_obj["rdata"]); + + return (succ && json_obj.contains("ren") && json_obj.contains("wen")); +} // JsonRfmapParseMem + +char inline to_space(char in) { return (in == '-' ? ' ' : in); } + +bool SecionNameRelaxedMatch(const std::string & in1, const std::string & in2) { + if(in1.length() != in2.length()) + return false; + for (size_t idx = 0; idx < in1.length(); ++ idx) { + if ( tolower(in1.at(idx)) != tolower(in2.at(idx)) && + (to_space(in1.at(idx)) != to_space(in2.at(idx))) ) + return false; + } + return true; +} // SecionNameRelaxedMatch + +nlohmann::json * GetJsonSection(nlohmann::json & in, const std::set & sec_names, bool allow_dup = false) { + nlohmann::json * ret = NULL; + if (!in.is_object()) + return NULL; + for (const auto & n : sec_names) { + for (const auto & n_v : in.items() ) { + if ( SecionNameRelaxedMatch(n_v.key(), n) ) { + + ILA_ERROR_IF(ret) << "Section " << n << " is duplicated."; + if (ret && !allow_dup) + return NULL; + + ret = &(in[n]); + } + } + } + return ret; +} // GetJsonSection + +bool JsonRfmapParseSingleSequence(OneBitSignalSequence & out, nlohmann::json & seq) { + + auto get_multipler = [](const std::string & in) -> unsigned { + if(in.length() < 2 ) + return 0; + if (in.at(0) != '*') + return 0; + auto sub = in.substr(1); + return StrToInt(sub,10); + }; + + if(!seq.is_array()) + return false; + OneBitSignalSequence tmp_seq; + bool the_last_encountered = false; + for(auto & elem : seq.items()){ + if (the_last_encountered) + return false; + auto & e = elem.value(); + if(!(e.is_number_unsigned() || e.is_array() || e.is_string())) + return false; + if(e.is_number_unsigned()) + tmp_seq.push_back(e.get()); + else if(e.is_array()) { + if(!JsonRfmapParseSingleSequence(tmp_seq, e)) + return false; + } else if (e.is_string()) { + // duplicate the tmp_sequence + auto mult = e.get(); + unsigned n_count = get_multipler(mult); + unsigned length = tmp_seq.size(); + if(length == 0 || n_count == 0) + return false; + for(unsigned iter = 0; iter & out, nlohmann::json & in) { + if(!in.is_object()) + return false; + + for(const auto & n_seq_pair : in.items()) { + const auto & name = n_seq_pair.key(); + auto & seq = n_seq_pair.value(); + if(!seq.is_array()) + return false; + if(IN(name, out)) + return false; + auto insert_ret = out.insert(std::make_pair(name, OneBitSignalSequence())); + // [pos (name, seq) , bool] + auto & seq_ref = insert_ret.first->second; + bool succ = JsonRfmapParseSingleSequence(seq_ref, seq); + if (!succ) + return false; + } + return true; +} // JsonRfmapParseSequence + +bool JsonRfmapParseClockFactor(std::map & out, nlohmann::json & in) { + if(!in.is_object()) + return false; + for(const auto & n_obj_pair : in.items()) { + const auto & n = n_obj_pair.key(); + auto & obj = n_obj_pair.value(); + if(IN(n, out)) + return false; + if(!obj.is_object()) + return false; + ClockSpecification::factor f; + auto * high = GetJsonSection(obj, {"high"}); + auto * low = GetJsonSection(obj, {"low"}); + auto * offset = GetJsonSection(obj, {"offset"}); + if(!(high && low)) + return false; + + if(high) { + if(!high->is_number_unsigned()) + return false; + f.high = high->get(); + } + + if(low) { + if(!low->is_number_unsigned()) + return false; + f.low = low->get(); + } + + if(offset) { + if(!offset->is_number_unsigned()) + return false; + f.offset = offset->get(); + } + out[n] = f; + } // end for + return true; +} // JsonRfmapParseClockFactor + +unsigned gcd(unsigned a, unsigned b) { + if(b==0) + return a; + return gcd(b, a%b); +} + +// least common multiplier +unsigned lcm(const std::vector & in) { + unsigned ans = in.at(0); + for(int i = 1; i < in.size(); ++i) { + ans = ((in.at(i)*ans)/gcd(in.at(i),ans)); + } + return ans; +} + +bool JsonRfmapConvertFactorToSeq( + const std::map & in, + std::map & out + ) { + if (in.size() == 0) + return false; + std::map seq_no_dup; + std::vector cycles; + for (const auto & n_factor_pair : in) { + const auto & n = n_factor_pair.first; + const auto & factor_obj = n_factor_pair.second; + auto n_cycle = factor_obj.high + factor_obj.low; + cycles.push_back(n_cycle); + seq_no_dup[n].resize(factor_obj.high,true); + seq_no_dup[n].insert(seq_no_dup.at(n).end(), factor_obj.low, false); + } // for each factor + + auto len = lcm(cycles); + for (const auto & n_factor_pair : in) { + const auto & n = n_factor_pair.first; + const auto & factor_obj = n_factor_pair.second; + auto n_cycle = factor_obj.high + factor_obj.low; + assert(len%n_cycle == 0); + auto n_copy = len/n_cycle; + auto offset = factor_obj.offset; + + unsigned idx = offset; + unsigned idx_copy = 0; + while(!(idx == offset && idx_copy == n_copy)) { + + out[n].push_back(seq_no_dup[n][idx]); + + if(idx + 1 == n_cycle) + ++ idx_copy; + idx = (idx + 1)%n_cycle; + } + assert(out[n].size() == len); + } + return true; +} // JsonRfmapConvertFactorToSeq + +// ------------------------------------------------------------------------------ + + +#define ERRIF(cond,str) do{ ILA_ERROR_IF(cond) << str ; if(cond) return; } while(false) +#define ENSURE(cond,str) ERRIF(!(cond), str) + +VerilogRefinementMap::VerilogRefinementMap + (const std::string & varmap_json_file, + const std::string & instcond_json_file) : ParseRfExprErrFlag(false) { + + // this is the first pass + nlohmann::json rf_vmap; + nlohmann::json rf_cond; + load_json(varmap_json_file, rf_vmap); + load_json(instcond_json_file, rf_cond); + // now json to -> Rfmap + { // state mapping + nlohmann::json * state_mapping = GetJsonSection(rf_vmap,{"state mapping"}); + ERRIF(state_mapping == NULL , "state var mapping is duplicated or missing"); + for (auto& i : state_mapping->items()) { + IlaStateVarMapping svmp; + auto sname = i.key(); // ila state name + if(i.value().is_string()) { + svmp.type = IlaStateVarMapping::StateVarMapType::SINGLE; + svmp.single_map.single_map = ParseRfMapExprJson(i.value()); + } else if (i.value().is_object()) { + // External Mem + svmp.type = IlaStateVarMapping::StateVarMapType::EXTERNMEM; + svmp.externmem_map.push_back(ExternalMemPortMap()); + + auto & extmem_ports = i.value(); + JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); + + } else if (i.value().is_array()) { + ERRIF( i.value().empty(), ("Empty list for " + sname) ); + bool are_memports = false; + if ( i.value().begin()->is_object() ) { + are_memports = true; + } else if (i.value().begin()->is_array() ) { + are_memports = false; + } else + ERRIF(true, "Expecting array of list or objects for" + sname); + + if (are_memports) { + svmp.type = IlaStateVarMapping::StateVarMapType::EXTERNMEM; + for (const auto & idx_obj_pair : i.value().items()) { + ENSURE( idx_obj_pair.value().is_object() , "Expecting array of objects for " + sname); + + svmp.externmem_map.push_back(ExternalMemPortMap()); + + auto & extmem_ports = idx_obj_pair.value(); + JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); + } + } else { + svmp.type = IlaStateVarMapping::StateVarMapType::CONDITIONAL; + JsonRfmapParseCond(svmp.single_map, i.value() ); + } + + } // if array of array / array of object + ILA_ERROR_IF( IN(sname, ila_state_var_map) ) << "ILA state var : " << sname << " has duplicated mapping"; + ila_state_var_map.emplace(sname, svmp); + } // for each state + } // state mapping + + { // interface map + nlohmann::json * rtl_if_map = GetJsonSection(rf_vmap,{"RTL interface connection"}); + ERRIF(rtl_if_map == nullptr, "`RTL interface connection` is duplicated or missing" ); + nlohmann::json * clock_domains = GetJsonSection(*rtl_if_map,{"CLOCK"},true); + nlohmann::json * reset_list = GetJsonSection(*rtl_if_map,{"RESET"},true); + nlohmann::json * nreset_list = GetJsonSection(*rtl_if_map,{"NRESET"},true); + nlohmann::json * reset_domains = GetJsonSection(*rtl_if_map,{"CUSTOMRESET"},true); + if(clock_domains) { + ENSURE(clock_domains->is_array() || clock_domains->is_string() || clock_domains->is_object(), + "clock specification in RTL interface connection should be string/list of string/map:string->list(string)"); + if(clock_domains->is_string()) + rtl_interface_connection.clock_domain_defs["default"].push_back(clock_domains->get()); + else if(clock_domains->is_array()){ + rtl_interface_connection.clock_domain_defs.insert( + std::make_pair(std::string("default"), clock_domains->get>())); + } else { // is_object + for(const auto & n_l_pair : clock_domains->items()) { + const auto & domain_name = n_l_pair.key(); + std::vector pins; + ENSURE(n_l_pair.value().is_string() || n_l_pair.value().is_array(), "expect string/array in RTL interface connection"); + if (n_l_pair.value().is_string()) { + pins.push_back(n_l_pair.value().get()); + } else { + pins = n_l_pair.value().get>(); + } + rtl_interface_connection.clock_domain_defs.emplace( + domain_name, pins + ); + } + } // if is_object + } // if (clock_domain) + + if(reset_list) { + if(reset_list->is_string()) + rtl_interface_connection.reset_pins.push_back(reset_list->get()); + else if(reset_list->is_array()){ + rtl_interface_connection.reset_pins = reset_list->get>(); + } + } + + if(nreset_list) { + if(nreset_list->is_string()) + rtl_interface_connection.nreset_pins.push_back(nreset_list->get()); + else if(nreset_list->is_array()){ + rtl_interface_connection.nreset_pins = nreset_list->get>(); + } + } + if(reset_domains) { + ENSURE(reset_domains->is_array() || reset_domains->is_string() || reset_domains->is_object(), + "clock specification in RTL interface connection should be string/list of string/map:string->list(string)"); + if(reset_domains->is_string()) + rtl_interface_connection.custom_reset_domain_defs["default"].push_back(reset_domains->get()); + else if(reset_domains->is_array()){ + rtl_interface_connection.custom_reset_domain_defs.insert( + std::make_pair(std::string("default"), reset_domains->get>())); + } else { // is_object + for(const auto & n_l_pair : reset_domains->items()) { + const auto & domain_name = n_l_pair.key(); + std::vector pins; + ENSURE(n_l_pair.value().is_string() || n_l_pair.value().is_array(), "expect string/array in RTL interface connection"); + if (n_l_pair.value().is_string()) { + pins.push_back(n_l_pair.value().get()); + } else { + pins = n_l_pair.value().get>(); + } + rtl_interface_connection.custom_reset_domain_defs.emplace( + domain_name, pins + ); + } + } // if is_object + } // if reset custom domain + } // interface map + + { // reset section parsing + nlohmann::json * reset_section = GetJsonSection(rf_vmap,{"reset"}); + if(reset_section) { + nlohmann::json * initial_state = GetJsonSection(*reset_section,{"initial-state"}); + nlohmann::json * cycle = GetJsonSection(*reset_section,{"cycles"}); + nlohmann::json * customreset = GetJsonSection(*reset_section,{"custom-seq"}); + if (initial_state) { + ENSURE(initial_state->is_object() , "initial state should be map:name->value"); + for(const auto & n_v_pair : initial_state->items()) { + const auto & sn = n_v_pair.key(); + RfExpr val = ParseRfMapExprJson(n_v_pair.value()); + ERRIF(IN(sn, reset_specification.initial_state), "duplicated sname for initial-state in reset" ); + reset_specification.initial_state[sn] = val; + } + } // initial state + + if (cycle) { + ENSURE(cycle->is_number_unsigned(), "cycles in reset should be unsigned integer"); + reset_specification.reset_cycle = cycle->get(); + } + + if (customreset) { + bool succ = JsonRfmapParseSequence(reset_specification.custom_reset_sequence, *customreset); + ENSURE(succ, "Custom Reset Sequence error!"); + } + + } // if reset_section + } // reset + + { // clock section + nlohmann::json * clock_section = GetJsonSection(rf_vmap,{"clock"}); + if (clock_section) { + nlohmann::json * factor_section = GetJsonSection(*clock_section, {"factor"}, true); + nlohmann::json * custom_section = GetJsonSection(*clock_section, {"custom"}, true); + ENSURE(factor_section || custom_section, "clock section must contain factor/custom field"); + ERRIF(factor_section && custom_section, "Cannot have both `factor` and `custom` section"); + if (custom_section) { + nlohmann::json * length = GetJsonSection(*custom_section, {"length"}); + ENSURE(length, "`length` field is needed for custom section"); + ENSURE(length->is_number_unsigned(), "length field must be unsigned integer"); + clock_specification.gcm_period = length->get(); + nlohmann::json * clocks = GetJsonSection(*custom_section, {"clocks"}); + ENSURE(clocks, "`clocks` field is needed for custom section"); + bool succ = JsonRfmapParseSequence(clock_specification.custom_clock_sequence, *clocks); + ENSURE(succ, "Custom Clock error!"); + } else { + // factor_section + bool succ = + JsonRfmapParseClockFactor(clock_specification.custom_clock_factor, *factor_section ); + succ = succ && + JsonRfmapConvertFactorToSeq( + clock_specification.custom_clock_factor, + clock_specification.custom_clock_sequence); + ENSURE(succ, "Custom clock sequence error"); + } + } // if clock section + } // clock + + { // uf section + nlohmann::json * func_section = GetJsonSection(rf_vmap,{"functions"}); + if (func_section) { + + } // if func_section + } // uf section + + + if (ParseRfExprErrFlag) { + // TODO: + } + + +} // VerilogRefinementMap::VerilogRefinementMap + +bool is_valid_id_name(const std::string & in) { + if(in.empty()) + return false; + if(!isalpha(in.at(0)) && in.at(0)!='_') + return false; + for(size_t idx = 1; idx < in.size(); ++ idx) + if (!isalnum(in.at(idx))) + return false; + return true; +} + +#undef ERRIF +#undef ENSURE +#define ERRIF(cond,str) do{ ILA_ERROR_IF(cond) << str ; if(cond) return false; } while(false) +#define ENSURE(cond,str) ERRIF(!(cond),str) + +bool VerilogRefinementMap::SelfCheckField() const { + // check module name + ERRIF(ParseRfExprErrFlag, "Error in parsing refinement expressions" ); + + if(!model_names.IlaModuleName.empty()) { + ERRIF( !is_valid_id_name(model_names.IlaModuleName), + "ILA instance name " + << model_names.IlaModuleName + << " is not valid"); + } + + if(!model_names.RtlModuleName.empty()) { + ERRIF( !is_valid_id_name(model_names.RtlModuleName), + "RTL instance name " + << model_names.RtlModuleName + << " is not valid"); + } + + for (const auto & n_map: ila_state_var_map) { + ENSURE( !(n_map.second.externmem_map.empty()) || + (n_map.second.single_map.single_map.get() != nullptr) || + !(n_map.second.single_map.cond_map.empty()) , "state var map cannot be empty for " + n_map.first); + ERRIF( !(n_map.second.externmem_map.empty()) && + (n_map.second.single_map.single_map.get() != nullptr) , "duplicate state var map for " + n_map.first ); + ERRIF( !(n_map.second.single_map.cond_map.empty()) && + (n_map.second.single_map.single_map.get() != nullptr) , "duplicate state var map for " + n_map.first ); + ERRIF( !(n_map.second.externmem_map.empty()) && + (!n_map.second.single_map.cond_map.empty()) , "duplicate state var map for " + n_map.first ); + } + + std::set custom_reset_seq_name; + std::set custom_clock_seq_name; + { // for reset, valid name, domain names are defs + unsigned seq_len = 0; + for (const auto & n_seq : reset_specification.custom_reset_sequence) { + ERRIF( !is_valid_id_name(n_seq.first), + "Custom reset sequence name " + << n_seq.first + << " is not valid" ); + ERRIF( IN(n_seq.first, custom_reset_seq_name) , "reset sequence name " + n_seq.first + "has been used multiple times" ); + + custom_reset_seq_name.insert(n_seq.first); + + ERRIF( n_seq.second.size() == 0, "Empty reset sequence for " + n_seq.first ); + if (seq_len == 0) + seq_len = n_seq.second.size(); + ERRIF( seq_len != reset_specification.reset_cycle , "Customized reset sequence does not match the cycle count" ); + + ERRIF( seq_len != n_seq.second.size(), "Reset sequence should be of same length" ); + } + } + + { // for clock, valid name, check no empty sequence, sequence of the same length + unsigned seq_len = 0; + for (const auto & n_seq : clock_specification.custom_clock_sequence) { + ERRIF( !is_valid_id_name(n_seq.first), + "Custom clock sequence name " + << n_seq.first + << " is not valid" ); + ERRIF( IN(n_seq.first, custom_clock_seq_name) , "clock sequence name " + n_seq.first + "has been used multiple times" ); + + custom_clock_seq_name.insert(n_seq.first); + + ERRIF( n_seq.second.size() == 0, "Empty clock sequence for " + n_seq.first ); + if (seq_len == 0) + seq_len = n_seq.second.size(); + ERRIF( seq_len != clock_specification.gcm_period, "Customized clock does not match the specified length requirement" ); + + ERRIF( seq_len != n_seq.second.size(), "Clock sequence should be of same length" ); + } + } + + { + for (const auto & clkd : custom_clock_seq_name) { + ERRIF( IN(clkd, custom_reset_seq_name) , "Name " + clkd + " has been used multiple times" ); + } + for (const auto & rstd : custom_reset_seq_name) { + ERRIF( IN(rstd, custom_clock_seq_name) , "Name " + rstd + " has been used multiple times" ); + } + } + + { // for each interface check domain names are good + for (const auto & n_clks : rtl_interface_connection.clock_domain_defs) { + ERRIF( !IN(n_clks.first, custom_clock_seq_name), "clock domain " + n_clks.first + " is not found" ); + } + for (const auto & n_rsts : rtl_interface_connection.custom_reset_domain_defs) { + ERRIF( !IN(n_rsts.first, custom_reset_seq_name), "reset domain " + n_rsts.first + " is not found" ); + } + } + + // check trackers, recorders, monitor names are okay + + { // GeneralVerilogMonitor, for ids are okay, no bad names + std::set monitor_names; + for (const auto & n_st : phase_tracker) { + ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); + ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); + monitor_names.insert(n_st.first); + } + for (const auto & n_st : value_recorder) { + ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); + ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); + monitor_names.insert(n_st.first); + } + for (const auto & n_st : customized_monitor) { + ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); + ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); + monitor_names.insert(n_st.first); + } + } + // no need to check for inst_cond +} // bool VerilogRefinementMap::SelfCheck() const + +#undef ERRIF +#undef ENSURE + +} // namespace rfmap +} // namespace ilang From 49089610ac35a1a5a9130a6dc2ac77b750a0dd34 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 29 Apr 2021 14:45:59 -0400 Subject: [PATCH 04/78] structure parse --- include/ilang/rfmap-in/verilog_rfmap.h | 8 +- src/rfmap-in/verilog_rfmap.cc | 388 ++++++++++++++++++++++++- 2 files changed, 387 insertions(+), 9 deletions(-) diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 9be9dfd07..4e0232cfe 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -125,7 +125,8 @@ struct GeneralVerilogMonitor { unsigned width; }; // VarDef - std::vector verilog_inline; + std::string verilog_inline; // handle concatnation/load from file etc + std::string verilog_append; // std::map var_defs; std::set var_uses; }; // GeneralVerilogMonitor @@ -159,6 +160,7 @@ struct PhaseTracker { using VarDef = GeneralVerilogMonitor::VarDef; // name to defs std::map var_defs; + std::map event_alias; std::vector rules; }; @@ -169,7 +171,7 @@ struct InstructionCompleteCondition{ enum class ConditionType {BOUND, SIGNAL} type; unsigned ready_bound; unsigned max_bound; - std::vector start_condition; + RfExpr start_condition; RfExpr ready_signal; }; // @@ -207,8 +209,6 @@ struct VerilogRefinementMap { VerilogRefinementMap(const std::string & varmap_json_file, const std::string & instcond_json_file); -private: - bool ParseRfExprErrFlag; }; // VerilogRefinementMap } // namespace ilang diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 82dc4d8ab..8b2f2384e 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -9,6 +9,7 @@ #include #include "nlohmann/json.hpp" +#include "interpreter.h" namespace ilang { namespace rfmap { @@ -69,8 +70,23 @@ bool load_json(const std::string& fname, nlohmann::json& j) { j = nlohmann::json::parse(contents); } // load_json + + +static bool ParseRfExprErrFlag = false; + RfExpr ParseRfMapExpr(const std::string & in) { // TODO + Vexp::Interpreter intp; + std::stringstream ss; + ss << in; + intp.switchInputStream(&ss); + try{ + intp.parse(); + return intp.GetAstRoot(); + } catch (verilog_expr::VexpException &e) { + ParseRfExprErrFlag = true; + } + return nullptr; } RfExpr ParseRfMapExprJson(nlohmann::json & in) { @@ -120,7 +136,7 @@ bool JsonRfmapParseMem(ExternalMemPortMap & mem_rfmap , nlohmann::json & json_ob return (succ && json_obj.contains("ren") && json_obj.contains("wen")); } // JsonRfmapParseMem -char inline to_space(char in) { return (in == '-' ? ' ' : in); } +char inline to_space(char in) { return ( (in == '-' || in == '_') ? ' ' : in); } bool SecionNameRelaxedMatch(const std::string & in1, const std::string & in2) { if(in1.length() != in2.length()) @@ -313,6 +329,150 @@ bool JsonRfmapConvertFactorToSeq( return true; } // JsonRfmapConvertFactorToSeq +#define ERRIF(cond, s) do { if(cond) return (s); } while(0) +#define ENSURE(cond, s) ERRIF(!(cond), (s)) +std::string JsonRfMapParseVarDefs(std::map & var_defs, nlohmann::json & def_field) { + + ENSURE(def_field.is_array(), "`defs` field should be list of [name, width, type]"); + for (auto & one_def : def_field) { + ENSURE(one_def.is_array(), "`defs` field should be list of [name, width, type]"); + auto pos = one_def.begin(); + + ENSURE( pos != one_def.end() && pos->is_string(), "`defs` field should be list of [name, width, type]"); + auto var_name = pos->get(); + ENSURE(!IN(var_name,var_defs), "var " + var_name + " has been defined"); + + ++ pos; + ENSURE( pos != one_def.end() && pos->is_number_unsigned(), "`defs` field should be list of [name, width, type]"); + var_defs[var_name].width = pos->get(); + ERRIF(var_defs[var_name].width == 0, "Definition of " + var_name + " has 0 width"); + + ++ pos; + ENSURE( pos != one_def.end() && pos->is_string(), "`defs` field should be list of [name, width, type]"); + auto tp = pos->get(); + ENSURE( SecionNameRelaxedMatch(tp, "reg") || SecionNameRelaxedMatch(tp, "wire") , "`defs` field should be list of [name, width, type (wire/reg)]" ); + + var_defs[var_name].type = SecionNameRelaxedMatch(tp, "reg") ? + GeneralVerilogMonitor::VarDef::var_type::REG : + GeneralVerilogMonitor::VarDef::var_type::WIRE; + ++ pos; + ENSURE( pos == one_def.end() , "`defs` expects 3-element tuple" ); + } + return ""; +} + +std::string JsonRfmapParsePhaseTracker(PhaseTracker & tracker, nlohmann::json & monitor) { + auto * event_alias = GetJsonSection(monitor, {"event-alias"}); + auto * rules = GetJsonSection(monitor, {"rules"}); + auto * aux_var = GetJsonSection(monitor, {"aux-var"}); + ERRIF(rules == NULL, "`phase tracker` needs `rules` field"); + if(event_alias) { + ERRIF(!event_alias->is_object(), "`event-alias` expects map:name->expr" ); + for (auto & name_val_pair : event_alias->items()) { + const auto & vn = name_val_pair.key(); + ERRIF(IN(vn,tracker.event_alias), "`"+vn+"` is already defined."); + ERRIF(!name_val_pair.value().is_string(), "expecting string in event-alias"); + tracker.event_alias.emplace(vn, ParseRfMapExprJson(name_val_pair.value())); + } + } + + if (aux_var) { + auto errmsg = JsonRfMapParseVarDefs(tracker.var_defs, *aux_var); + ENSURE(errmsg.empty(), errmsg); + } + + assert(rules); + ENSURE(rules->is_array(), "`rules` field should be list of objects"); + for(auto & stage : *rules) { + ENSURE(rules->is_object(), "`rules` field should be list of objects"); + auto * enter = GetJsonSection(stage, {"enter"}); + auto * exit = GetJsonSection(stage, {"exit"}); + auto * stage_name = GetJsonSection(stage, {"name"}); + ENSURE(enter && exit, "`rules` object must contain `enter` and `exit` events"); + ENSURE(enter->is_object(), "`enter` should contain `event` and (optional) `action`"); + ENSURE(exit->is_object(), "`exit` should contain `event` and (optional) `action`"); + auto * enter_event = GetJsonSection(*enter, {"event"}); + auto * exit_event = GetJsonSection(*exit, {"event"}); + auto * enter_action = GetJsonSection(*enter, {"action"}); + auto * exit_action = GetJsonSection(*exit, {"action"}); + ENSURE(enter_event, "`enter` should contain `event` and (optional) `action`"); + ENSURE(exit_event, "`exit` should contain `event` and (optional) `action`"); + ENSURE(enter_event->is_string(), "`enter` -> `event` should be a string"); + ENSURE(exit_event->is_string(), "`exit` -> `event` should be a string"); + + tracker.rules.push_back(PhaseTracker::Rule()); + auto & ws = tracker.rules.back(); + if(stage_name) { + ENSURE(stage_name->is_string(), "`name` of a phase should be string"); + ws.stage_name = stage_name->get(); + } + ws.enter_rule = ParseRfMapExprJson(*enter_event); + ws.exit_rule = ParseRfMapExprJson(*exit_event); + + if (enter_action) { + ENSURE(enter_action->is_string(), "`action` should be a string"); + auto action_str = enter_action->get(); + auto actions = Split(action_str, ";"); + for(auto & a : actions) { + StrTrim(a); + if(a.empty()) + continue; + auto pos = a.find("<="); + ERRIF(pos == std::string::npos, "`action` should be `LHS <= RHS ; ...`"); + auto LHS = a.substr(0,pos); + auto RHS = a.substr(pos+2); + PhaseTracker::Assignment assign; + StrTrim(LHS); + assign.LHS = LHS; + assign.RHS = ParseRfMapExpr(RHS); + ws.enter_action.push_back(assign); + } // for each action + } // if (enter_action) + + if (exit_action) { + ENSURE(exit_action->is_string(), "`action` should be a string"); + auto action_str = exit_action->get(); + auto actions = Split(action_str, ";"); + for(auto & a : actions) { + StrTrim(a); + if(a.empty()) + continue; + auto pos = a.find("<="); + ERRIF(pos == std::string::npos, "`action` should be `LHS <= RHS ; ...`"); + auto LHS = a.substr(0,pos); + auto RHS = a.substr(pos+2); + PhaseTracker::Assignment assign; + StrTrim(LHS); + assign.LHS = LHS; + assign.RHS = ParseRfMapExpr(RHS); + ws.exit_action.push_back(assign); + } // for each action + } // exit_action + } // for each stage + + return ""; +} + +std::string JsonRfmapParseValueRecorder(ValueRecorder & tracker, nlohmann::json & monitor) { + auto * cond = GetJsonSection(monitor, {"condition", "cond"}); + auto * val = GetJsonSection(monitor,{"value", "val"}); + auto * width = GetJsonSection(monitor, {"width", "w"}); + ENSURE(cond && cond->is_string(), "`cond` field should be a string"); + ENSURE(val && val->is_string(), "`val` field should be a string"); + tracker.condition = ParseRfMapExprJson(*cond); + tracker.value = ParseRfMapExprJson(*val); + if(width && width->is_number_unsigned()) { + tracker.width = width->get(); + } + else + tracker.width = 0; + return ""; +} + +#undef ENSURE +#undef ERRIF + + // ------------------------------------------------------------------------------ @@ -321,8 +481,10 @@ bool JsonRfmapConvertFactorToSeq( VerilogRefinementMap::VerilogRefinementMap (const std::string & varmap_json_file, - const std::string & instcond_json_file) : ParseRfExprErrFlag(false) { + const std::string & instcond_json_file) { + ParseRfExprErrFlag = false; + // this is the first pass nlohmann::json rf_vmap; nlohmann::json rf_cond; @@ -511,16 +673,218 @@ VerilogRefinementMap::VerilogRefinementMap { // uf section nlohmann::json * func_section = GetJsonSection(rf_vmap,{"functions"}); if (func_section) { - + ENSURE(func_section->is_object(), "Expect `functions` to be map:name->list of invocation "); + for(auto & n_invocation_pair : func_section->items()) { + const auto & n = n_invocation_pair.key(); + auto & invocations = n_invocation_pair.value(); + auto ret = uf_application.insert(std::make_pair(n, UninterpretedFunctionApplication())); + auto & apply_obj = ret.first->second; // point to the UninterpretedFunctionApplication object + ENSURE(invocations.is_array(), "Expect `functions` to be map:name->list of invocation"); + for (auto & elem : invocations) { + ENSURE(elem.is_object(), "Expect `functions` to be map:name->list of invocation(object)"); + auto * result = GetJsonSection(elem,{"result"}); + auto * arg = GetJsonSection(elem, {"arg"}); + ENSURE(result && arg, "Expect invocation object has `result` and `arg` field"); + ENSURE(result->is_string(), "Expect type string in `result` field of invocation object"); + ENSURE(arg->is_array(), "Expect type list(string) in `arg` field of invocation object"); + apply_obj.func_applications.push_back(UninterpretedFunctionApplication::Apply()); + auto & curr_invocation = apply_obj.func_applications.back(); + curr_invocation.result_map = ParseRfMapExprJson(*result); + std::vector argList = arg->get>(); + for (const auto & arg : argList) + curr_invocation.arg_map.push_back(ParseRfMapExpr(arg)); + } + } // for each invocation } // if func_section } // uf section - + { // additional mapping & assumptions + nlohmann::json * additonal_section = GetJsonSection(rf_vmap,{"additional mapping"}); + if(additonal_section) { + ENSURE(additonal_section->is_array(), "`additional mapping` section should be a list of string"); + for(auto & pstr : *additonal_section) { + ENSURE(pstr.is_string(), "`additional mapping` section should be a list of string"); + additional_mapping.push_back(ParseRfMapExprJson(pstr)); + } + } // if additional mapping + + nlohmann::json * assumption_section = GetJsonSection(rf_vmap,{"assumptions"}); + if(assumption_section) { + ENSURE(assumption_section->is_array(), "`assumptions` section should be a list of string"); + for(auto & pstr : *assumption_section) { + ENSURE(pstr.is_string(), "`assumptions` section should be a list of string"); + assumptions.push_back(ParseRfMapExprJson(pstr)); + } + } + } // additional mapping & assumptions + + { // phase tracker, value recorder, customized ones + nlohmann::json * monitor_section = GetJsonSection(rf_vmap,{"monitor"}); + if(monitor_section) { + ENSURE(monitor_section->is_object(), "`monitor` section should be a map"); + for(auto & name_monitor_pair : monitor_section->items()) { + auto name = name_monitor_pair.key(); + + ERRIF(IN(name,customized_monitor), "monitor `"+name+"` has been defined."); + ERRIF(IN(name,phase_tracker), "monitor `"+name+"` has been defined."); + ERRIF(IN(name,value_recorder), "monitor `"+name+"` has been defined."); + + auto & monitor = name_monitor_pair.value(); + auto * template_field = GetJsonSection(monitor,{"template"}); + if(template_field) { + ENSURE(template_field->is_string(), "`template` field should be string"); + auto template_name = template_field->get(); + if(SecionNameRelaxedMatch(template_name,"phase tracker")) { + phase_tracker.emplace(name, PhaseTracker()); + std::string errmsg = JsonRfmapParsePhaseTracker(phase_tracker.at(name), monitor); + ENSURE(errmsg.empty(), errmsg); + } else if (SecionNameRelaxedMatch(template_name,"value recorder")) { + value_recorder.emplace(name, ValueRecorder()); + std::string errmsg = JsonRfmapParseValueRecorder(value_recorder.at(name), monitor); + ENSURE(errmsg.empty(), errmsg); + } else { + ERRIF(true, "template name `" +template_name+"` is not recognized." ); + } + // end if has template field + } else { + customized_monitor.emplace(name, GeneralVerilogMonitor()); + auto & mnt_ref = customized_monitor.at(name); + { // inline verilog + // has no template + auto * verilog_field = GetJsonSection(monitor,{"verilog"}); + auto * verilog_file_field = GetJsonSection(monitor,{"verilog-from-file"}); + + ERRIF(verilog_field && verilog_file_field, "`verilog` or `verilog-from-file` fields are mutual exclusive"); + + if(verilog_field) { + if( verilog_field->is_string() ) { + mnt_ref.verilog_inline = verilog_field->get(); + } else { + ENSURE(verilog_field->is_array() , "`verilog` field should be a list of string" ); + for (auto & ps : *verilog_field) { + ENSURE(ps.is_string(), "`verilog` field should be a list of string"); + mnt_ref.verilog_inline += ps.get() + "\n"; + } + } + } else if (verilog_file_field) { + ENSURE(verilog_file_field->is_string(), "`verilog-from-file` expects a string (file name)"); + auto fname = verilog_file_field->get(); + std::ifstream fin(fname); + ENSURE(fin.is_open(), "Cannot read from " + fname); + { + std::stringstream buffer; + buffer << fin.rdbuf(); + mnt_ref.verilog_inline = buffer.str(); + } + } // verilog_file_field : from file + } // inline verilog + + { // append verilog outside the module + // has no template + auto * verilog_field = GetJsonSection(monitor,{"append-verilog"}); + auto * verilog_file_field = GetJsonSection(monitor,{"append-verilog-from-file"}); + + ERRIF(verilog_field && verilog_file_field, "`append-verilog` or `append-verilog-from-file` fields are mutual exclusive"); + + if(verilog_field) { + if( verilog_field->is_string() ) { + mnt_ref.verilog_append = verilog_field->get(); + } else { + ENSURE(verilog_field->is_array() , "`append-verilog` field should be a list of string" ); + for (auto & ps : *verilog_field) { + ENSURE(ps.is_string(), "`append-verilog` field should be a list of string"); + mnt_ref.verilog_append += ps.get() + "\n"; + } + } + } else if (verilog_file_field) { + ENSURE(verilog_file_field->is_string(), "`append-verilog-from-file` expects a string (file name)"); + auto fname = verilog_file_field->get(); + std::ifstream fin(fname); + ENSURE(fin.is_open(), "Cannot read from " + fname); + { + std::stringstream buffer; + buffer << fin.rdbuf(); + mnt_ref.verilog_append = buffer.str(); + } + } // append-verilog_file_field : from file + } // verilog_append verilog + + auto * ref_field = GetJsonSection(monitor,{"refs"}); + if (ref_field) + { // refs + ENSURE(ref_field->is_array(), "`refs` field should be a list of string"); + for ( auto & p : *ref_field) { + ENSURE(p.is_string(), "`refs` field should be a list of string"); + auto var_name = p.get(); + ILA_WARN_IF(IN(var_name, mnt_ref.var_uses)) << "`" + var_name+"` has been declared already"; + mnt_ref.var_uses.insert( p.get() ); + } + } // if ref_field + + auto * def_field = GetJsonSection(monitor,{"defs"}); + if (def_field) + { // defs + auto err_msg = JsonRfMapParseVarDefs( mnt_ref.var_defs , *def_field); + ENSURE(err_msg.empty(), err_msg); + } // if def_field + } // else if it is verilog monitor (general) + } // for each monitor + } // if has monitor field + } // monitor block + // ---------------- inst_cond ------------------------ // + { + auto * instrs = GetJsonSection(rf_cond, {"instructions"}); + auto * invariants = GetJsonSection(rf_cond, {"global invariants"}); + if(instrs) { + ENSURE(instrs->is_array(), "`instructions` should be array of object"); + for(auto & instr : *instrs) { + ENSURE(instr.is_object() , "`instructions` should be array of object"); + auto * instr_name = GetJsonSection(instr, {"instruction"}); + auto * ready_bnd = GetJsonSection(instr, {"ready-bound"}); + auto * ready_signal = GetJsonSection(instr, {"ready-signal"}); + auto * max_bound = GetJsonSection(instr, {"max-bound"}); + auto * start_condition = GetJsonSection(instr, {"start-condition"}); + ENSURE(instr_name && instr_name->is_string(), "`instruction` field should be a string"); + ERRIF(ready_bnd && ready_signal, "`ready bound` and `ready signal` are mutual exclusive"); + ENSURE(ready_bnd || ready_signal , "You must specify one of `ready bound` and `ready signal`"); + auto iname = instr_name->get(); + inst_complete_cond.emplace(iname,InstructionCompleteCondition()); + auto & ws = inst_complete_cond.at(iname); + + ws.instruction_name = iname; + if(ready_bnd) { + ENSURE(ready_bnd->is_number_unsigned(), "`ready-bound` should be an unsigned number"); + ws.ready_bound = ready_bnd->get(); + } else { // ready_signal + ENSURE(ready_signal->is_string(), "`ready-signal` should be a string"); + ws.ready_signal = ParseRfMapExprJson(*ready_signal); + } + + if(max_bound) { + ENSURE(max_bound->is_number_unsigned(), "`max_bound` should be an unsigned number"); + ws.max_bound = max_bound->get(); + } + if (start_condition) { + ENSURE(start_condition->is_string(), "`start_condition` should be a string"); + ws.start_condition = ParseRfMapExprJson(*start_condition); + } + } // for each instr` + } // if instrs + + if (invariants) { + ENSURE(invariants->is_array(), "`global-invariants` should be an array of strings"); + for(auto & inv : *invariants) { + ENSURE(inv.is_string(), "`global-invariants` should be an array of strings"); + global_invariants.push_back(ParseRfMapExprJson(inv)); + } + } // if invariant + } // inst cond + + if (ParseRfExprErrFlag) { // TODO: } - } // VerilogRefinementMap::VerilogRefinementMap bool is_valid_id_name(const std::string & in) { @@ -633,10 +997,19 @@ bool VerilogRefinementMap::SelfCheckField() const { { // GeneralVerilogMonitor, for ids are okay, no bad names std::set monitor_names; + std::set var_def_names; for (const auto & n_st : phase_tracker) { ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); monitor_names.insert(n_st.first); + for (const auto & var_def : n_st.second.event_alias ) { + ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); + var_def_names.insert(var_def.first); + } + for (const auto & var_def : n_st.second.var_defs ) { + ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); + var_def_names.insert(var_def.first); + } } for (const auto & n_st : value_recorder) { ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); @@ -647,6 +1020,11 @@ bool VerilogRefinementMap::SelfCheckField() const { ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); monitor_names.insert(n_st.first); + + for (const auto & var_def : n_st.second.var_defs ) { + ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); + var_def_names.insert(var_def.first); + } } } // no need to check for inst_cond From 10caa7e17853f575608577a50a3dbf6bebaceb9e Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 12 May 2021 18:24:22 -0400 Subject: [PATCH 05/78] add array addr width extract --- src/verilog-in/verilog_analysis.cc | 23 +++++++++++--- test/t_verilog_analysis.cc | 34 +++++++++++++++++++++ test/unit-data/verilog_sample/range-array.v | 25 +++++++++++++++ 3 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 test/unit-data/verilog_sample/range-array.v diff --git a/src/verilog-in/verilog_analysis.cc b/src/verilog-in/verilog_analysis.cc index d1d5ba604..cef16633a 100644 --- a/src/verilog-in/verilog_analysis.cc +++ b/src/verilog-in/verilog_analysis.cc @@ -635,7 +635,7 @@ SignalInfoBase VerilogAnalyzer::get_signal( const std::string& net_name, const std::map* const width_info) const { SignalInfoBase bad_signal("", "", 0, hierarchical_name_type::NONE, - vlg_loc_t()); + vlg_loc_t(), 0); if (_bad_state_return()) return bad_signal; @@ -834,6 +834,15 @@ bool VerilogAnalyzer::get_hierarchy_from_full_name( // ------------------- signal info base ---------------------------------- +unsigned addr_range_to_width(ast_identifier id, const std::string& full_name, + const VerilogAnalyzer* _ana, int width) { + if(id->range_or_idx == ID_HAS_RANGES && id->ranges && id->ranges->items > 0) { + ast_range * range = (ast_range *) id->ranges->head; + return range_to_width(range, full_name, _ana, width); + } + return 0; +} + unsigned range_to_width(ast_range* range, const std::string& full_name, const VerilogAnalyzer* _ana, int width = -1) { if (range == NULL) @@ -878,7 +887,9 @@ SignalInfoPort::SignalInfoPort( : (IN_p(full_name, width_info) ? width_info->at(full_name) : -1)), - tp, VerilogAnalyzer::Meta2Loc(def->meta)), + tp, VerilogAnalyzer::Meta2Loc(def->meta), + 0 // not an array + ), _def(def) { // ILA_WARN_IF( def->range == NULL ) << "Verilog Analyzer: // signal "<< full_name <<" has no range."; ILA_WARN_IF(_width == 0) @@ -898,7 +909,9 @@ SignalInfoReg::SignalInfoReg(ast_reg_declaration* def, : (IN_p(full_name, width_info) ? width_info->at(full_name) : -1)), - tp, VerilogAnalyzer::Meta2Loc(def->meta)), + tp, VerilogAnalyzer::Meta2Loc(def->meta), + addr_range_to_width(def->identifier, full_name, _ana, -1) + ), _def(def) { ILA_WARN_IF(_width == 0) << "Verilog Analyzer is not able to determine the width of signal:" @@ -917,7 +930,9 @@ SignalInfoWire::SignalInfoWire( : (IN_p(full_name, width_info) ? width_info->at(full_name) : -1)), - tp, VerilogAnalyzer::Meta2Loc(def->meta)), + tp, VerilogAnalyzer::Meta2Loc(def->meta), + 0 // not an array + ), _def(def) { ILA_WARN_IF(_width == 0) << "Verilog Analyzer is not able to determine the width of signal:" diff --git a/test/t_verilog_analysis.cc b/test/t_verilog_analysis.cc index 60ae60bfb..61d3b0cd2 100644 --- a/test/t_verilog_analysis.cc +++ b/test/t_verilog_analysis.cc @@ -81,9 +81,26 @@ TEST(TestVerilogAnalysis, Include) { << "End loc of m1:" << va.get_endmodule_loc("m1"); } +TEST(TestVerilogAnalysis, RangeAnalysisArray) { +#define IS_ARRAY_WIDTH(n, w) EXPECT_EQ(va.get_signal("m1." n).get_addr_width(), w) + { + VerilogInfo va( + VerilogInfo::path_vec_t( + {std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/verilog_sample/"}), + VerilogInfo::path_vec_t({std::string(ILANG_TEST_SRC_ROOT) + + "/unit-data/verilog_sample/range-array.v"}), + "m1"); + IS_ARRAY_WIDTH("r12", 8-1); + IS_ARRAY_WIDTH("r22", 8-1); + IS_ARRAY_WIDTH("r14", 9-1); + IS_ARRAY_WIDTH("r24", 7-1); + } +} + TEST(TestVerilogAnalysis, RangeAnalysis) { #define IS_WIDTH(n, w) EXPECT_EQ(va.get_signal("m1." n).get_width(), w) +#define NOT_ARRAY(n) EXPECT_EQ(va.get_signal("m1." n).get_addr_width(), 0) { // test 1 VerilogInfo va( @@ -97,22 +114,39 @@ TEST(TestVerilogAnalysis, RangeAnalysis) { IS_WIDTH("r2", 8); IS_WIDTH("r3", 8); IS_WIDTH("r4", 8); + NOT_ARRAY("r1"); + NOT_ARRAY("r2"); + NOT_ARRAY("r3"); + NOT_ARRAY("r4"); IS_WIDTH("r12", 8); IS_WIDTH("r22", 8); IS_WIDTH("r32", 8); IS_WIDTH("r42", 8); + NOT_ARRAY("r12"); + NOT_ARRAY("r22"); + NOT_ARRAY("r32"); + NOT_ARRAY("r42"); IS_WIDTH("r14", 9); IS_WIDTH("r24", 7); IS_WIDTH("r34", 8); IS_WIDTH("r44", 8); + NOT_ARRAY("r14"); + NOT_ARRAY("r24"); + NOT_ARRAY("r34"); + NOT_ARRAY("r44"); IS_WIDTH("rm", 2); IS_WIDTH("a", 1); // F IS_WIDTH("b", 1); // F IS_WIDTH("c", 2); // F IS_WIDTH("d", 1); // F + NOT_ARRAY("rm"); + NOT_ARRAY("a"); // F + NOT_ARRAY("b"); // F + NOT_ARRAY("c"); // F + NOT_ARRAY("d"); // F } // end of test1 { // test 2 VerilogInfo va( diff --git a/test/unit-data/verilog_sample/range-array.v b/test/unit-data/verilog_sample/range-array.v new file mode 100644 index 000000000..8416b8144 --- /dev/null +++ b/test/unit-data/verilog_sample/range-array.v @@ -0,0 +1,25 @@ + +module range( clk, rst, r1, r2); + +`include "rangeheader2.v" + +input clk; +input rst; +output [`R1:0] r1; +output [`R2-1:0] r2; + +wire [`R3:0] r3; +wire [`R4] r4; + +reg [`R12:0] r12 [`R12-1:0]; +reg [`R22-1:0] r22 [`R22-2:0]; +wire [`R32:0] r32; +wire [`R42] r42; + +reg [`R14:0] r14 [`R14-1:0]; +reg [`R24-1:0] r24 [`R24-2:0]; +wire [`R34:0] r34; +wire [`R44] r44; + + +endmodule From 89ac6e204abf846f552890cc5fe1fdd2abafd699 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 12 May 2021 18:27:16 -0400 Subject: [PATCH 06/78] fix update --- .../verilog-in/verilog_analysis_wrapper.h | 9 +++++++-- src/verilog-in/verilog_analysis.cc | 20 ++++++++++--------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/ilang/verilog-in/verilog_analysis_wrapper.h b/include/ilang/verilog-in/verilog_analysis_wrapper.h index 11d5f52c3..089ae2349 100644 --- a/include/ilang/verilog-in/verilog_analysis_wrapper.h +++ b/include/ilang/verilog-in/verilog_analysis_wrapper.h @@ -122,11 +122,15 @@ class SignalInfoBase { const VerilogAnalyzerBase::hierarchical_name_type _type; /// its location of definition const VerilogAnalyzerBase::vlg_loc_t _loc; + /// addr width of the array, 0 if not array + const unsigned _addr_width; public: /// --------------------- ACCESSORS ------------------- /// /// Return the width of the signal virtual unsigned get_width() const { return _width; } + /// Return the addrwidth of the signal + virtual unsigned get_addr_width() const {return _addr_width; } /// Whether is a IO signal virtual bool is_io_sig() const { return VerilogAnalyzerBase::is_io_sig(_type); @@ -164,8 +168,9 @@ class SignalInfoBase { /// --------------------- ACCESSORS ------------------- /// SignalInfoBase(const std::string& n, const std::string& h, unsigned w, const VerilogAnalyzerBase::hierarchical_name_type& typ, - const VerilogAnalyzerBase::vlg_loc_t& loc) - : _name(n), _hierarchical_name(h), _width(w), _type(typ), _loc(loc) {} + const VerilogAnalyzerBase::vlg_loc_t& loc, + unsigned aw) + : _name(n), _hierarchical_name(h), _width(w), _type(typ), _loc(loc), _addr_width(aw) {} /// implicit copy constructor }; // class SignalInfoBase diff --git a/src/verilog-in/verilog_analysis.cc b/src/verilog-in/verilog_analysis.cc index cef16633a..bf2021496 100644 --- a/src/verilog-in/verilog_analysis.cc +++ b/src/verilog-in/verilog_analysis.cc @@ -834,15 +834,6 @@ bool VerilogAnalyzer::get_hierarchy_from_full_name( // ------------------- signal info base ---------------------------------- -unsigned addr_range_to_width(ast_identifier id, const std::string& full_name, - const VerilogAnalyzer* _ana, int width) { - if(id->range_or_idx == ID_HAS_RANGES && id->ranges && id->ranges->items > 0) { - ast_range * range = (ast_range *) id->ranges->head; - return range_to_width(range, full_name, _ana, width); - } - return 0; -} - unsigned range_to_width(ast_range* range, const std::string& full_name, const VerilogAnalyzer* _ana, int width = -1) { if (range == NULL) @@ -875,6 +866,17 @@ unsigned range_to_width(ast_range* range, const std::string& full_name, return analyzed_width; } + +unsigned addr_range_to_width(ast_identifier id, const std::string& full_name, + const VerilogAnalyzer* _ana, int width) { + if(id->range_or_idx == ID_HAS_RANGES && id->ranges && id->ranges->items > 0) { + ast_range * range = (ast_range *) id->ranges->head; + return range_to_width(range, full_name, _ana, width); + } + return 0; +} + + SignalInfoPort::SignalInfoPort( ast_port_declaration* def, const std::string& full_name, VerilogAnalyzerBase::hierarchical_name_type tp, From 92285566acd9871459897a631a0b8c4670bc71cc Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 12 May 2021 18:28:51 -0400 Subject: [PATCH 07/78] rfmap wip --- include/ilang/rfmap-in/rfmap_typecheck.h | 118 +++++++++++++++++++++++ include/ilang/rfmap-in/verilog_rfmap.h | 21 ++-- include/ilang/vtarget-out/vtarget_gen.h | 66 +++++-------- src/rfmap-in/CMakeLists.txt | 1 + src/rfmap-in/rfmap_typecheck.cc | 103 ++++++++++++++++++++ src/rfmap-in/verilog_rfmap.cc | 60 ++++++------ src/vtarget-out/single_target.cc | 2 +- 7 files changed, 288 insertions(+), 83 deletions(-) create mode 100644 include/ilang/rfmap-in/rfmap_typecheck.h create mode 100644 src/rfmap-in/rfmap_typecheck.cc diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h new file mode 100644 index 000000000..ab2670206 --- /dev/null +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -0,0 +1,118 @@ +/// \file Verilog Verification Refinement Map Interface Class +/// Type checker +/// --- Hongce Zhang (hongcez@princeton.edu) + + +#ifndef RFMAP_TYPECHECK_H__ +#define RFMAP_TYPECHECK_H__ + +#include +#include + +namespace ilang { +namespace rfmap { + +// define type +struct RfMapType { + enum class TYPE {BV, MEM} type; + unsigned width; + unsigned addr_width; + unsigned data_width; +}; + +// define annotation +namespace verilog_expr{ +class TypeAnnotation : public AbstractInternalInfo { + public: + enum class VARTYPE { + NOTVAR, /*also unknown type*/ + ILAS /*state var*/, + ILAI, /*ila input*/ + RTLV, /*rtl signal*/ + PHASE, /*stage name*/ + DEFINE_VAR, /*defined vars*/ + DELAY, /*inline delay*/ + VALUE_RECORDER, /*inline value recorder*/ + INTERNAL /* those already translated: + like __CYCLE_CNT__, __START__*/ }; + + // allow instantiation + virtual void should_not_instantiate() override {} + + VARTYPE var_ref_type; + RfMapType type; + + unsigned width() { return type.type == RfMapType::BV ? width : data_width; } +}; // TypeAnnotation +} + +struct InternalSignals { + RfExpr start; + RfExpr issue; + RfExpr iend; + RfExpr cycle_cnt; + // and others if necessary + // __STARTED__ +}; + +// type infer rules +// + +// provide function: + +// try_find_ila_type -> TypeAnnotation +// try find_rtl_type -> TypeAnnotation +// type annotation & checking & replacing : all-together + +struct TypedVerilogRefinementMap : public VerilogRefinementMap { + + // type definitions + typedef std::function var_typecheck_t; + using VarDef = GeneralVerilogMonitor::VarDef; + + // constructor + TypedVerilogRefinementMap( + const std::string & varmap_json_file, + const std::string & instcond_json_file, + var_typecheck_t ila_var_type_check, + var_typecheck_t rtl_var_type_check + ); + +// references +// - named defined vars with type +// - named stages with type bit 1 + +// additional delayed + std::map aux_delays; +// additional value_recoder added to value_recorder + + // defined vars + // 1. first round : only explict ones + // this is to collect information before running the + // the AST type checks + // 2. second round : will be populated by the AST type checks + // so this can NOT be used in creating vars stage? + // Var creating stage should deal with separate ones + std::map all_var_def_types; + // this should include phase-tracker (m,v,alias) + // ... ? + +protected: + void CollectInternallyDefinedVars(); + // internal signals + InternalSignals internals_; + +private: + + // help with naming + unsigned counter; + std::string new_id(); + +}; + +} // namespace rfmap +} // namespace ilang + +#endif // RFMAP_TYPECHECK_H__ + + diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 4e0232cfe..7e7a6e709 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -1,5 +1,5 @@ /// \file Verilog Verification Refinement Map Interface Class -/// External Refinement Map Interface Classe +/// External Refinement Map Interface Class /// --- Hongce Zhang (hongcez@princeton.edu) @@ -28,11 +28,6 @@ namespace rfmap { typedef verilog_expr::VExprAst::VExprAstPtr RfExpr; -/// \class Module Name section (optional) -struct ModelNames { - std::string IlaModuleName; - std::string RtlModuleName; -}; /* "ILA_mem_state_var_2" : { // case 4 : external RTL memory @@ -61,7 +56,7 @@ struct ExternalMemPortMap { SingleVarMap rdata_map; }; // struct ExternalMemPortMap -struct IlaStateVarMapping { +struct IlaVarMapping { enum class StateVarMapType { SINGLE, CONDITIONAL, @@ -71,7 +66,7 @@ struct IlaStateVarMapping { SingleVarMap single_map; /// the standard 6-port map std::vector externmem_map; -}; // struct IlaStateVarMapping +}; // struct IlaVarMapping struct RtlInterfaceMapping{ /// "CLOCK" : { "clkA" : "wclk", "clkB" : ["rclk", "clk"] } @@ -145,8 +140,8 @@ struct SignalDelay { struct PhaseTracker { struct Assignment { - std::string LHS; - RfExpr RHS; + std::string LHS; // a state name + RfExpr RHS; // a rhs expression }; typedef std::vector Action; struct Rule { @@ -177,10 +172,10 @@ struct InstructionCompleteCondition{ struct VerilogRefinementMap { // ---------------------- varmap ------------------------------- // - /// model name section (optional) - ModelNames model_names; /// State mapping section - std::map ila_state_var_map; + std::map ila_state_var_map; + /// State mapping section + std::map ila_input_var_map; /// RTL interface connection specification RtlInterfaceMapping rtl_interface_connection; /// reset section diff --git a/include/ilang/vtarget-out/vtarget_gen.h b/include/ilang/vtarget-out/vtarget_gen.h index f67548cfe..980b247d7 100644 --- a/include/ilang/vtarget-out/vtarget_gen.h +++ b/include/ilang/vtarget-out/vtarget_gen.h @@ -26,11 +26,10 @@ class VlgVerifTgtGenBase { // ----------- Verification Settings -------------- // /// Type of the backend: - /// CoSA, JasperGold, CHC for chc solver, AIGER for abc + /// Pono, JasperGold, CHC for chc solver, AIGER for abc // YOSYS is for invariant synthesis use typedef enum { NONE = 0, - COSA = 1, JASPERGOLD = 2, YOSYS = 128, // 10000000 CHC = YOSYS + 8, // 10001000 @@ -38,7 +37,7 @@ class VlgVerifTgtGenBase { ELD_CEGAR = CHC + 2, // 10001010 GRAIN_SYGUS = CHC + 4, // 10001100 ABCPDR = YOSYS + 16, // 10010000 - BTOR_GENERIC = YOSYS + 32,// 10100000 + PONO = YOSYS + 32, // 10100000 RELCHC = YOSYS + 64 // 11000000 } backend_selector; /// Type of invariant synthesis backend @@ -47,7 +46,7 @@ class VlgVerifTgtGenBase { GRAIN = GRAIN_SYGUS ^ YOSYS, ABC = ABCPDR ^ YOSYS, ELDERICA = ELD_CEGAR ^ YOSYS,// 0001010 - NOSYN = BTOR_GENERIC ^ YOSYS // 1000000 + NOSYN = YOSYS // 1000000 } synthesis_backend_selector; /// Type of the chc target enum _chc_target_t { CEX, INVCANDIDATE, GENERAL_PROPERTY }; @@ -84,52 +83,33 @@ class VlgVerifTgtGenBase { ALL } ValidateSynthesizedInvariant; - // ----------- Options for CoSA settings -------------- // - /// Do we set separate problems for different var map (CoSA only) - bool PerVariableProblemCosa; // true - /// Whether to abstract the memory read - bool MemAbsReadAbstraction; // false + // ----------- Options for Pono settings -------------- // /// Whether to force the instruction check to start from reset state bool ForceInstCheckReset; - /// For COSA target generator : whether to force NEW/OLD port declaration + /// For Pono target generator : whether to force NEW/OLD port declaration enum { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; - /// Generate a jg script to help validate cosa? - bool CosaGenJgTesterScript; - /// generate the trace for all variables? or just the relevent variables - bool CosaFullTrace; - /// For CoSA backend: do we add (* keep *)? default true, however, it can be + /// Generate a jg script to help validate Pono? + bool PonoGenJgTesterScript; + /// For Pono backend: do we add (* keep *)? default true, however, it can be /// buggy, so you can disable it if you want - bool CosaAddKeep; + bool PonoAddKeep; + /// For Pono backend: what more options to add + std::string PonoOtherSolverOptions; /// whether to force dot reference check in the generation - /// if you expect to use cosa on the it, yes, you need to + /// if you expect to use Pono on the it, yes, you need to /// use the default setting : NOTIFY_PANIC /// in some rare cases, you may want to use JasperGold after it /// in that case, it is okay to just ignore it - enum CosaDotReferenceNotify_t { + enum PonoDotReferenceNotify_t { NOTIFY_PANIC = 0, NOTIFY_WARNING = 1, NOTIFY_IGNORE = 2 - } CosaDotReferenceNotify; + } PonoDotReferenceNotify; // The bound of BMC, default 127 unsigned MaxBound; /// Only enforce var eq on updated vars, should not be used bool OnlyAssumeUpdatedVarsEq; // should be false - - // ----------- Options for CoSA script -------------- // - /// If not empty, the generated script will include the path of Cosa - std::string CosaPath; - /// If not empty, the generated script will include sourcing a script - std::string CosaPyEnvironment; - /// A choice of solver (in the script) - std::string CosaSolver; - /// Whether the Solver should generate vcd trace - bool CosaGenTraceVcd; - /// Assumption overly constrained check - bool CosaAssumptionOverlyConstrainedCheck; - /// other CoSA options - std::string CosaOtherSolverOptions; - // ----------- Options for Yosys SMT-LIB2 Generator -------------- // /// The path to yosys, if yosys is not in the PATH, default empty std::string YosysPath; @@ -183,6 +163,10 @@ class VlgVerifTgtGenBase { /// CHC, whether to force assumption on the init bool BtorAddCommentsInOutputs; + /* TODO: future work: + bool YosysAssumptionOverlyConstrainedCheck; + */ + // ----------- Options for Z3/Grain/ABC Solver -------------- // /// The path to Z3, if "z3" is not in the PATH, default empty std::string Z3Path; @@ -227,17 +211,15 @@ class VlgVerifTgtGenBase { VerificationSettingAvoidIssueStage(false), ValidateSynthesizedInvariant(ALL), - // ----------- Options for CoSA settings -------------- // - PerVariableProblemCosa(false), MemAbsReadAbstraction(false), + // ----------- Options for Pono settings -------------- // ForceInstCheckReset(false), PortDeclStyle(AUTO), - CosaGenJgTesterScript(false), CosaFullTrace(false), CosaAddKeep(true), - CosaDotReferenceNotify(CosaDotReferenceNotify_t::NOTIFY_PANIC), + PonoGenJgTesterScript(false), PonoAddKeep(true), + PonoOtherSolverOptions(""), + PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), MaxBound(127), OnlyAssumeUpdatedVarsEq(false), - // ----------- Options for CoSA script -------------- // - CosaPath(""), CosaPyEnvironment(""), CosaSolver(""), - CosaGenTraceVcd(true), CosaAssumptionOverlyConstrainedCheck(false), - CosaOtherSolverOptions(""), + // ----------- Options for Pono script -------------- // + // PonoAssumptionOverlyConstrainedCheck(false), // ----------- Options for Yosys SMT-LIB2 Generator -------------- // YosysUndrivenNetAsInput(true), YosysSmtFlattenHierarchy(true), diff --git a/src/rfmap-in/CMakeLists.txt b/src/rfmap-in/CMakeLists.txt index ce38831d3..6ea9bd03a 100644 --- a/src/rfmap-in/CMakeLists.txt +++ b/src/rfmap-in/CMakeLists.txt @@ -3,5 +3,6 @@ # ---------------------------------------------------------------------------- # target_sources(${ILANG_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/verilog_rfmap.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rfmap_typecheck.cc ) diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc new file mode 100644 index 000000000..eb3ab7816 --- /dev/null +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -0,0 +1,103 @@ +/// \file rfmap_typecheck.cc Refinement map typecheck +/// Second pass : rfexpr typecheck + +#include + +#include + +namespace ilang { +namespace rfmap { + +using namespace verilog_expr; + +std::string TypedVerilogRefinementMap::new_id() { + return "__auxvar"+std::to_string(counter++) + "__"; +} + + +TypedVerilogRefinementMap::TypedVerilogRefinementMap( + const std::string & varmap_json_file, + const std::string & instcond_json_file, + var_typecheck_t ila_var_type_check, + var_typecheck_t rtl_var_type_check + ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), + counter(0) { + + CreateInternalSignals(); + + // we are not allowing recursive value recorder in the value field + CollectInlineValueRecorder(); + AnnotateValueRecorderType(); + + // Gather 1. value recorder + // 2. delay vars + // 3. def vars () + // 4. stage or others are 1 cycle + CollectInternallyDefinedVars(); + + + AnnotateAllTypes(); + // additionally you can have an RTL signal replace pass? + + +} // TypedVerilogRefinementMap::TypedVerilogRefinementMap + +void TypedVerilogRefinementMap::CollectInlineValueRecorderFunc(RfExpr & inout) { + if(inout->get_op() == voperator::AT) { + auto recorder_name = new_id(); + auto new_node = VExprAst::MakeVar(recorder_name); + VExprAst::VExprAstPtrVec child(inout->get_child()); + ValueRecorder tmp_value_recorder; + tmp_value_recorder.width = 0; + tmp_value_recorder.value = child.at(0); + if (child.at(1)->is_constant()) { + // deal with value@0 + + auto new_cond = VExprAst::MakeBinaryAst(voperator::L_EQ, + + ) + + } else + tmp_value_recorder.condition = child.at(1); + + + } +} // CollectInlineValueRecorder + +void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { + +#define ERRIF(cond,str) do{ ILA_ERROR_IF(cond) << str ; if(cond) return; } while(false) + + for (const auto & n_st : phase_tracker) { + for (const auto & var_def : n_st.second.event_alias ) { + VarDef tmp; + tmp.type = VarDef::var_type::WIRE; + tmp.width = 1; + all_var_def_types.emplace(var_def.first, tmp); + } + for (const auto & var_def : n_st.second.var_defs ) { + all_var_def_types.emplace(var_def.first, var_def.second); + } + } + for (const auto & n_st : value_recorder) { + VarDef tmp; + all_var_def_types.emplace(n_st.first); + } + for (const auto & n_st : customized_monitor) { + ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); + ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); + monitor_names.insert(n_st.first); + + for (const auto & var_def : n_st.second.var_defs ) { + ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); + var_def_names.insert(var_def.first); + } + } +#undef ERRIF +} // CollectInternallyDefinedVars + + + +} // namespace rfmap +} // namespace ilang + diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 8b2f2384e..372099fbc 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -495,14 +495,14 @@ VerilogRefinementMap::VerilogRefinementMap nlohmann::json * state_mapping = GetJsonSection(rf_vmap,{"state mapping"}); ERRIF(state_mapping == NULL , "state var mapping is duplicated or missing"); for (auto& i : state_mapping->items()) { - IlaStateVarMapping svmp; + IlaVarMapping svmp; auto sname = i.key(); // ila state name if(i.value().is_string()) { - svmp.type = IlaStateVarMapping::StateVarMapType::SINGLE; + svmp.type = IlaVarMapping::StateVarMapType::SINGLE; svmp.single_map.single_map = ParseRfMapExprJson(i.value()); } else if (i.value().is_object()) { // External Mem - svmp.type = IlaStateVarMapping::StateVarMapType::EXTERNMEM; + svmp.type = IlaVarMapping::StateVarMapType::EXTERNMEM; svmp.externmem_map.push_back(ExternalMemPortMap()); auto & extmem_ports = i.value(); @@ -519,7 +519,7 @@ VerilogRefinementMap::VerilogRefinementMap ERRIF(true, "Expecting array of list or objects for" + sname); if (are_memports) { - svmp.type = IlaStateVarMapping::StateVarMapType::EXTERNMEM; + svmp.type = IlaVarMapping::StateVarMapType::EXTERNMEM; for (const auto & idx_obj_pair : i.value().items()) { ENSURE( idx_obj_pair.value().is_object() , "Expecting array of objects for " + sname); @@ -529,7 +529,7 @@ VerilogRefinementMap::VerilogRefinementMap JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); } } else { - svmp.type = IlaStateVarMapping::StateVarMapType::CONDITIONAL; + svmp.type = IlaVarMapping::StateVarMapType::CONDITIONAL; JsonRfmapParseCond(svmp.single_map, i.value() ); } @@ -539,6 +539,30 @@ VerilogRefinementMap::VerilogRefinementMap } // for each state } // state mapping + { // input mapping + // TODO: add things here + nlohmann::json * input_mapping = GetJsonSection(rf_vmap,{"input mapping"}); + if(input_mapping) { + for (auto& i : input_mapping->items()) { + IlaVarMapping ivmp; + auto sname = i.key(); // ila state name + ERRIF(i.value().is_object(), "input array is not supported"); + if(i.value().is_string()) { + ivmp.type = IlaVarMapping::StateVarMapType::SINGLE; + ivmp.single_map.single_map = ParseRfMapExprJson(i.value()); + } else if (i.value().is_array()) { + ERRIF( i.value().empty(), ("Empty list for " + sname) ); + ENSURE(i.value().begin()->is_array(), "Expect array of array"); + ivmp.type = IlaVarMapping::StateVarMapType::CONDITIONAL; + JsonRfmapParseCond(ivmp.single_map, i.value() ); + + } // if array of array / array of object + ILA_ERROR_IF( IN(sname, ila_input_var_map) ) << "ILA state var : " << sname << " has duplicated mapping"; + ila_input_var_map.emplace(sname, ivmp); + } // for each input var + } + } // input mapping + { // interface map nlohmann::json * rtl_if_map = GetJsonSection(rf_vmap,{"RTL interface connection"}); ERRIF(rtl_if_map == nullptr, "`RTL interface connection` is duplicated or missing" ); @@ -880,10 +904,7 @@ VerilogRefinementMap::VerilogRefinementMap } // if invariant } // inst cond - - if (ParseRfExprErrFlag) { - // TODO: - } + ERRIF(ParseRfExprErrFlag, "error occur in refinement expression parsing"); } // VerilogRefinementMap::VerilogRefinementMap @@ -907,20 +928,6 @@ bool VerilogRefinementMap::SelfCheckField() const { // check module name ERRIF(ParseRfExprErrFlag, "Error in parsing refinement expressions" ); - if(!model_names.IlaModuleName.empty()) { - ERRIF( !is_valid_id_name(model_names.IlaModuleName), - "ILA instance name " - << model_names.IlaModuleName - << " is not valid"); - } - - if(!model_names.RtlModuleName.empty()) { - ERRIF( !is_valid_id_name(model_names.RtlModuleName), - "RTL instance name " - << model_names.RtlModuleName - << " is not valid"); - } - for (const auto & n_map: ila_state_var_map) { ENSURE( !(n_map.second.externmem_map.empty()) || (n_map.second.single_map.single_map.get() != nullptr) || @@ -996,13 +1003,12 @@ bool VerilogRefinementMap::SelfCheckField() const { // check trackers, recorders, monitor names are okay { // GeneralVerilogMonitor, for ids are okay, no bad names - std::set monitor_names; std::set var_def_names; for (const auto & n_st : phase_tracker) { - ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); - ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); - monitor_names.insert(n_st.first); + for (const auto & var_def : n_st.second.event_alias ) { + all_var_def_types.emplace(var_def.first) + ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); var_def_names.insert(var_def.first); } diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index 8bf4857db..2f0adaf39 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -143,7 +143,7 @@ VlgSglTgtGen::VlgSglTgtGen( ILA_NOT_NULL(instr_ptr); // TODO: insert the memory export directive - vlg_ila.AnnotateMemory(supplementary_info.memory_export); + vlg_ila.AnnotateMemory(supplementary_info.memory_export); // need to change this vlg_ila.ExportTopLevelInstr(instr_ptr); From c7f845ed9c6a2950ffb1aaef9a08a15a4c361a56 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 12 May 2021 18:24:22 -0400 Subject: [PATCH 08/78] add array addr width extract --- src/verilog-in/verilog_analysis.cc | 23 +++++++++++--- test/t_verilog_analysis.cc | 34 +++++++++++++++++++++ test/unit-data/verilog_sample/range-array.v | 25 +++++++++++++++ 3 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 test/unit-data/verilog_sample/range-array.v diff --git a/src/verilog-in/verilog_analysis.cc b/src/verilog-in/verilog_analysis.cc index d1d5ba604..cef16633a 100644 --- a/src/verilog-in/verilog_analysis.cc +++ b/src/verilog-in/verilog_analysis.cc @@ -635,7 +635,7 @@ SignalInfoBase VerilogAnalyzer::get_signal( const std::string& net_name, const std::map* const width_info) const { SignalInfoBase bad_signal("", "", 0, hierarchical_name_type::NONE, - vlg_loc_t()); + vlg_loc_t(), 0); if (_bad_state_return()) return bad_signal; @@ -834,6 +834,15 @@ bool VerilogAnalyzer::get_hierarchy_from_full_name( // ------------------- signal info base ---------------------------------- +unsigned addr_range_to_width(ast_identifier id, const std::string& full_name, + const VerilogAnalyzer* _ana, int width) { + if(id->range_or_idx == ID_HAS_RANGES && id->ranges && id->ranges->items > 0) { + ast_range * range = (ast_range *) id->ranges->head; + return range_to_width(range, full_name, _ana, width); + } + return 0; +} + unsigned range_to_width(ast_range* range, const std::string& full_name, const VerilogAnalyzer* _ana, int width = -1) { if (range == NULL) @@ -878,7 +887,9 @@ SignalInfoPort::SignalInfoPort( : (IN_p(full_name, width_info) ? width_info->at(full_name) : -1)), - tp, VerilogAnalyzer::Meta2Loc(def->meta)), + tp, VerilogAnalyzer::Meta2Loc(def->meta), + 0 // not an array + ), _def(def) { // ILA_WARN_IF( def->range == NULL ) << "Verilog Analyzer: // signal "<< full_name <<" has no range."; ILA_WARN_IF(_width == 0) @@ -898,7 +909,9 @@ SignalInfoReg::SignalInfoReg(ast_reg_declaration* def, : (IN_p(full_name, width_info) ? width_info->at(full_name) : -1)), - tp, VerilogAnalyzer::Meta2Loc(def->meta)), + tp, VerilogAnalyzer::Meta2Loc(def->meta), + addr_range_to_width(def->identifier, full_name, _ana, -1) + ), _def(def) { ILA_WARN_IF(_width == 0) << "Verilog Analyzer is not able to determine the width of signal:" @@ -917,7 +930,9 @@ SignalInfoWire::SignalInfoWire( : (IN_p(full_name, width_info) ? width_info->at(full_name) : -1)), - tp, VerilogAnalyzer::Meta2Loc(def->meta)), + tp, VerilogAnalyzer::Meta2Loc(def->meta), + 0 // not an array + ), _def(def) { ILA_WARN_IF(_width == 0) << "Verilog Analyzer is not able to determine the width of signal:" diff --git a/test/t_verilog_analysis.cc b/test/t_verilog_analysis.cc index 60ae60bfb..61d3b0cd2 100644 --- a/test/t_verilog_analysis.cc +++ b/test/t_verilog_analysis.cc @@ -81,9 +81,26 @@ TEST(TestVerilogAnalysis, Include) { << "End loc of m1:" << va.get_endmodule_loc("m1"); } +TEST(TestVerilogAnalysis, RangeAnalysisArray) { +#define IS_ARRAY_WIDTH(n, w) EXPECT_EQ(va.get_signal("m1." n).get_addr_width(), w) + { + VerilogInfo va( + VerilogInfo::path_vec_t( + {std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/verilog_sample/"}), + VerilogInfo::path_vec_t({std::string(ILANG_TEST_SRC_ROOT) + + "/unit-data/verilog_sample/range-array.v"}), + "m1"); + IS_ARRAY_WIDTH("r12", 8-1); + IS_ARRAY_WIDTH("r22", 8-1); + IS_ARRAY_WIDTH("r14", 9-1); + IS_ARRAY_WIDTH("r24", 7-1); + } +} + TEST(TestVerilogAnalysis, RangeAnalysis) { #define IS_WIDTH(n, w) EXPECT_EQ(va.get_signal("m1." n).get_width(), w) +#define NOT_ARRAY(n) EXPECT_EQ(va.get_signal("m1." n).get_addr_width(), 0) { // test 1 VerilogInfo va( @@ -97,22 +114,39 @@ TEST(TestVerilogAnalysis, RangeAnalysis) { IS_WIDTH("r2", 8); IS_WIDTH("r3", 8); IS_WIDTH("r4", 8); + NOT_ARRAY("r1"); + NOT_ARRAY("r2"); + NOT_ARRAY("r3"); + NOT_ARRAY("r4"); IS_WIDTH("r12", 8); IS_WIDTH("r22", 8); IS_WIDTH("r32", 8); IS_WIDTH("r42", 8); + NOT_ARRAY("r12"); + NOT_ARRAY("r22"); + NOT_ARRAY("r32"); + NOT_ARRAY("r42"); IS_WIDTH("r14", 9); IS_WIDTH("r24", 7); IS_WIDTH("r34", 8); IS_WIDTH("r44", 8); + NOT_ARRAY("r14"); + NOT_ARRAY("r24"); + NOT_ARRAY("r34"); + NOT_ARRAY("r44"); IS_WIDTH("rm", 2); IS_WIDTH("a", 1); // F IS_WIDTH("b", 1); // F IS_WIDTH("c", 2); // F IS_WIDTH("d", 1); // F + NOT_ARRAY("rm"); + NOT_ARRAY("a"); // F + NOT_ARRAY("b"); // F + NOT_ARRAY("c"); // F + NOT_ARRAY("d"); // F } // end of test1 { // test 2 VerilogInfo va( diff --git a/test/unit-data/verilog_sample/range-array.v b/test/unit-data/verilog_sample/range-array.v new file mode 100644 index 000000000..8416b8144 --- /dev/null +++ b/test/unit-data/verilog_sample/range-array.v @@ -0,0 +1,25 @@ + +module range( clk, rst, r1, r2); + +`include "rangeheader2.v" + +input clk; +input rst; +output [`R1:0] r1; +output [`R2-1:0] r2; + +wire [`R3:0] r3; +wire [`R4] r4; + +reg [`R12:0] r12 [`R12-1:0]; +reg [`R22-1:0] r22 [`R22-2:0]; +wire [`R32:0] r32; +wire [`R42] r42; + +reg [`R14:0] r14 [`R14-1:0]; +reg [`R24-1:0] r24 [`R24-2:0]; +wire [`R34:0] r34; +wire [`R44] r44; + + +endmodule From cdafa8bdf6b22441b65b1df82588b66b6e405e10 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 12 May 2021 18:27:16 -0400 Subject: [PATCH 09/78] fix update --- .../verilog-in/verilog_analysis_wrapper.h | 9 +++++++-- src/verilog-in/verilog_analysis.cc | 20 ++++++++++--------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/ilang/verilog-in/verilog_analysis_wrapper.h b/include/ilang/verilog-in/verilog_analysis_wrapper.h index 11d5f52c3..089ae2349 100644 --- a/include/ilang/verilog-in/verilog_analysis_wrapper.h +++ b/include/ilang/verilog-in/verilog_analysis_wrapper.h @@ -122,11 +122,15 @@ class SignalInfoBase { const VerilogAnalyzerBase::hierarchical_name_type _type; /// its location of definition const VerilogAnalyzerBase::vlg_loc_t _loc; + /// addr width of the array, 0 if not array + const unsigned _addr_width; public: /// --------------------- ACCESSORS ------------------- /// /// Return the width of the signal virtual unsigned get_width() const { return _width; } + /// Return the addrwidth of the signal + virtual unsigned get_addr_width() const {return _addr_width; } /// Whether is a IO signal virtual bool is_io_sig() const { return VerilogAnalyzerBase::is_io_sig(_type); @@ -164,8 +168,9 @@ class SignalInfoBase { /// --------------------- ACCESSORS ------------------- /// SignalInfoBase(const std::string& n, const std::string& h, unsigned w, const VerilogAnalyzerBase::hierarchical_name_type& typ, - const VerilogAnalyzerBase::vlg_loc_t& loc) - : _name(n), _hierarchical_name(h), _width(w), _type(typ), _loc(loc) {} + const VerilogAnalyzerBase::vlg_loc_t& loc, + unsigned aw) + : _name(n), _hierarchical_name(h), _width(w), _type(typ), _loc(loc), _addr_width(aw) {} /// implicit copy constructor }; // class SignalInfoBase diff --git a/src/verilog-in/verilog_analysis.cc b/src/verilog-in/verilog_analysis.cc index cef16633a..bf2021496 100644 --- a/src/verilog-in/verilog_analysis.cc +++ b/src/verilog-in/verilog_analysis.cc @@ -834,15 +834,6 @@ bool VerilogAnalyzer::get_hierarchy_from_full_name( // ------------------- signal info base ---------------------------------- -unsigned addr_range_to_width(ast_identifier id, const std::string& full_name, - const VerilogAnalyzer* _ana, int width) { - if(id->range_or_idx == ID_HAS_RANGES && id->ranges && id->ranges->items > 0) { - ast_range * range = (ast_range *) id->ranges->head; - return range_to_width(range, full_name, _ana, width); - } - return 0; -} - unsigned range_to_width(ast_range* range, const std::string& full_name, const VerilogAnalyzer* _ana, int width = -1) { if (range == NULL) @@ -875,6 +866,17 @@ unsigned range_to_width(ast_range* range, const std::string& full_name, return analyzed_width; } + +unsigned addr_range_to_width(ast_identifier id, const std::string& full_name, + const VerilogAnalyzer* _ana, int width) { + if(id->range_or_idx == ID_HAS_RANGES && id->ranges && id->ranges->items > 0) { + ast_range * range = (ast_range *) id->ranges->head; + return range_to_width(range, full_name, _ana, width); + } + return 0; +} + + SignalInfoPort::SignalInfoPort( ast_port_declaration* def, const std::string& full_name, VerilogAnalyzerBase::hierarchical_name_type tp, From ca747d3f3d989c97db8e5be3f80ef5fd1874967c Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 12 May 2021 18:55:34 -0400 Subject: [PATCH 10/78] fix array range parsing --- src/verilog-in/verilog_analysis.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/verilog-in/verilog_analysis.cc b/src/verilog-in/verilog_analysis.cc index bf2021496..c8094ddeb 100644 --- a/src/verilog-in/verilog_analysis.cc +++ b/src/verilog-in/verilog_analysis.cc @@ -870,7 +870,7 @@ unsigned range_to_width(ast_range* range, const std::string& full_name, unsigned addr_range_to_width(ast_identifier id, const std::string& full_name, const VerilogAnalyzer* _ana, int width) { if(id->range_or_idx == ID_HAS_RANGES && id->ranges && id->ranges->items > 0) { - ast_range * range = (ast_range *) id->ranges->head; + ast_range * range = (ast_range *) id->ranges->head->data; return range_to_width(range, full_name, _ana, width); } return 0; From ad1e20ab6e3b2f9bc20dfcd072108cd2ea78321b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sat, 15 May 2021 11:27:21 -0400 Subject: [PATCH 11/78] update vexpparser --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 3d959485a..9c9532828 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 3d959485a8f039c3200304e82534b9563aef6a3c +Subproject commit 9c9532828ee049a946d618ff102c063bcf7154fa From 8ce99675ee1a394206452079f23deff2f90b1c62 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 31 May 2021 22:25:21 -0400 Subject: [PATCH 12/78] type inference --- extern/vexpparser | 2 +- include/ilang/rfmap-in/rfmap_typecheck.h | 83 ++--- include/ilang/rfmap-in/rfvar_type.h | 56 +++ include/ilang/rfmap-in/verilog_rfmap.h | 9 +- src/rfmap-in/rfmap_typecheck.cc | 432 ++++++++++++++++++++--- src/rfmap-in/verilog_rfmap.cc | 21 +- 6 files changed, 495 insertions(+), 108 deletions(-) create mode 100644 include/ilang/rfmap-in/rfvar_type.h diff --git a/extern/vexpparser b/extern/vexpparser index 9c9532828..b1ed8f99d 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 9c9532828ee049a946d618ff102c063bcf7154fa +Subproject commit b1ed8f99d30c367bc3c0712bafce9622ee02bdba diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index ab2670206..6b3f3657c 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -3,57 +3,33 @@ /// --- Hongce Zhang (hongcez@princeton.edu) -#ifndef RFMAP_TYPECHECK_H__ -#define RFMAP_TYPECHECK_H__ +#ifndef ILANG_RFMAP_TYPECHECK_H__ +#define ILANG_RFMAP_TYPECHECK_H__ #include +#include + #include + +// define annotation + + namespace ilang { namespace rfmap { -// define type -struct RfMapType { - enum class TYPE {BV, MEM} type; - unsigned width; - unsigned addr_width; - unsigned data_width; -}; - -// define annotation -namespace verilog_expr{ -class TypeAnnotation : public AbstractInternalInfo { - public: - enum class VARTYPE { - NOTVAR, /*also unknown type*/ - ILAS /*state var*/, - ILAI, /*ila input*/ - RTLV, /*rtl signal*/ - PHASE, /*stage name*/ - DEFINE_VAR, /*defined vars*/ - DELAY, /*inline delay*/ - VALUE_RECORDER, /*inline value recorder*/ - INTERNAL /* those already translated: - like __CYCLE_CNT__, __START__*/ }; - - // allow instantiation - virtual void should_not_instantiate() override {} - - VARTYPE var_ref_type; - RfMapType type; + +class TypeAnnotation : + public ::verilog_expr::AbstractInternalInfo, + public ::ilang::rfmap::RfVarTypeOrig { + +public: + // allow instantiation + virtual void should_not_instantiate() override {} - unsigned width() { return type.type == RfMapType::BV ? width : data_width; } }; // TypeAnnotation -} - -struct InternalSignals { - RfExpr start; - RfExpr issue; - RfExpr iend; - RfExpr cycle_cnt; - // and others if necessary - // __STARTED__ -}; + + // type infer rules // @@ -67,15 +43,14 @@ struct InternalSignals { struct TypedVerilogRefinementMap : public VerilogRefinementMap { // type definitions - typedef std::function var_typecheck_t; + typedef std::function var_typecheck_t; using VarDef = GeneralVerilogMonitor::VarDef; // constructor TypedVerilogRefinementMap( const std::string & varmap_json_file, const std::string & instcond_json_file, - var_typecheck_t ila_var_type_check, - var_typecheck_t rtl_var_type_check + var_typecheck_t type_checker ); // references @@ -96,23 +71,35 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { std::map all_var_def_types; // this should include phase-tracker (m,v,alias) // ... ? + void TraverseAllRfExpr(std::function func); protected: void CollectInternallyDefinedVars(); - // internal signals - InternalSignals internals_; + void TraverseRfExpr(RfExpr & inout, std::function func) ; + void TraverseCondMap(SingleVarMap & inout, std::function func) ; + + var_typecheck_t typechecker; private: // help with naming unsigned counter; std::string new_id(); + // helper for AST traversal + void collect_inline_value_recorder_func(RfExpr & inout); + void collect_inline_delay_func(RfExpr & inout); + void CollectInlineDelayValueHolder(); + + RfMapVarType TypeInferTravserRfExpr(const RfExpr & in); + void ComputeDelayValueHolderWidth(); + + }; } // namespace rfmap } // namespace ilang -#endif // RFMAP_TYPECHECK_H__ +#endif // ILANG_RFMAP_TYPECHECK_H__ diff --git a/include/ilang/rfmap-in/rfvar_type.h b/include/ilang/rfmap-in/rfvar_type.h new file mode 100644 index 000000000..954a13564 --- /dev/null +++ b/include/ilang/rfmap-in/rfvar_type.h @@ -0,0 +1,56 @@ +/// \file Verilog Verification Refinement Map Interface Class +/// Variable Types +/// --- Hongce Zhang (hongcez@princeton.edu) + + +#ifndef ILANG_RFMAP_VARTYPE_H__ +#define ILANG_RFMAP_VARTYPE_H__ + + +namespace ilang { +namespace rfmap { + +// define type +struct RfMapVarType { + enum class TYPE {BV, MEM, UNKNOWN} type; + unsigned width; + unsigned addr_width; + unsigned data_width; + + bool is_unknown() const { return type == TYPE::UNKNOWN; } + bool is_bv() const { return type == TYPE::BV; } + bool is_array() const { return type == TYPE::MEM; } + + /// for unknown type + RfMapVarType() : type(TYPE::UNKNOWN) {} + /// for bit-vector type + RfMapVarType(unsigned w) : type(TYPE::BV), width(w) {} + /// for array type + RfMapVarType(unsigned a, unsigned d) : type(TYPE::MEM), addr_width(a), data_width(d) {} + unsigned unified_width() { return type == RfMapVarType::TYPE::BV ? width : data_width; } +}; + +class RfVarTypeOrig { +public: + enum class VARTYPE { + NOTVAR, /*also unknown type*/ + ILAS /*state var*/, + ILAI, /*ila input*/ + RTLV, /*rtl signal*/ + PHASE, /*stage name*/ + DEFINE_VAR, /*defined vars*/ + DELAY, /*inline delay*/ + VALUE_RECORDER, /*inline value recorder*/ + INTERNAL /* those already translated: + like __CYCLE_CNT__, __START__*/ }; + + VARTYPE var_ref_type; + RfMapVarType type; + + +}; // class RfVarType + +} // namespace rfmap +} // namespace ilang + +#endif // ILANG_RFMAP_VARTYPE_H__ diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 7e7a6e709..90f494ab8 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -3,8 +3,8 @@ /// --- Hongce Zhang (hongcez@princeton.edu) -#ifndef VERILOG_RFMAP_H__ -#define VERILOG_RFMAP_H__ +#ifndef ILANG_VERILOG_RFMAP_H__ +#define ILANG_VERILOG_RFMAP_H__ #include #include @@ -136,6 +136,7 @@ struct ValueRecorder { struct SignalDelay { RfExpr signal; unsigned num_cycle; + unsigned width; }; struct PhaseTracker { @@ -166,7 +167,7 @@ struct InstructionCompleteCondition{ enum class ConditionType {BOUND, SIGNAL} type; unsigned ready_bound; unsigned max_bound; - RfExpr start_condition; + std::vector start_condition; RfExpr ready_signal; }; // @@ -209,5 +210,5 @@ struct VerilogRefinementMap { } // namespace ilang } // namespace rfmap -#endif // VERILOG_RFMAP_H__ +#endif // ILANG_VERILOG_RFMAP_H__ diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index eb3ab7816..16b50000b 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -2,8 +2,11 @@ /// Second pass : rfexpr typecheck #include +#include +#include #include +#include namespace ilang { namespace rfmap { @@ -18,84 +21,415 @@ std::string TypedVerilogRefinementMap::new_id() { TypedVerilogRefinementMap::TypedVerilogRefinementMap( const std::string & varmap_json_file, const std::string & instcond_json_file, - var_typecheck_t ila_var_type_check, - var_typecheck_t rtl_var_type_check + var_typecheck_t type_checker ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), - counter(0) { + counter(0), typechecker(type_checker) { - CreateInternalSignals(); - - // we are not allowing recursive value recorder in the value field - CollectInlineValueRecorder(); - AnnotateValueRecorderType(); - - // Gather 1. value recorder - // 2. delay vars - // 3. def vars () - // 4. stage or others are 1 cycle + // collect those with unknown types + // a. delay + // b. value holder + CollectInlineDelayValueHolder(); + + // collect those new vars with user-defined types CollectInternallyDefinedVars(); + // determine the types of delay and value holder + ComputeDelayValueHolderWidth(); - AnnotateAllTypes(); - // additionally you can have an RTL signal replace pass? + // + AnnotateSignalsAndCollectRtlVars(); } // TypedVerilogRefinementMap::TypedVerilogRefinementMap -void TypedVerilogRefinementMap::CollectInlineValueRecorderFunc(RfExpr & inout) { - if(inout->get_op() == voperator::AT) { - auto recorder_name = new_id(); - auto new_node = VExprAst::MakeVar(recorder_name); - VExprAst::VExprAstPtrVec child(inout->get_child()); +void TypedVerilogRefinementMap::collect_inline_value_recorder_func(RfExpr & inout) { + if(inout->get_op() == verilog_expr::voperator::AT) { + auto recorder_name = new_id()+"recorder"; + auto new_node = verilog_expr::VExprAst::MakeVar(recorder_name); + verilog_expr::VExprAst::VExprAstPtrVec child(inout->get_child()); ValueRecorder tmp_value_recorder; tmp_value_recorder.width = 0; tmp_value_recorder.value = child.at(0); + // TODO: deal with value@CLK.n if (child.at(1)->is_constant()) { // deal with value@0 - - auto new_cond = VExprAst::MakeBinaryAst(voperator::L_EQ, - - ) - + auto new_cond = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, + verilog_expr::VExprAst::MakeVar("__CYCLE_CNT__"), + child.at(1) + ); + tmp_value_recorder.condition = new_cond; } else tmp_value_recorder.condition = child.at(1); - - + value_recorder.emplace(recorder_name, tmp_value_recorder); + inout = new_node; // rewrite the node } -} // CollectInlineValueRecorder +} // collect_inline_value_recorder_func + +void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr & inout) { + if(inout->get_op() == voperator::DELAY) { + assert(inout->get_str_parameter().empty()); // currently we don't handle multi-clock + assert(inout->get_parameter().size() == 1); + assert(inout->get_child().size() >= 1); + + int delay = inout->get_parameter().at(0); + + auto delay_name = new_id()+"delay"; + auto new_node = VExprAst::MakeVar(delay_name); + SignalDelay tmp_delay; + tmp_delay.signal = inout->get_child().at(0); + tmp_delay.num_cycle = delay; + tmp_delay.width = 0; + aux_delays.emplace(delay_name, tmp_delay); + + if(inout->get_child().size() == 1) { + inout = new_node; + } else { + assert(inout->get_child().size() == 2); + auto tmp_node = VExprAst::MakeBinaryAst(voperator::L_AND, + new_node, inout->get_child().at(1) ); + inout = tmp_node; + } + } +} // collect_inline_delay_func + +void TypedVerilogRefinementMap::CollectInlineDelayValueHolder() { + TraverseAllRfExpr([this](RfExpr & inout) -> void { this->collect_inline_delay_func(inout);} ); + TraverseAllRfExpr([this](RfExpr & inout) -> void { this->collect_inline_value_recorder_func(inout);} ); +} + void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { + for (const auto & n_st : phase_tracker) { + for (const auto & var_def : n_st.second.event_alias ) { + VarDef tmp; + tmp.type = VarDef::var_type::WIRE; + tmp.width = 1; + all_var_def_types.emplace(var_def.first, tmp); + } + for (const auto & var_def : n_st.second.var_defs ) { + all_var_def_types.emplace(var_def.first, var_def.second); + } + } + for (const auto & n_st : value_recorder) { + VarDef tmp; + if(n_st.second.width != 0) { + tmp.width = n_st.second.width; + tmp.type = VarDef::var_type::REG; + all_var_def_types.emplace(n_st.first, tmp); + } + } // value recorder -#define ERRIF(cond,str) do{ ILA_ERROR_IF(cond) << str ; if(cond) return; } while(false) + for (const auto & n_st : customized_monitor) { + for (const auto & var_def : n_st.second.var_defs ) { + all_var_def_types.emplace(var_def.first, var_def.second); + } + } - for (const auto & n_st : phase_tracker) { - for (const auto & var_def : n_st.second.event_alias ) { - VarDef tmp; - tmp.type = VarDef::var_type::WIRE; - tmp.width = 1; - all_var_def_types.emplace(var_def.first, tmp); + // add internal signals + { + VarDef tmp; + tmp.width = 1; + tmp.type = VarDef::var_type::WIRE; + all_var_def_types.emplace("decode", tmp); + all_var_def_types.emplace("commit", tmp); + } + + +} // CollectInternallyDefinedVars + +void TypedVerilogRefinementMap::TraverseCondMap(SingleVarMap & inout, std::function func) { + if(inout.single_map) + TraverseRfExpr(inout.single_map, func); + else + for (auto & c : inout.cond_map) { + TraverseRfExpr(c.first, func); + TraverseRfExpr(c.second, func); + } +} // TraverseCondMap + +void TypedVerilogRefinementMap::TraverseAllRfExpr(std::function func) { + for(auto & sv : ila_state_var_map) { + if(sv.second.type == IlaVarMapping::StateVarMapType::SINGLE) + TraverseRfExpr(sv.second.single_map.single_map,func); + else if(sv.second.type == IlaVarMapping::StateVarMapType::CONDITIONAL) { + for (auto & c : sv.second.single_map.cond_map) { + TraverseRfExpr(c.first, func); + TraverseRfExpr(c.second, func); } - for (const auto & var_def : n_st.second.var_defs ) { - all_var_def_types.emplace(var_def.first, var_def.second); + } else { // extern map + for (auto & m : sv.second.externmem_map) { + TraverseCondMap(m.raddr_map, func); + TraverseCondMap(m.rdata_map, func); + TraverseCondMap(m.ren_map, func); + TraverseCondMap(m.waddr_map, func); + TraverseCondMap(m.wdata_map, func); + TraverseCondMap(m.wen_map, func); } } - for (const auto & n_st : value_recorder) { - VarDef tmp; - all_var_def_types.emplace(n_st.first); + } // sv map + + for(auto & sv : ila_input_var_map) { + if(sv.second.type == IlaVarMapping::StateVarMapType::SINGLE) + TraverseRfExpr(sv.second.single_map.single_map,func); + else /* if(sv.second.type == IlaVarMapping::StateVarMapType::CONDITIONAL) */ { + for (auto & c : sv.second.single_map.cond_map) { + TraverseRfExpr(c.first, func); + TraverseRfExpr(c.second, func); + } + } + } // input var + + for(auto & ufa : uf_application) { + for (auto & fapp : ufa.second.func_applications) { + TraverseRfExpr(fapp.result_map, func); + for( auto & a : fapp.arg_map) + TraverseRfExpr(a, func); + } + } // uf application + for( auto & a : assumptions) + TraverseRfExpr(a, func); + for( auto & a : additional_mapping) + TraverseRfExpr(a, func); + + for(auto & ptracker : phase_tracker) { + for(auto & a : ptracker.second.event_alias) + TraverseRfExpr(a.second, func); + for(auto & r : ptracker.second.rules) { + TraverseRfExpr(r.enter_rule, func); + TraverseRfExpr(r.exit_rule, func); + for(auto & act : r.enter_action) + TraverseRfExpr(act.RHS, func); + for(auto & act : r.exit_action) + TraverseRfExpr(act.RHS, func); } - for (const auto & n_st : customized_monitor) { - ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); - ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); - monitor_names.insert(n_st.first); + } // phase tracker + for (auto & pv : value_recorder) { + TraverseRfExpr(pv.second.condition, func); + TraverseRfExpr(pv.second.value, func); + } + // ALERT: do not handle customized recorder + + for (auto & instcond : inst_complete_cond) { + if ( instcond.second.type == InstructionCompleteCondition::ConditionType::SIGNAL ) + TraverseRfExpr(instcond.second.ready_signal, func); + for( auto & cond : instcond.second.start_condition) + TraverseRfExpr(cond, func); + } + + for (auto & a : global_invariants) + TraverseRfExpr(a, func); + +} // TraverseAllRfExpr + +void TypedVerilogRefinementMap::TraverseRfExpr(RfExpr & inout, std::function func) { + // DFS -- Note: we need to call func on the parent's child + // and make sure it runs the first + std::vector> parent_stack; + parent_stack.push_back(std::make_pair(inout,0U)); + while(!parent_stack.empty()) { + auto & lastlv = parent_stack.back(); + auto cnt = lastlv.first->get_child_cnt(); + auto & idx = lastlv.second; + if(idx >= cnt) { + parent_stack.pop_back(); + if(!parent_stack.empty()) { + func( parent_stack.back().first->child( parent_stack.back().second ) ); + ++ parent_stack.back().second; + } + continue; + } else { + // enter c[idx] + if(lastlv.first->get_child_cnt() == 0) { + func ( lastlv.first->child(idx) ); + ++idx; + } else { + parent_stack.push_back( std::make_pair(lastlv.first->child(idx), 0U )); + } + } + } // end of while + func(inout); +} // TraverseRfExpr + +// ------------------------------------------------------------------------------ + + +// helper for type inference +bool _compute_const(const RfExpr & in, unsigned & out) { + if(!in->is_constant()) + return false; + std::shared_ptr cst_ast_ptr = std::dynamic_pointer_cast(in); + if(cst_ast_ptr == nullptr) + return false; + auto bws = cst_ast_ptr->get_constant(); + auto base = std::get<0>(bws); + auto width = std::get<1>(bws); + out = StrToLong(std::get<2>(bws), base); + return true; +} + +RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in) { + + if(in->is_constant()) { + auto c = std::dynamic_pointer_cast(in)->get_constant(); + return RfMapVarType(std::get<1>(c)); + } else if (in->is_var()) { + auto n = std::dynamic_pointer_cast(in)->get_name(); + + auto pos_def_var = all_var_def_types.find(n.first); + + if(n.second) { // is a special name + // check special name first + if (pos_def_var != all_var_def_types.end()) + return RfMapVarType(pos_def_var->second.width); + + RfVarTypeOrig rtl_ila_vartype = typechecker(n.first); + if (!rtl_ila_vartype.type.is_unknown()) + return rtl_ila_vartype.type; + // then rtl ila name + } else { + // check rtl ila name first + // then special name + RfVarTypeOrig rtl_ila_vartype = typechecker(n.first); + if (!rtl_ila_vartype.type.is_unknown()) + return rtl_ila_vartype.type; + if (pos_def_var != all_var_def_types.end()) + return RfMapVarType(pos_def_var->second.width); - for (const auto & var_def : n_st.second.var_defs ) { - ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); - var_def_names.insert(var_def.first); + } // if # ... # else not + return RfMapVarType(); // unknown type + } else { // has op + if(in->get_op() == verilog_expr::voperator::STAR || + in->get_op() == verilog_expr::voperator::PLUS || + in->get_op() == verilog_expr::voperator::MINUS || + in->get_op() == verilog_expr::voperator::DIV || + in->get_op() == verilog_expr::voperator::POW || + in->get_op() == verilog_expr::voperator::MOD || + in->get_op() == verilog_expr::voperator::B_NEG || + in->get_op() == verilog_expr::voperator::B_AND || + in->get_op() == verilog_expr::voperator::B_OR || + in->get_op() == verilog_expr::voperator::B_XOR || + in->get_op() == verilog_expr::voperator::B_NAND || + in->get_op() == verilog_expr::voperator::B_NOR + ) { + // the max of the args + unsigned nchild = in->get_child_cnt(); + unsigned maxw = 0; + for(size_t idx = 0; idx < nchild; idx ++) { + RfMapVarType t = TypeInferTravserRfExpr( in->child(idx) ); + if(t.is_bv()) + maxw = std::max(maxw, t.unified_width()); + } + return RfMapVarType(maxw); + } else if ( + in->get_op() == verilog_expr::voperator::ASL || + in->get_op() == verilog_expr::voperator::ASR || + in->get_op() == verilog_expr::voperator::LSL || + in->get_op() == verilog_expr::voperator::LSR || + in->get_op() == verilog_expr::voperator::AT + ) { // the left type + assert( in->get_child_cnt() == 2); + return TypeInferTravserRfExpr(in->child(0)); + } else if ( in->get_op() == verilog_expr::voperator::DELAY) { + // arg 1: width of first + // arg 2: width is 1 !!! + assert(in->get_child_cnt() == 1 || in->get_child_cnt() == 2); + if (in->get_child_cnt() == 2) + return RfMapVarType(1); + + // set return type to be the same as the first one + return TypeInferTravserRfExpr(in->child(0)); + } else if ( + in->get_op() == verilog_expr::voperator::GTE || + in->get_op() == verilog_expr::voperator::LTE || + in->get_op() == verilog_expr::voperator::GT || + in->get_op() == verilog_expr::voperator::LT || + in->get_op() == verilog_expr::voperator::C_EQ || + in->get_op() == verilog_expr::voperator::L_EQ || + in->get_op() == verilog_expr::voperator::L_NEG || + in->get_op() == verilog_expr::voperator::L_AND || + in->get_op() == verilog_expr::voperator::L_OR + ) { + return RfMapVarType(1); + } else if (in->get_op() == verilog_expr::voperator::INDEX) { + RfMapVarType child_type = TypeInferTravserRfExpr(in->child(0)); + if (child_type.is_array()) + return child_type.unified_width(); // data width + // TODO: check index within ? + if (child_type.is_bv()) + return RfMapVarType(1); + return RfMapVarType(); // UNKNOWN type + } else if ( + in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || + in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { + unsigned diff; + bool succ = _compute_const(in->child(2), diff /*ref*/); + // TODO: check index within ? + if (succ) + return RfMapVarType(diff); + return RfMapVarType(); + } else if (in->get_op() == verilog_expr::voperator::RANGE_INDEX) { + assert(in->get_child_cnt() == 3); + unsigned l,r; + + bool succ = _compute_const(in->child(1), l /*ref*/), + succ = succ && _compute_const(in->child(2), r /*ref*/); + if(!succ) + return RfMapVarType(); + // TODO: check width! + return std::max(l,r)-std::min(l,r) + 1; + } else if (in->get_op() == verilog_expr::voperator::STORE_OP) { + // TODO: check width! + // actually not implemented + return TypeInferTravserRfExpr(in->child(0)); + } else if (in->get_op() == verilog_expr::voperator::TERNARY) { + auto left = TypeInferTravserRfExpr(in->child(1)); + auto right = TypeInferTravserRfExpr(in->child(2)); + if(left.is_array() || right.is_array()) + return left; // TODO: check compatibility + return RfMapVarType(std::max(left.unified_width(), right.unified_width())); + } else if (in->get_op() == verilog_expr::voperator::FUNCTION_APP) { + return RfMapVarType(); + } else if(in->get_op() == verilog_expr::voperator::CONCAT) { + unsigned nchild = in->get_child_cnt(); + unsigned sumw = 0; + for(size_t idx = 0; idx < nchild; idx ++) { + RfMapVarType t = TypeInferTravserRfExpr( in->child(idx) ); + if(t.is_bv()) + sumw += t.unified_width(); + else + return RfMapVarType(); // cannot decide } + return RfMapVarType(sumw); + } else if (in->get_op() == verilog_expr::voperator::REPEAT) { + assert( in->get_child_cnt() == 2 ); + unsigned ntimes; + if(!_compute_const(in->child(0), ntimes)) + return RfMapVarType(); + auto tp = TypeInferTravserRfExpr(in->child(1)); + return RfMapVarType(tp.unified_width()*ntimes); } -#undef ERRIF -} // CollectInternallyDefinedVars + } // end of else has op + return RfMapVarType(); +} // TypeInferTravserRfExpr +void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { + for(auto & name_delay_pair: aux_delays) { + if(name_delay_pair.second.width == 0) { + auto tp = TypeInferTravserRfExpr(name_delay_pair.second.signal); + ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; + ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_delay_pair.second.signal->to_verilog(); + name_delay_pair.second.width = tp.unified_width(); + } + } + for (auto & name_vr : value_recorder) { + if (name_vr.second.width == 0) { + auto tp = TypeInferTravserRfExpr(name_vr.second.value); + ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; + ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_vr.second.value->to_verilog(); + name_vr.second.width = tp.unified_width(); + } + } +} // ComputeDelayValueHolderWidth } // namespace rfmap diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 372099fbc..fd1474c50 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -463,7 +463,7 @@ std::string JsonRfmapParseValueRecorder(ValueRecorder & tracker, nlohmann::json tracker.value = ParseRfMapExprJson(*val); if(width && width->is_number_unsigned()) { tracker.width = width->get(); - } + } // if you don't write width or use a string then it is 0 else tracker.width = 0; return ""; @@ -506,7 +506,8 @@ VerilogRefinementMap::VerilogRefinementMap svmp.externmem_map.push_back(ExternalMemPortMap()); auto & extmem_ports = i.value(); - JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); + bool succ = JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); + ENSURE(succ, "fail to parse external memory map"); } else if (i.value().is_array()) { ERRIF( i.value().empty(), ("Empty list for " + sname) ); @@ -526,7 +527,8 @@ VerilogRefinementMap::VerilogRefinementMap svmp.externmem_map.push_back(ExternalMemPortMap()); auto & extmem_ports = idx_obj_pair.value(); - JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); + bool succ = JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); + ENSURE(succ, "fail to parse external memory map"); } } else { svmp.type = IlaVarMapping::StateVarMapType::CONDITIONAL; @@ -889,9 +891,16 @@ VerilogRefinementMap::VerilogRefinementMap ws.max_bound = max_bound->get(); } if (start_condition) { - ENSURE(start_condition->is_string(), "`start_condition` should be a string"); - ws.start_condition = ParseRfMapExprJson(*start_condition); - } + if (start_condition->is_string()) { + ws.start_condition.push_back( ParseRfMapExprJson(*start_condition) ); + } else { + ENSURE(start_condition->is_array(), "`start_condition` should be a string or array of strings"); + for (auto & cond : *start_condition) { + ENSURE(cond.is_string(), "`start_condition` should be a string or array of strings"); + ws.start_condition.push_back( ParseRfMapExprJson(cond)); + } + } // end if start condition is string + } // end if start condition } // for each instr` } // if instrs From 7d79862050f7e7ac3581cd4ad307bece24f5b227 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 10 Jun 2021 20:43:18 -0400 Subject: [PATCH 13/78] update vexpparser ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index b1ed8f99d..cba0f43bb 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit b1ed8f99d30c367bc3c0712bafce9622ee02bdba +Subproject commit cba0f43bb6bba4d7f1842ee417532231676511e6 From 89078844ad24f43f98280b96522a41b13dc30b8a Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 10 Jun 2021 20:43:36 -0400 Subject: [PATCH 14/78] type check rewrite --- include/ilang/rfmap-in/rfmap_typecheck.h | 66 +++++++++++ include/ilang/rfmap-in/rfvar_type.h | 7 +- src/rfmap-in/rfmap_typecheck.cc | 145 ++++++++++++++++++++++- 3 files changed, 213 insertions(+), 5 deletions(-) diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index 6b3f3657c..0b0f6184f 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -27,8 +27,70 @@ class TypeAnnotation : // allow instantiation virtual void should_not_instantiate() override {} + TypeAnnotation() {} + TypeAnnotation(const ::ilang::rfmap::RfVarTypeOrig & r): + ::ilang::rfmap::RfVarTypeOrig(r) {} }; // TypeAnnotation +struct VarReplacement { + RfExpr origvar; // this is certainly a var + RfExpr newvar; // this is certainly a var + std::string range_o; // but this could be different + + VarReplacement(const RfExpr & o, const RfExpr & n, const std::string & r = "") : + origvar(o), newvar(n), range_o (r) {} + + std::string get_orig_name() const { + if(is_orig_var_array() && !range_o.empty()) + return ( + std::dynamic_pointer_cast + (origvar)->get_name().first + "[" + range_o + "]" + ); + // else + return std::dynamic_pointer_cast( + origvar)->get_name().first; + } + + std::string get_new_name() const{ + //if(is_orig_var_array() && !range_o.empty()) + // return ( + // std::dynamic_pointer_cast + // (origvar)->get_name().first + "_" + ReplaceAll(range_o,"'","") + "_" + // ); + // else + return std::dynamic_pointer_cast + (newvar)->get_name().first; } + + RfVarTypeOrig get_type_new() const { + /*if(is_orig_var_array() && !range_o.empty()) { + TypeAnnotation ret; + ret.type = RfMapVarType(get_type_orig().type.data_width); + ret.var_ref_type = TypeAnnotation::VARTYPE::NOTVAR; + return ret; + }*/ + return get_type_orig(); + } + +private: + RfVarTypeOrig get_type_orig() const { + auto annotation_ptr = newvar->get_annotation(); + return annotation_ptr?*annotation_ptr:RfVarTypeOrig(); + } + + bool is_orig_rtlv() const { + return get_type_orig().var_ref_type == RfVarTypeOrig::VARTYPE::RTLV; + } + bool is_orig_ila_state() const{ + return get_type_orig().var_ref_type == RfVarTypeOrig::VARTYPE::ILAS; + } + bool is_orig_ila_input() const{ + return get_type_orig().var_ref_type == RfVarTypeOrig::VARTYPE::ILAI; + } + + bool is_orig_var_array() const { + return get_type_orig().type.is_array(); + } +}; // type infer rules @@ -73,6 +135,10 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { // ... ? void TraverseAllRfExpr(std::function func); + RfExpr ReplacingRtlIlaVar(const RfExpr & in, bool replace_dot); + + std::map var_replacement; // including rtl/ilas/ilav + protected: void CollectInternallyDefinedVars(); diff --git a/include/ilang/rfmap-in/rfvar_type.h b/include/ilang/rfmap-in/rfvar_type.h index 954a13564..5045146a4 100644 --- a/include/ilang/rfmap-in/rfvar_type.h +++ b/include/ilang/rfmap-in/rfvar_type.h @@ -34,7 +34,7 @@ class RfVarTypeOrig { public: enum class VARTYPE { NOTVAR, /*also unknown type*/ - ILAS /*state var*/, + ILAS, /*state var*/ ILAI, /*ila input*/ RTLV, /*rtl signal*/ PHASE, /*stage name*/ @@ -47,6 +47,11 @@ class RfVarTypeOrig { VARTYPE var_ref_type; RfMapVarType type; + // constructur + RfVarTypeOrig() : var_ref_type(VARTYPE::NOTVAR) {} + RfVarTypeOrig(const RfVarTypeOrig & r) : + var_ref_type(r.var_ref_type), + type(r.type) {} }; // class RfVarType diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 16b50000b..133119e7a 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -35,17 +35,137 @@ TypedVerilogRefinementMap::TypedVerilogRefinementMap( // determine the types of delay and value holder ComputeDelayValueHolderWidth(); - - // - AnnotateSignalsAndCollectRtlVars(); - } // TypedVerilogRefinementMap::TypedVerilogRefinementMap + +RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( + const RfExpr & in, + bool replace_internal_wire) +{ + // skip state memory mapped + // provide a function to ReplExpr... + auto tp_annotate = in->get_annotation(); + + if(in->is_var()) { + auto var_ptr = std::dynamic_pointer_cast(in); + ILA_NOT_NULL(var_ptr); + auto n = var_ptr->get_name(); + + if(var_replacement.find(n.first) != var_replacement.end()) { + return var_replacement.at(n.first).newvar; + } + + RfVarTypeOrig tp; + + if(tp_annotate != nullptr) + tp = *tp_annotate; + if(tp.type.is_unknown()) { + auto pos_def_var = all_var_def_types.find(n.first); + auto rtl_ila_tp = typechecker(n.first); + + if(n.second) { // if it is special name + if(pos_def_var != all_var_def_types.end()) { + tp.var_ref_type = RfVarTypeOrig::VARTYPE::DEFINE_VAR; + tp.type = RfMapVarType(pos_def_var->second.width); + } else { + tp = rtl_ila_tp; + } + } else { // if it is not special name + if(!rtl_ila_tp.type.is_unknown()) + tp = rtl_ila_tp; + else if(pos_def_var != all_var_def_types.end()) { + tp.var_ref_type = RfVarTypeOrig::VARTYPE::DEFINE_VAR; + tp.type = RfMapVarType(pos_def_var->second.width); + } + } + // put back the annotation? in new expr? + } // end if it is unknown + + bool is_array = tp.type.is_array(); + if(!replace_internal_wire || is_array) { + auto ret_copy = std::make_shared(*var_ptr); + ret_copy->set_annotation(std::make_shared(tp)); + return ret_copy; + // 1 will not do replacement + // 2 will not record that + } + + if(tp.var_ref_type == RfVarTypeOrig::VARTYPE::RTLV) { + auto new_name = ReplaceAll(n.first, ".", "__DOT__"); + auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); + new_node->set_annotation(std::make_shared(tp)); + var_replacement.emplace(n.first, VarReplacement(in, new_node)); + return new_node; + } else if (tp.var_ref_type == RfVarTypeOrig::VARTYPE::ILAI) { + auto new_name = "__ILA_I_" + n.first; + auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); + new_node->set_annotation(std::make_shared(tp)); + var_replacement.emplace(n.first, VarReplacement(in, new_node)); + return new_node; + } else if (tp.var_ref_type == RfVarTypeOrig::VARTYPE::ILAS) { + auto new_name = "__ILA_SO_" + n.first; + auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); + new_node->set_annotation(std::make_shared(tp)); + var_replacement.emplace(n.first, VarReplacement(in, new_node)); + return new_node; + } + + auto ret_copy = std::make_shared(*var_ptr); + ret_copy->set_annotation(std::make_shared(tp)); + return ret_copy; // will return the annotated one anyway + } // is_var + else if (in->is_constant()) { + return in; // no annotation needed + } else { + // check type + auto ret_copy = std::make_shared(*in); + for (size_t idx = 0 ; idx < ret_copy->get_child_cnt(); ++ idx) { + ret_copy->child(idx) = + ReplacingRtlIlaVar( + ret_copy->get_child().at(idx), replace_internal_wire); + } // for each child + + if(ret_copy->child(0)->is_var() && ret_copy->get_op() == verilog_expr::voperator::INDEX) { + std::shared_ptr annotate = + ret_copy->child(0)->get_annotation(); + if(annotate != nullptr && annotate->type.is_array()) { + assert(ret_copy->get_child_cnt() == 2); + auto array_index = ret_copy->child(1); + auto n = std::dynamic_pointer_cast + ( ret_copy->child(0) )->get_name(); + + if( array_index->is_constant() ) { + std::string range_o = array_index->to_verilog(); + + auto new_name = ReplaceAll(n.first, ".", "__DOT__") + "_"+ ReplaceAll(range_o,"'","") +"_"; + auto orig_name = n.first+"["+range_o+"]"; + + if(var_replacement.find(orig_name) != var_replacement.end()) + return var_replacement.at(orig_name).newvar; + + auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(annotate->type.unified_width()); + new_node->set_annotation(new_annotation); + + var_replacement.emplace(orig_name, VarReplacement(in, new_node, range_o)); + return new_node; + } else { + ILA_CHECK(false) << "FIXME: currently does not handle dynamic index into array"; + } // end if it is const + } + } + return ret_copy; + } + assert(false); // Should not be reachable +} // AnnotateSignalsAndCollectRtlVars + void TypedVerilogRefinementMap::collect_inline_value_recorder_func(RfExpr & inout) { if(inout->get_op() == verilog_expr::voperator::AT) { auto recorder_name = new_id()+"recorder"; auto new_node = verilog_expr::VExprAst::MakeVar(recorder_name); + verilog_expr::VExprAst::VExprAstPtrVec child(inout->get_child()); ValueRecorder tmp_value_recorder; tmp_value_recorder.width = 0; @@ -419,6 +539,13 @@ void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_delay_pair.second.signal->to_verilog(); name_delay_pair.second.width = tp.unified_width(); + + // replendish all_var_def_types + VarDef internal_var_def; + internal_var_def.width = tp.unified_width(); + internal_var_def.type = VarDef::var_type::REG; + + all_var_def_types.emplace(name_delay_pair.first, internal_var_def); } } for (auto & name_vr : value_recorder) { @@ -427,8 +554,18 @@ void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_vr.second.value->to_verilog(); name_vr.second.width = tp.unified_width(); + + // replendish all_var_def_types + VarDef internal_var_def; + internal_var_def.width = tp.unified_width(); + internal_var_def.type = VarDef::var_type::REG; + + all_var_def_types.emplace(name_vr.first, internal_var_def); } } + // replendish internal defined vars + + } // ComputeDelayValueHolderWidth From 1f925c2032db0ae91c38c8defe458f47cd85eba6 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 15 Jun 2021 16:26:05 -0400 Subject: [PATCH 15/78] vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index cba0f43bb..882a86bff 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit cba0f43bb6bba4d7f1842ee417532231676511e6 +Subproject commit 882a86bffae53166f03adb00f808d89b948b9491 From 480e4d06cb373bf7786f974975842cc28a3c862a Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 15 Jun 2021 16:27:03 -0400 Subject: [PATCH 16/78] test --- include/ilang/rfmap-in/rfmap_typecheck.h | 11 ++- include/ilang/rfmap-in/verilog_rfmap.h | 16 ++++ include/ilang/verilog-out/verilog_gen.h | 6 -- include/ilang/vtarget-out/absmem.h | 85 ------------------- include/ilang/vtarget-out/directive.h | 58 ------------- .../ilang/vtarget-out/supplementary_info.h | 60 ------------- include/ilang/vtarget-out/var_extract.h | 68 --------------- include/ilang/vtarget-out/vtarget_gen.h | 68 +++++++-------- include/ilang/vtarget-out/vtarget_gen_impl.h | 76 +++++------------ test/t_inv_syn.cc | 26 +++--- test/t_vtarget_gen.cc | 2 +- 11 files changed, 95 insertions(+), 381 deletions(-) delete mode 100644 include/ilang/vtarget-out/absmem.h delete mode 100644 include/ilang/vtarget-out/supplementary_info.h delete mode 100644 include/ilang/vtarget-out/var_extract.h diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index 0b0f6184f..1785f5bcd 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -114,6 +114,12 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { const std::string & instcond_json_file, var_typecheck_t type_checker ); + + TypedVerilogRefinementMap( + const VerilogRefinementMap & refinement, + var_typecheck_t type_checker + ); + // references // - named defined vars with type @@ -140,6 +146,8 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { std::map var_replacement; // including rtl/ilas/ilav protected: + + void initialize(); void CollectInternallyDefinedVars(); void TraverseRfExpr(RfExpr & inout, std::function func) ; @@ -160,8 +168,7 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { RfMapVarType TypeInferTravserRfExpr(const RfExpr & in); void ComputeDelayValueHolderWidth(); - -}; +}; // TypedVerilogRefinementMap } // namespace rfmap } // namespace ilang diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 90f494ab8..d4aebc5c0 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -134,9 +134,22 @@ struct ValueRecorder { // this is not directly used struct SignalDelay { + + SignalDelay(const RfExpr & _signal, unsigned n_cycle) : + delay_type(delay_typeT::SINGLE), signal(_signal), + num_cycle(n_cycle), width(0), upper_bnd(0) {} + + SignalDelay(const RfExpr & _signal, unsigned n_cycle, unsigned u_bnd) : + delay_type(u_bnd == 0 ? delay_typeT::TO_INFINITE : delay_typeT::RANGE), + signal(_signal), + num_cycle(n_cycle), width(0), upper_bnd(u_bnd) {} + + enum class delay_typeT { SINGLE, RANGE, TO_INFINITE } delay_type; RfExpr signal; unsigned num_cycle; unsigned width; + + unsigned upper_bnd; }; struct PhaseTracker { @@ -198,6 +211,9 @@ struct VerilogRefinementMap { std::map inst_complete_cond; std::vector global_invariants; + // ---------------------- supplementary_info ------------------------------- // + std::map width_info; // this is needed in case our width inference failed + // member function : return true if checking passed bool SelfCheckField() const; diff --git a/include/ilang/verilog-out/verilog_gen.h b/include/ilang/verilog-out/verilog_gen.h index 3005506eb..b6d3550b7 100644 --- a/include/ilang/verilog-out/verilog_gen.h +++ b/include/ilang/verilog-out/verilog_gen.h @@ -174,12 +174,6 @@ class VerilogGeneratorBase { : extMem(ExternalMem), fcOpt(funcOpt), start_signal(gen_start), pass_node_name(pass_name), reg_random_init(rand_init), expand_mem(ExpandMem), collect_ite_unknown_update(CollectIteUnknownUpdate) {} - /// Overwrite configuration, used by vtarget gen - VlgGenConfig(const VlgGenConfig& c, bool ExternalMem, funcOption funcOpt, - bool gen_start, bool rand_init, bool ExpandMem, bool CollectIteUnknownUpdate) - : extMem(ExternalMem), fcOpt(funcOpt), start_signal(gen_start), - pass_node_name(c.pass_node_name), reg_random_init(rand_init), - expand_mem(ExpandMem), collect_ite_unknown_update(CollectIteUnknownUpdate) {} // set other fields if there are such need (?) }; // end of struct VlgGenConfig diff --git a/include/ilang/vtarget-out/absmem.h b/include/ilang/vtarget-out/absmem.h deleted file mode 100644 index 7211d41bd..000000000 --- a/include/ilang/vtarget-out/absmem.h +++ /dev/null @@ -1,85 +0,0 @@ -/// \file Header for generating abstract memory -// --- Hongce Zhang - -#ifndef ILANG_VTARGET_OUT_ABS_MEM_H__ -#define ILANG_VTARGET_OUT_ABS_MEM_H__ - -#include -#include -#include -#include -#include - -#include -#include - -namespace ilang { - -/// \brief a struct to store abstract memory -struct VlgAbsMem { - // ---------------------- TYPES --------------- // - /// type of read port - using rport_t = VerilogGeneratorBase::rport_t; - /// type of write port - using wport_t = VerilogGeneratorBase::wport_t; - - // ---------------------- MEMBERS --------------- // - /// verilog read ports - std::map vlg_rports; - /// verilog write ports - std::map vlg_wports; - /// ila read ports - std::map ila_rports; - /// ila write ports - std::map ila_wports; - - /// whether to abstract the memory read - bool read_abstract; - /// how many are considered to be concrete - unsigned concrete_level; - /// widths , 0 stands for unknown - unsigned data_width; - /// widths , 0 stands for unknown - unsigned addr_width; - /// which ila state it is mapped to - std::string ila_map_name; - /// the name in rfmap - std::string mem_name; - /// the assumptions it has - std::vector assumpts; - -private: - /// Whether the module is checked to be okay - bool checked; - /// track what kind of memory need to export, positive for w-abs, negative for - /// r-w-abs - static std::set concrete_level_encountered; - -public: - // ------------------CONSTRUCTOR ----------- // - /// do nothing - VlgAbsMem(); - // ------------------ MEMBERS ------------- // - /// SetAddrWidth, if already set, and different -> error - void SetAddrWidth(unsigned w); - /// SetDataWidth - void SetDataWidth(unsigned w); - /// Get the memeq signal name - std::string MemEQSignalName() const; - /// Get the memory module instantiation string, it will also - /// add signals when necessary - std::string - GeneratingMemModuleSignalsInstantiation(VerilogGeneratorBase& gen, - const std::string& endCond); - /// Output the memory module to the stream - static void OutputMemFile(std::ostream& os, bool avoid_issue_stage); - /// Return true if there are abs mem used (strategy : ALL -> AUTO) - static bool hasAbsMem(); - /// reset concrete_level (per-target). - static void ClearAbsMemRecord(); - -}; // class VlgAbsMem - -}; // namespace ilang - -#endif // ILANG_VTARGET_OUT_ABS_MEM_H__ diff --git a/include/ilang/vtarget-out/directive.h b/include/ilang/vtarget-out/directive.h index 03b42fd94..5b0d3f591 100644 --- a/include/ilang/vtarget-out/directive.h +++ b/include/ilang/vtarget-out/directive.h @@ -12,7 +12,6 @@ #include #include -#include namespace ilang { @@ -65,13 +64,6 @@ class IntefaceDirectiveRecorder { using wport_t = VerilogGeneratorBase::wport_t; public: - /// Return if a string 'c' begins with string 's' - static bool beginsWith(const std::string& c, const std::string& s); - /// Return true if 'c' is special input directive - static bool isSpecialInputDir(const std::string& c); - /// Check for compatibility - static bool isSpecialInputDirCompatibleWith(const std::string& c, - const SignalInfoBase& vlg_sig); /// Check if an interface needs to be declare as top module I/O // static bool interfaceDeclareTop(const std::string & c); // --- more to added @@ -94,39 +86,7 @@ class IntefaceDirectiveRecorder { /// Register the extra wire to connect (for extra wire) void RegisterExtraWire(const std::string& io_name, const std::string& outside_name); - /// Register the connection of signals related to a memory - std::string ConnectMemory(const std::string& directive, - const std::string& ila_state_name, - const std::map& rports, - const std::map& wports, - int ila_addr_width, int ila_data_width, - bool abs_read); - /// Insert memory abstractions' assumptions - void InsertAbsMemAssmpt(assmpt_inserter_t inserter); - /// Setting the memory abstraction name, but does not enforce any equality - /// there - void SetMemName(const std::string& directive, - const std::string& ila_state_name, bool abs_read); - - /// Setting the memory abstraction name, and width... - /// but does not enforce any equality - /// there - void SetMemNameAndWidth(const std::string& directive, - const std::string& ila_state_name, bool abs_read, int, - int); - - /// Return the memory instantiation string - std::string GetAbsMemInstString(VerilogGeneratorBase& gen, - const std::string& endCond); - /// Check if some port has been connected, - /// if not, connect it to the wire_name (will not create wire!) - /// if connected, will warn and refuse to connect - /// should be called before GetAbsMemInstString - /// return the wire name to create (but no need to create if it is empty) - std::pair - KeepMemoryPorts(const std::string& mem_name, const std::string& port_name, - bool caller_build_wire); protected: /// a sanity check for module instantiation string gen, check if all the vlg @@ -148,8 +108,6 @@ class IntefaceDirectiveRecorder { vlg_sig_vec_t output_wires; /// wires to be declared as just wire vlg_sig_vec_t internal_wires; - /// ila-mem-name -> abs - std::map abs_mems; /// whether to reset this vlg (reset to rst or dummy_reset) bool _reset_vlg; @@ -159,22 +117,6 @@ class IntefaceDirectiveRecorder { **MEM**.? */ -/// \brief a class to handle state-mapping directives in the refinement -/// relations -class StateMappingDirectiveRecorder { -public: - // ------------------------------ HELPER - // ------------------------------------// - /// a function to determine if a state map refstr is special directie (**???) - static bool isSpecialStateDir(const std::string& c); - /// a function to determine if a state map refstr is special directie (**???) - static bool isSpecialStateDirMem(const std::string& c); - /// a function to determine if a function name is an unknown special directive - static bool isSpecialUnknownFunctionName(const std::string &funcname); - /// a function to determine if a function (no arg) is an unknown special directive - static bool isSpecialUnknownFunction(const FuncPtr &func_ptr); -}; // class StateMappingDirectiveRecorder - }; // namespace ilang #endif // ILANG_VTARGET_OUT_DIRECTIVE_H__ diff --git a/include/ilang/vtarget-out/supplementary_info.h b/include/ilang/vtarget-out/supplementary_info.h deleted file mode 100644 index b832ffd5f..000000000 --- a/include/ilang/vtarget-out/supplementary_info.h +++ /dev/null @@ -1,60 +0,0 @@ -/// \file Header for Verilog Verification Supplementary Information -/// this is useful to provide our tool information that it cannot -/// or may not be able to figure out itself - -#ifndef SUPPLEMENTARY_INFO_H__ -#define SUPPLEMENTARY_INFO_H__ - -#include "nlohmann/json.hpp" - -#include -#include - -namespace ilang { - -/// \brief the class to hold supplementary information -struct VlgTgtSupplementaryInfo { - - // ----------------------- TYPE ------------------------ // - struct reset_config_t { - /// whether to enforce no reset constraint - bool no_reset_after_starting_state; - /// how many cycles should reset signal holds - unsigned reset_cycles; - /// the reset sequence: list of (signal name -> value) map (not supported - /// yet) - // we anticipate in the reset sequence, you don't need a wide signal - std::vector> reset_sequence; - /// Future work: reset state: signame -> signal value (valid vlog expr) (not - /// supported yet) - std::map reset_state; - /// Constructor, set default parameters - reset_config_t() : no_reset_after_starting_state(false), reset_cycles(1) {} - }; // struct reset_config_t - - // ----------------------- MEMBERS ------------------------ // - /// the width info - std::map width_info; - /// how to treat a memory , the reason of using bool instead of enum is - /// because I don't want the verilog-out part to include this file, so its - /// type should be a generic type - typedef bool memory_export_type; -#define memory_export_type_internal false -#define memory_export_type_external true - /// the map of memory - std::map memory_export; - /// the port to keep : memory_name -> (port and its connector) - std::map> memory_ports; - /// The reset annotation for CoSA & Yosys (Jasper should be fine...) - reset_config_t cosa_yosys_reset_config; - - // ----------------------- METHODS ------------------------ // - /// Constructor - default - VlgTgtSupplementaryInfo(); - /// Parse annotations from Json - void FromJson(nlohmann::json& vmap); -}; // struct VlgTgtSupplementaryInfo - -}; // namespace ilang - -#endif // SUPPLEMENTARY_INFO_H__ diff --git a/include/ilang/vtarget-out/var_extract.h b/include/ilang/vtarget-out/var_extract.h deleted file mode 100644 index b8e4ec89c..000000000 --- a/include/ilang/vtarget-out/var_extract.h +++ /dev/null @@ -1,68 +0,0 @@ -/// \file Header of variable extractor -/// This is use to extract variable from expression (string) -/// See whether it is ila-state(I/O) / vlg-state and ... -/// and change their name if needed and generate a string -// --- Hongce Zhang - -#ifndef ILANG_VTARGET_OUT_VAR_EXTRACT_H__ -#define ILANG_VTARGET_OUT_VAR_EXTRACT_H__ - -#include -#include -#include - -namespace ilang { - -class VarExtractor { - -public: - /// Type of tokens - typedef enum { KEEP = 0, ILA_S, ILA_IN, VLG_S, UNKN_S, NUM } token_type; - /// Tokens - typedef std::pair token; - /// Type of function pointer of string judger - typedef std::function str_j; - /// Type of function pointer of string replacer - typedef std::function str_r; - -protected: - /// token from parsed string - std::vector _tokens; - /// a pointer to string judger (is ila state?) - str_j _is_ila_state; - /// a pointer to string judge (is ila input?) - str_j _is_ila_input; - /// a pointer to string judger (is vlg signal?) - str_j _is_vlg_sig; - -public: - // ---------------------- CONSTRUCTOR ----------------- // - VarExtractor(str_j is_ila_state, str_j is_ila_input, str_j is_vlg_sig); - // ---------------------- METHODS ----------------- // - /// Parse a string and populate the token vector, will clear the _tokens - /// storage - void - ParseToExtract(const std::string& in, - bool force_vlg_statename = - false); // the later is only used in dealing w. invariants - /// Traverse the tokens, see if replace is needed - void ForEachTokenReplace( - str_r replacer); // you can return the same so it will not be replaced - /// Get back string - std::string GenString() const; - /// A shortcut to do all at once - std::string Replace(const std::string& in, bool force_vlg_statename, - str_r replacer) { - ParseToExtract(in, force_vlg_statename); - ForEachTokenReplace(replacer); - return GenString(); - } - // ---------------------- HELPERS ----------------- // - static bool contains_mod_inst_name(const std::string& s, - const std::string& mi); - -}; // class VarExtractor - -}; // namespace ilang - -#endif // ILANG_VTARGET_OUT_VAR_EXTRACT_H__ diff --git a/include/ilang/vtarget-out/vtarget_gen.h b/include/ilang/vtarget-out/vtarget_gen.h index 980b247d7..4564a7151 100644 --- a/include/ilang/vtarget-out/vtarget_gen.h +++ b/include/ilang/vtarget-out/vtarget_gen.h @@ -28,7 +28,7 @@ class VlgVerifTgtGenBase { /// Type of the backend: /// Pono, JasperGold, CHC for chc solver, AIGER for abc // YOSYS is for invariant synthesis use - typedef enum { + enum class backend_selector{ NONE = 0, JASPERGOLD = 2, YOSYS = 128, // 10000000 @@ -39,17 +39,24 @@ class VlgVerifTgtGenBase { ABCPDR = YOSYS + 16, // 10010000 PONO = YOSYS + 32, // 10100000 RELCHC = YOSYS + 64 // 11000000 - } backend_selector; + }; + + + /// decide if a backend needs Yosys + static bool backend_needs_yosys(backend_selector b) { + return (int(b) & int(backend_selector::YOSYS)) == int(backend_selector::YOSYS); + } + /// Type of invariant synthesis backend - typedef enum { - Z3 = Z3PDR ^ YOSYS, - GRAIN = GRAIN_SYGUS ^ YOSYS, - ABC = ABCPDR ^ YOSYS, - ELDERICA = ELD_CEGAR ^ YOSYS,// 0001010 - NOSYN = YOSYS // 1000000 - } synthesis_backend_selector; + enum class synthesis_backend_selector { + Z3 = int(backend_selector::Z3PDR) ^ int(backend_selector::YOSYS), + GRAIN = int(backend_selector::GRAIN_SYGUS) ^ int(backend_selector::YOSYS), + ABC = int(backend_selector::ABCPDR) ^ int(backend_selector::YOSYS), + ELDERICA = int(backend_selector::ELD_CEGAR) ^ int(backend_selector::YOSYS),// 0001010 + NOSYN = int(backend_selector::YOSYS) // 1000000 + } ; /// Type of the chc target - enum _chc_target_t { CEX, INVCANDIDATE, GENERAL_PROPERTY }; + enum class _chc_target_t { CEX, INVCANDIDATE, GENERAL_PROPERTY }; /// Verilog Target Generation Configuration typedef struct _vtg_config { /// Preheader Content : will use in all targets @@ -65,18 +72,14 @@ class VlgVerifTgtGenBase { /// Does not insert assertions of variable mapping /// if an instruction does not update that var bool OnlyCheckInstUpdatedVars; // true - /// A shortcut for SetUpdate(s, Ite(c, v, __unknown__() )) - /// will only gnerate map like : ( ila.c => ila.v == vlg.v ) - /// In this case, you don't need to deal with unknown in func map - /// nor do you need to create a special refinement map - /// function has to be defined as __unknown__X - bool IteUnknownAutoIgnore; // false - /// whether to remove the extra issue cycle and starts from reset - bool VerificationSettingAvoidIssueStage; + /// Whether to pass Verilog node name in reference + /// generation + bool VerilogGenPassNodeName; + /// Configure the behavior of INV target, if false, /// will not check synthesized invariants by default (unless call /// generateInvariantVerificationTarget) if true, will check by default - enum _validate_synthesized_inv { + enum class _validate_synthesized_inv { NOINV, CANDIDATE, CONFIRMED, @@ -87,7 +90,7 @@ class VlgVerifTgtGenBase { /// Whether to force the instruction check to start from reset state bool ForceInstCheckReset; /// For Pono target generator : whether to force NEW/OLD port declaration - enum { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; + enum class PortDeclStyleT { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; /// Generate a jg script to help validate Pono? bool PonoGenJgTesterScript; /// For Pono backend: do we add (* keep *)? default true, however, it can be @@ -100,7 +103,7 @@ class VlgVerifTgtGenBase { /// use the default setting : NOTIFY_PANIC /// in some rare cases, you may want to use JasperGold after it /// in that case, it is okay to just ignore it - enum PonoDotReferenceNotify_t { + enum class PonoDotReferenceNotify_t { NOTIFY_PANIC = 0, NOTIFY_WARNING = 1, NOTIFY_IGNORE = 2 @@ -128,12 +131,11 @@ class VlgVerifTgtGenBase { bool YosysSmtArrayForRegFile; /// How to encode Verilog state /// DataSort seems to use PDR engine - typedef enum { + enum class YosysStateSortT { UnintepretedFunc /*not supported*/, Datatypes, /*by default*/ BitVec /*optional for property check, not inv-syn*/ - } _state_sort_t; - _state_sort_t YosysSmtStateSort; + } YosysSmtStateSort; /// for invariant synthesis do we keep memory abstraction in Verilog /// you can keep it true, untill the invariant refers to some memory there bool InvariantSynthesisKeepMemory; @@ -193,13 +195,12 @@ class VlgVerifTgtGenBase { /// ABC option : whether to minimize invariant bool AbcMinimizeInv; /// ABC option : the way to handle assumptions - typedef enum _abc_assumption_style_t { + enum class AbcAssumptionStyle_t { AigMiterExtraOutput = 0, // Use AIG's extra output to represent, cannot use with GLA AssumptionRegister = 1 // Use extra register, may have issues in interpreting the invariant - } AbcAssumptionStyle_t; - AbcAssumptionStyle_t AbcAssumptionStyle; + } AbcAssumptionStyle; // ----------- Extended Options for Grain -------------- // @@ -207,13 +208,12 @@ class VlgVerifTgtGenBase { _vtg_config() : target_select(BOTH), CheckThisInstructionOnly(""), InstructionNoReset(true), OnlyCheckInstUpdatedVars(true), - IteUnknownAutoIgnore(false), - VerificationSettingAvoidIssueStage(false), - ValidateSynthesizedInvariant(ALL), + VerilogGenPassNodeName(false), + ValidateSynthesizedInvariant(_validate_synthesized_inv::ALL), // ----------- Options for Pono settings -------------- // - ForceInstCheckReset(false), PortDeclStyle(AUTO), - PonoGenJgTesterScript(false), PonoAddKeep(true), + ForceInstCheckReset(false), PortDeclStyle(PortDeclStyleT::AUTO), + PonoGenJgTesterScript(false), PonoAddKeep(false), PonoOtherSolverOptions(""), PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), MaxBound(127), OnlyAssumeUpdatedVarsEq(false), @@ -225,7 +225,7 @@ class VlgVerifTgtGenBase { YosysUndrivenNetAsInput(true), YosysSmtFlattenHierarchy(true), YosysSmtFlattenDatatype(false), YosysPropertyCheckShowProof(false), YosysSmtArrayForRegFile(false), - YosysSmtStateSort(Datatypes), InvariantSynthesisKeepMemory(true), + YosysSmtStateSort(YosysStateSortT::Datatypes), InvariantSynthesisKeepMemory(true), InvariantCheckKeepMemory(true), InvariantSynthesisReachableCheckKeepOldInvariant(false), @@ -245,7 +245,7 @@ class VlgVerifTgtGenBase { // ----------- Options for ABC -------------- // AbcUseGla(false), AbcGlaTimeLimit(500), AbcGlaFrameLimit(200), AbcUseCorr(false), AbcUseAiger(true), AbcMinimizeInv(false), - AbcAssumptionStyle(_abc_assumption_style_t::AigMiterExtraOutput) + AbcAssumptionStyle(AbcAssumptionStyle_t::AigMiterExtraOutput) {} } vtg_config_t; diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 461e7da94..651083d49 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -23,11 +23,10 @@ #include #include #include +#include #include #include #include -#include -#include #include namespace ilang { @@ -38,13 +37,6 @@ class VlgSglTgtGen { // --------------------- TYPE DEFINITION ------------------------ // /// Type of the target typedef enum { INVARIANTS, INSTRUCTIONS, INV_SYN_DESIGN_ONLY } target_type_t; - /// Type of the ready condition - typedef enum { - NA = 0, - READY_SIGNAL = 1, - READY_BOUND = 2, - BOTH = 3 - } ready_type_t; /// Per func apply counter typedef std::map func_app_cnt_t; /// Type of the verification backend @@ -73,19 +65,17 @@ class VlgSglTgtGen { /// \param[in] which backend to use, it needs this info to gen proper /// properties VlgSglTgtGen( - const std::string& output_path, // will be a sub directory of the - // output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const VerilogGenerator::VlgGenConfig& config, nlohmann::json& _rf_vmap, - nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo& _supplementary_info, - VerilogInfo* _vlg_info_ptr, const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector backend, - const target_type_t& target_tp, advanced_parameters_t* adv_ptr); + const std::string& output_path, // will be a sub directory of the output_path of its parent + const InstrPtr& instr_ptr, // which could be an empty pointer, and it will + // be used to verify invariants + const InstrLvlAbsPtr& ila_ptr, + const rfmap::VerilogRefinementMap & refinement, + VerilogInfo* _vlg_info_ptr, + const std::string& wrapper_name, + const std::vector& implementation_srcs, + const std::vector& implementation_include_path, + const vtg_config_t& vtg_config, backend_selector backend, + const target_type_t& target_tp, advanced_parameters_t* adv_ptr); /// Destructor: do nothing , most importantly it is virtual virtual ~VlgSglTgtGen() {} @@ -109,32 +99,18 @@ class VlgSglTgtGen { VerilogGeneratorBase vlg_wrapper; /// Generator for the ila verilog VerilogGenerator vlg_ila; - /// inteface directive recorder + /// Verilog module connection IntefaceDirectiveRecorder _idr; - /// state directive recorder - StateMappingDirectiveRecorder _sdr; + + /// The refinement map with type checked + rfmap::TypedVerilogRefinementMap refinement_map; + /// Analyzer for the implementation // we don't know the module name, before analyzing the rfmap. so we cannot // initialize in the beginning VerilogInfo* vlg_info_ptr; - /// variable extractor to handle property expressions - VarExtractor _vext; - /// refinement relation variable mapping - nlohmann::json& rf_vmap; - /// refinement relation instruction conditions - nlohmann::json& rf_cond; - /// An empty json for default fallthrough cases - nlohmann::json empty_json; - /// The supplementary information - const VlgTgtSupplementaryInfo& supplementary_info; - /// record all the referred vlg names, so you can add (*keep*) if needed - std::map _all_referred_vlg_names; /// target type target_type_t target_type; - /// a shortcut of whether rf has flush condition set - bool has_flush; - /// ready type - ready_type_t ready_type; /// func apply counter func_app_cnt_t func_cnt; /// max bound , default 127 @@ -243,10 +219,10 @@ class VlgSglTgtGen { void ConstructWrapper_add_uf_constraints(); /// Add post value holder (val @ cond == ...) void ConstructWrapper_add_post_value_holder(); - /// A sub function of the above post-value-holder hanlder - int ConstructWrapper_add_post_value_holder_handle_obj( - nlohmann::json& pv_cond_val, const std::string& pv_name, int width, - bool create_reg); + /// Add delay unit + void ConstructWrapper_add_delay_unit(); + /// Add stage tracker unit + void ConstructWrapper_add_stage_tracker(); /// Add Verilog inline monitor void ConstructWrapper_add_vlg_monitor(); @@ -286,8 +262,6 @@ class VlgSglTgtGen { std::vector vlg_include_files_path; /// Store the configuration vtg_config_t _vtg_config; - /// Store the vlg configurations - const VerilogGenerator::VlgGenConfig& _vlg_cfg; /// Store the selection of backend backend_selector _backend; @@ -360,6 +334,7 @@ class VlgSglTgtGen { protected: /// If it is bad state, return true and display a message bool bad_state_return(void); + void RfmapIlaStateSanityCheck(); private: /// If it is in a bad state @@ -447,13 +422,6 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { /// to store the generate script name std::vector runnable_script_name; -protected: - /// store the vmap info - nlohmann::json rf_vmap; - /// store the condition - nlohmann::json rf_cond; - /// The supplementary information - VlgTgtSupplementaryInfo supplementary_info; public: // --------------------- METHODS ---------------------------- // diff --git a/test/t_inv_syn.cc b/test/t_inv_syn.cc index 628f2c9fa..ad27e5bf0 100644 --- a/test/t_inv_syn.cc +++ b/test/t_inv_syn.cc @@ -51,7 +51,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegar) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = false; // let's test flatten datatype also cfg.YosysSmtFlattenHierarchy = true; @@ -150,7 +150,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegarWithAssumptions) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = true; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = false; // let's test flatten datatype also cfg.YosysSmtFlattenHierarchy = true; @@ -195,7 +195,7 @@ TEST_F(TestVlgVerifInvSyn, LoadInvFromBeginning) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = false; // let's test flatten datatype also cfg.YosysSmtFlattenHierarchy = true; @@ -319,7 +319,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegarPassed) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = false; // let's test flatten datatype also cfg.YosysSmtFlattenHierarchy = true; @@ -361,7 +361,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbc) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = false; cfg.YosysSmtFlattenHierarchy = true; @@ -413,7 +413,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcBlif) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = false; cfg.YosysSmtFlattenHierarchy = true; @@ -466,7 +466,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcWithAssumption) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = true; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = false; cfg.YosysSmtFlattenHierarchy = true; @@ -512,7 +512,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcInvStart) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = false; cfg.YosysSmtFlattenHierarchy = true; @@ -607,7 +607,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntGrain) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = true; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = true; // let's test flatten datatype also cfg.YosysSmtFlattenHierarchy = true; @@ -679,7 +679,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntGrainBackVars) { VerilogVerificationTargetGenerator::vtg_config_t cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = true; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = true; // let's test flatten datatype also cfg.YosysSmtFlattenHierarchy = true; @@ -754,7 +754,7 @@ TEST_F(TestVlgVerifInvSyn, CegarPipelineAbcAigEnhance) { VerilogVerificationTargetGenerator::vtg_config_t cfg; // cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; cfg.YosysSmtFlattenDatatype = true; // for freqhorn cfg.YosysSmtFlattenHierarchy = true; @@ -836,7 +836,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntRelChc) { auto ila_model = CntTest::BuildModel(); VerilogVerificationTargetGenerator::vtg_config_t cfg; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.YosysPath = "N/A"; cfg.YosysSmtFlattenHierarchy = false; @@ -858,7 +858,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntRelChcNoStart) { auto ila_model = CntTest::BuildModel(); VerilogVerificationTargetGenerator::vtg_config_t cfg; - cfg.CosaAddKeep = false; + cfg.PonoAddKeep = false; cfg.YosysPath = "N/A"; cfg.YosysSmtFlattenHierarchy = false; cfg.VerificationSettingAvoidIssueStage = true; diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index a0ed39d58..f4d1bb270 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -341,7 +341,7 @@ TEST(TestVlgTargetGen, MemoryInternalExternal) { TEST(TestVlgTargetGen, MemoryInternalExternalEntry6) { auto ila_model = MemorySwap::BuildRfAsMemModelRegEntry6(); VlgVerifTgtGenBase::vtg_config_t vtg_cfg; - vtg_cfg.CosaAddKeep = false; + vtg_cfg.PonoAddKeep = false; auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; VerilogVerificationTargetGenerator vg( From 77b55bba24be4c5c4bc9e45ec539917c686bbcae Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 15 Jun 2021 16:27:16 -0400 Subject: [PATCH 17/78] rfmap update --- src/rfmap-in/rfmap_typecheck.cc | 52 ++++++++++++++++++++++++--------- src/rfmap-in/verilog_rfmap.cc | 16 ++++++++++ 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 133119e7a..0923dd4c4 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -17,6 +17,12 @@ std::string TypedVerilogRefinementMap::new_id() { return "__auxvar"+std::to_string(counter++) + "__"; } +TypedVerilogRefinementMap::TypedVerilogRefinementMap( + const VerilogRefinementMap & refinement, + var_typecheck_t type_checker + ) : VerilogRefinementMap(refinement), counter(0), typechecker(type_checker) { + initialize(); +} TypedVerilogRefinementMap::TypedVerilogRefinementMap( const std::string & varmap_json_file, @@ -24,7 +30,10 @@ TypedVerilogRefinementMap::TypedVerilogRefinementMap( var_typecheck_t type_checker ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), counter(0), typechecker(type_checker) { - + initialize(); +} // TypedVerilogRefinementMap::TypedVerilogRefinementMap + +void TypedVerilogRefinementMap::initialize() { // collect those with unknown types // a. delay // b. value holder @@ -35,9 +44,10 @@ TypedVerilogRefinementMap::TypedVerilogRefinementMap( // determine the types of delay and value holder ComputeDelayValueHolderWidth(); - -} // TypedVerilogRefinementMap::TypedVerilogRefinementMap - + +} // initialize + + RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( const RfExpr & in, bool replace_internal_wire) @@ -187,19 +197,21 @@ void TypedVerilogRefinementMap::collect_inline_value_recorder_func(RfExpr & inou void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr & inout) { if(inout->get_op() == voperator::DELAY) { - assert(inout->get_str_parameter().empty()); // currently we don't handle multi-clock - assert(inout->get_parameter().size() == 1); - assert(inout->get_child().size() >= 1); - - int delay = inout->get_parameter().at(0); + assert(inout->get_parameter().size() == inout->get_str_parameter().size()); + assert(inout->get_child().size() == 1 || inout->get_child().size() == 2); + assert(inout->get_parameter().size() == 1 || inout->get_parameter().size() == 2); auto delay_name = new_id()+"delay"; auto new_node = VExprAst::MakeVar(delay_name); - SignalDelay tmp_delay; - tmp_delay.signal = inout->get_child().at(0); - tmp_delay.num_cycle = delay; - tmp_delay.width = 0; - aux_delays.emplace(delay_name, tmp_delay); + + if( inout->get_parameter().size() == 1 ) { + int delay = inout->get_parameter().at(0); + aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), delay) ); + } else { // inout->get_parameter().size() == 2 + int delay = inout->get_parameter().at(0); + int delay_upper = inout->get_parameter().at(1); + aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), delay, delay_upper) ); + } if(inout->get_child().size() == 1) { inout = new_node; @@ -252,6 +264,18 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { tmp.type = VarDef::var_type::WIRE; all_var_def_types.emplace("decode", tmp); all_var_def_types.emplace("commit", tmp); + + // decode and commit stage replacement + var_replacement.emplace("decode", + VarReplacement( + verilog_expr::VExprAst::MakeSpecialName("decode"), + verilog_expr::VExprAst::MakeSpecialName("__START__") + )); + var_replacement.emplace("commit", + VarReplacement( + verilog_expr::VExprAst::MakeSpecialName("commit"), + verilog_expr::VExprAst::MakeSpecialName("__IEND__") + )); } diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index fd1474c50..7baa68dd9 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -913,6 +913,22 @@ VerilogRefinementMap::VerilogRefinementMap } // if invariant } // inst cond + + // ---------------- supplementary_info ------------------------ // + { + auto * annotation = GetJsonSection(rf_vmap, {"annotation","annotations"}); + if(annotation) { + auto * width_anno = GetJsonSection(*annotation, {"width"}); + if(width_anno && width_anno->is_object()){ + for (auto&& nw : width_anno->items()) { + width_info.insert(std::make_pair(nw.key(), nw.value().get())); + } + } + } // end of annotation + } // end of supplementary_info + + + ERRIF(ParseRfExprErrFlag, "error occur in refinement expression parsing"); } // VerilogRefinementMap::VerilogRefinementMap From 25c9f82b09864bebfa9003b9099aed9fa954499a Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 17 Jun 2021 22:25:11 -0400 Subject: [PATCH 18/78] backend mod WIP --- include/ilang/rfmap-in/verilog_rfmap.h | 16 +- include/ilang/vtarget-out/directive.h | 3 +- include/ilang/vtarget-out/vtarget_gen.h | 6 +- include/ilang/vtarget-out/vtarget_gen_impl.h | 12 +- src/rfmap-in/verilog_rfmap.cc | 37 +- src/vtarget-out/.gitignore | 2 + src/vtarget-out/CMakeLists.txt | 3 - src/vtarget-out/absmem.cc | 636 ------------------ src/vtarget-out/directive.cc | 491 ++------------ src/vtarget-out/gen_util.cc | 327 +-------- src/vtarget-out/inv-syn/rel_chc.cc | 7 +- .../inv-syn/vtarget_gen_inv_abc.cc | 2 +- .../inv-syn/vtarget_gen_inv_chc.cc | 2 +- .../inv-syn/vtarget_gen_inv_enhance.cc | 2 +- src/vtarget-out/single_target.cc | 201 ++---- src/vtarget-out/single_target_cond.cc | 199 ++---- src/vtarget-out/single_target_connect.cc | 92 +-- src/vtarget-out/single_target_misc.cc | 489 ++++++-------- src/vtarget-out/supplementary_info.cc | 103 --- src/vtarget-out/var_extract.cc | 196 ------ src/vtarget-out/vlg_mod.cc | 4 +- src/vtarget-out/vtarget_gen_cosa.cc | 2 +- src/vtarget-out/vtarget_gen_relchc.cc | 2 +- src/vtarget-out/vtarget_gen_yosys.cc | 11 +- 24 files changed, 463 insertions(+), 2382 deletions(-) create mode 100644 src/vtarget-out/.gitignore delete mode 100644 src/vtarget-out/absmem.cc delete mode 100644 src/vtarget-out/supplementary_info.cc delete mode 100644 src/vtarget-out/var_extract.cc diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index d4aebc5c0..0ad63710d 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -71,12 +71,12 @@ struct IlaVarMapping { struct RtlInterfaceMapping{ /// "CLOCK" : { "clkA" : "wclk", "clkB" : ["rclk", "clk"] } // name of the clock domain -> list of clock pins - std::map> clock_domain_defs; + std::map> clock_domain_defs; // "RESET" : "reset", // you can have a list of signals here - std::vector reset_pins; + std::set reset_pins; // "NRESET" : ["nreset1", "nreset2"], // like this - std::vector nreset_pins; + std::set nreset_pins; // "CUSTOMRESET" : {"name" : "input-pin", ...} std::map> custom_reset_domain_defs; }; // struct RtlInterfaceMapping @@ -124,12 +124,17 @@ struct GeneralVerilogMonitor { std::string verilog_append; // std::map var_defs; std::set var_uses; + bool keep_for_invariant; + + GeneralVerilogMonitor() : keep_for_invariant(false) {} }; // GeneralVerilogMonitor struct ValueRecorder { RfExpr condition; RfExpr value; unsigned width; + + ValueRecorder() : condition(nullptr), value(nullptr), width(0) {} }; // this is not directly used @@ -182,6 +187,11 @@ struct InstructionCompleteCondition{ unsigned max_bound; std::vector start_condition; RfExpr ready_signal; + + + InstructionCompleteCondition() : ready_bound(0), max_bound(0), ready_signal(nullptr) {} + bool is_readybound() const {return type == ConditionType::BOUND; } + bool is_readysignal() const {return type == ConditionType::SIGNAL; } }; // struct VerilogRefinementMap { diff --git a/include/ilang/vtarget-out/directive.h b/include/ilang/vtarget-out/directive.h index 5b0d3f591..c3e22e62f 100644 --- a/include/ilang/vtarget-out/directive.h +++ b/include/ilang/vtarget-out/directive.h @@ -81,8 +81,7 @@ class IntefaceDirectiveRecorder { void VlgAddTopInteface(VerilogGeneratorBase& gen) const; /// Used to tell this module about the refinement relations void RegisterInterface(const SignalInfoBase& vlg_sig, - const std::string& refstr, ila_input_checker_t chk, - ila_mem_checker_t mget); + const std::string& refstr); /// Register the extra wire to connect (for extra wire) void RegisterExtraWire(const std::string& io_name, const std::string& outside_name); diff --git a/include/ilang/vtarget-out/vtarget_gen.h b/include/ilang/vtarget-out/vtarget_gen.h index 4564a7151..1e8057eef 100644 --- a/include/ilang/vtarget-out/vtarget_gen.h +++ b/include/ilang/vtarget-out/vtarget_gen.h @@ -69,6 +69,9 @@ class VlgVerifTgtGenBase { /// in the whole execution of checking instruction /// from reseted --> to forever bool InstructionNoReset; // true + /// Ensure the design will not be reseted + /// from reseted --> to forever + bool InvariantCheckNoReset; // true /// Does not insert assertions of variable mapping /// if an instruction does not update that var bool OnlyCheckInstUpdatedVars; // true @@ -207,7 +210,8 @@ class VlgVerifTgtGenBase { /// The default constructor for default values _vtg_config() : target_select(BOTH), CheckThisInstructionOnly(""), - InstructionNoReset(true), OnlyCheckInstUpdatedVars(true), + InstructionNoReset(true), InvariantCheckNoReset(false), + OnlyCheckInstUpdatedVars(true), VerilogGenPassNodeName(false), ValidateSynthesizedInvariant(_validate_synthesized_inv::ALL), diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 651083d49..c600d30f7 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -154,8 +154,7 @@ class VlgSglTgtGen { bool TryFindVlgState(const std::string& sname); /// Try to find a ILA var according to a name ExprPtr TryFindIlaVarName(const std::string& sname); - /// Modify a token and record its use - std::string ModifyCondExprAndRecordVlgName(const VarExtractor::token& t); + /// Check if ila name and vlg name are type compatible (not including special /// directives) static unsigned TypeMatched(const ExprPtr& ila_var, @@ -163,7 +162,7 @@ class VlgSglTgtGen { /// get width of an ila node static unsigned get_width(const ExprPtr& n); /// Parse and modify a condition string - std::string ReplExpr(const std::string& expr, bool force_vlg_sts = false); + std::string ReplExpr(const rfmap::RfExpr & in); /// handle a single string map (s-name/equ-string) std::string PerStateMap(const std::string& ila_state_name_or_equ, const std::string& vlg_st_name); @@ -177,9 +176,9 @@ class VlgSglTgtGen { std::string GetStateVarMapExpr(const std::string& ila_state_name, nlohmann::json& m, bool is_assert = false); /// add a start condition if it is given - void handle_start_condition(nlohmann::json& dc); + void handle_start_condition(const std::vector & dc); /// Find the current instruction-mapping - nlohmann::json& get_current_instruction_rf(); + const rfmap::InstructionCompleteCondition & get_current_instruction_rf(); protected: // --------------- STEPS OF GENERATION ------------------------// @@ -212,9 +211,6 @@ class VlgSglTgtGen { void ConstructWrapper_register_extra_io_wire(); /// Add instantiation statement of the two modules void ConstructWrapper_add_module_instantiation(); - /// Add instantiation of the memory and put the needed mem implementation in - /// extra export This also include the assertions - void ConstructWrapper_add_helper_memory(); /// Add buffers and assumption/assertions about the void ConstructWrapper_add_uf_constraints(); /// Add post value holder (val @ cond == ...) diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 7baa68dd9..3a43daa84 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -576,19 +576,21 @@ VerilogRefinementMap::VerilogRefinementMap ENSURE(clock_domains->is_array() || clock_domains->is_string() || clock_domains->is_object(), "clock specification in RTL interface connection should be string/list of string/map:string->list(string)"); if(clock_domains->is_string()) - rtl_interface_connection.clock_domain_defs["default"].push_back(clock_domains->get()); + rtl_interface_connection.clock_domain_defs["default"].insert(clock_domains->get()); else if(clock_domains->is_array()){ - rtl_interface_connection.clock_domain_defs.insert( - std::make_pair(std::string("default"), clock_domains->get>())); + auto clk_pins = clock_domains->get>(); + for (const auto & clk_pin : clk_pins) + rtl_interface_connection.clock_domain_defs["default"].insert(clk_pin); } else { // is_object for(const auto & n_l_pair : clock_domains->items()) { const auto & domain_name = n_l_pair.key(); - std::vector pins; + std::set pins; ENSURE(n_l_pair.value().is_string() || n_l_pair.value().is_array(), "expect string/array in RTL interface connection"); if (n_l_pair.value().is_string()) { - pins.push_back(n_l_pair.value().get()); + pins.insert(n_l_pair.value().get()); } else { - pins = n_l_pair.value().get>(); + auto pin_vec = n_l_pair.value().get>(); + pins = std::set(pin_vec.begin(), pin_vec.end()); } rtl_interface_connection.clock_domain_defs.emplace( domain_name, pins @@ -599,17 +601,21 @@ VerilogRefinementMap::VerilogRefinementMap if(reset_list) { if(reset_list->is_string()) - rtl_interface_connection.reset_pins.push_back(reset_list->get()); + rtl_interface_connection.reset_pins.insert(reset_list->get()); else if(reset_list->is_array()){ - rtl_interface_connection.reset_pins = reset_list->get>(); + auto reset_pins = reset_list->get>(); + for (const auto & pin : reset_pins) + rtl_interface_connection.reset_pins.insert(pin); } } if(nreset_list) { if(nreset_list->is_string()) - rtl_interface_connection.nreset_pins.push_back(nreset_list->get()); + rtl_interface_connection.nreset_pins.insert(nreset_list->get()); else if(nreset_list->is_array()){ - rtl_interface_connection.nreset_pins = nreset_list->get>(); + auto nreset_pins = nreset_list->get>(); + for (const auto & pin : nreset_pins) + rtl_interface_connection.nreset_pins.insert(pin); } } if(reset_domains) { @@ -778,8 +784,13 @@ VerilogRefinementMap::VerilogRefinementMap // has no template auto * verilog_field = GetJsonSection(monitor,{"verilog"}); auto * verilog_file_field = GetJsonSection(monitor,{"verilog-from-file"}); + auto * keep_inv = GetJsonSection(monitor,{"keep-for-invariant", "keep-for-invariants"}); ERRIF(verilog_field && verilog_file_field, "`verilog` or `verilog-from-file` fields are mutual exclusive"); + if(keep_inv) { + ENSURE(keep_inv->is_boolean(), "`keep-for-invariant` should be Boolean"); + mnt_ref.keep_for_invariant = keep_inv->get(); + } if(verilog_field) { if( verilog_field->is_string() ) { @@ -881,15 +892,19 @@ VerilogRefinementMap::VerilogRefinementMap if(ready_bnd) { ENSURE(ready_bnd->is_number_unsigned(), "`ready-bound` should be an unsigned number"); ws.ready_bound = ready_bnd->get(); + ws.type = InstructionCompleteCondition::ConditionType::BOUND; } else { // ready_signal ENSURE(ready_signal->is_string(), "`ready-signal` should be a string"); ws.ready_signal = ParseRfMapExprJson(*ready_signal); + ws.type = InstructionCompleteCondition::ConditionType::SIGNAL; } if(max_bound) { ENSURE(max_bound->is_number_unsigned(), "`max_bound` should be an unsigned number"); ws.max_bound = max_bound->get(); - } + } else + ws.max_bound = 0; + if (start_condition) { if (start_condition->is_string()) { ws.start_condition.push_back( ParseRfMapExprJson(*start_condition) ); diff --git a/src/vtarget-out/.gitignore b/src/vtarget-out/.gitignore new file mode 100644 index 000000000..dcd1b5ed4 --- /dev/null +++ b/src/vtarget-out/.gitignore @@ -0,0 +1,2 @@ +NOTE.txt + diff --git a/src/vtarget-out/CMakeLists.txt b/src/vtarget-out/CMakeLists.txt index 14134d4db..867b8bff9 100644 --- a/src/vtarget-out/CMakeLists.txt +++ b/src/vtarget-out/CMakeLists.txt @@ -7,7 +7,6 @@ add_subdirectory(inv-syn) target_sources(${ILANG_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/directive.cc ${CMAKE_CURRENT_SOURCE_DIR}/gen_util.cc - ${CMAKE_CURRENT_SOURCE_DIR}/var_extract.cc ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_impl.cc ${CMAKE_CURRENT_SOURCE_DIR}/single_target.cc ${CMAKE_CURRENT_SOURCE_DIR}/single_target_as.cc @@ -21,8 +20,6 @@ target_sources(${ILANG_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_relchc.cc ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen.cc ${CMAKE_CURRENT_SOURCE_DIR}/vlg_mod.cc - ${CMAKE_CURRENT_SOURCE_DIR}/absmem.cc ${CMAKE_CURRENT_SOURCE_DIR}/design_stat.cc - ${CMAKE_CURRENT_SOURCE_DIR}/supplementary_info.cc ) diff --git a/src/vtarget-out/absmem.cc b/src/vtarget-out/absmem.cc deleted file mode 100644 index 3fba7e41c..000000000 --- a/src/vtarget-out/absmem.cc +++ /dev/null @@ -1,636 +0,0 @@ -/// \file Source for generating abstract memory -// --- Hongce Zhang - -#include - -#include -#include - -#include -#include -#include - -namespace ilang { - -unsigned mem_count = 0; -std::string get_m_inst_name() { - return std::string("mi") + std::to_string(mem_count++); -} - -// ---------------------- class VlgAbsMem ------------------------------- // -VlgAbsMem::VlgAbsMem() - : read_abstract(false), concrete_level(1), data_width(0), addr_width(0), - checked(false) {} - -/// SetAddrWidth -void VlgAbsMem::SetAddrWidth(unsigned w) { - if (addr_width != 0 && addr_width != w) { - ILA_ERROR << "Address width incompatible!"; - return; - } - addr_width = w; -} -/// SetDataWidth -void VlgAbsMem::SetDataWidth(unsigned w) { - if (data_width != 0 && data_width != w) { - ILA_ERROR << "Data width incompatible!"; - return; - } - data_width = w; -} - -std::string VlgAbsMem::MemEQSignalName() const { return mem_name + "_EQ_"; } - -// add signals and add instantiation statement; -std::string -VlgAbsMem::GeneratingMemModuleSignalsInstantiation(VerilogGeneratorBase& gen, - const std::string& endCond) { - // eq ? signal - // if not given, use a name it self - if (addr_width == 0 || data_width == 0) { - ILA_ERROR << "Unknown addr/data width for absmem : " << ila_map_name; - return ""; - } - if (vlg_rports.size() > 1 || vlg_wports.size() > 1 || ila_rports.size() > 1 || - ila_wports.size() > 1) { - ILA_ERROR << "Not implemented for support for abs mem w. more than 1 rport " - "and 1 wport"; - return ""; - } - - std::stringstream ret; - std::string moduleName; - auto inst_name = get_m_inst_name(); - if (concrete_level == 1) - moduleName = "absmem"; - else - moduleName = "absmemD" + std::to_string(concrete_level); - if (read_abstract) - moduleName += "_ra"; - ret << moduleName << " #( \n .AW(" << addr_width << "),\n"; - if (read_abstract) { - ret << " .DW(" << data_width << ") )\n"; - // will not have TTS, because not used - // and will create problem for jg - } else { - ret << " .DW(" << data_width << "),\n"; - ret << " .TTS(" << (long long)(std::pow(2, addr_width)) << ") )\n"; - } - ret << inst_name << "(\n"; - ret << " .clk(clk),\n"; - ret << " .rst(rst),\n"; - - auto vlg_rand_input_name = inst_name + "_vlg_r_rand_input"; - auto ila_rand_input_name = inst_name + "_ila_r_rand_input"; - auto read_assume_true = inst_name + "_read_assume_true"; - gen.add_input(vlg_rand_input_name, data_width); - gen.add_input(ila_rand_input_name, data_width); - gen.add_output(read_assume_true, 1); - - if (read_abstract) - assumpts.push_back(read_assume_true + "==1'b1"); - - ret << " .vlg_r_rand_input( " << vlg_rand_input_name << "),\n"; - ret << " .ila_r_rand_input( " << ila_rand_input_name << "),\n"; - ret << " .equal(" << MemEQSignalName() << "),\n"; - ret << " .issue( __ISSUE__ ),\n"; - if (read_abstract) - ret << " .read_assume_true(" << read_assume_true << "),\n"; - ret << " .compare(" << endCond // "__IEND__ || __ENDED__" - << ")"; - - gen.add_wire(MemEQSignalName(), 1, true); - if (ila_map_name == "") - ILA_WARN_IF(ila_map_name == "") - << "Empty mem abs name for (" << mem_name << ")"; - - // connect ports, create - // treat unconnected wire? -#define CONNECT(e, s, w, i) \ - do { \ - std::string wn = (e); \ - if ((wn).size() == 0) { \ - (wn) = base_name + (s); \ - gen.add_wire((wn), (w), true); \ - if (i) \ - gen.add_input((wn), (w)); \ - else \ - gen.add_output((wn), (w)); \ - } \ - ret << ",\n .vlg" s "(" << (wn) << ")"; \ - } while (false) - - for (auto&& np : vlg_wports) { - auto n = np.first; - auto& p = np.second; - auto base_name = "__MEM_" + - VerilogGeneratorBase::sanitizeName(ila_map_name) + "_" + - std::to_string(n); - - CONNECT(p.waddr, "_waddr", addr_width, true); - CONNECT(p.wdata, "_wdata", data_width, false); - CONNECT(p.wen, "_wen", 1, true); - } // the else case: - if (vlg_wports.size() == 0) { // avoid write arbitrarily - ret << ",\n .vlg_wen(1'b0)"; - int n = 0; - auto base_name = "__MEM_" + - VerilogGeneratorBase::sanitizeName(ila_map_name) + "_" + - std::to_string(n); - CONNECT("", "_waddr", addr_width, true); - CONNECT("", "_wdata", data_width, false); - } - - for (auto&& np : vlg_rports) { - auto n = np.first; - auto& p = np.second; - auto base_name = "__MEM_" + - VerilogGeneratorBase::sanitizeName(ila_map_name) + "_" + - std::to_string(n); - - CONNECT(p.raddr, "_raddr", addr_width, true); - CONNECT(p.rdata, "_rdata", data_width, false); - CONNECT(p.ren, "_ren", 1, true); - } // else case - if (vlg_rports.size() == 0) { - ret << ",\n .vlg_ren(1'b0)"; - int n = 0; - auto base_name = "__MEM_" + - VerilogGeneratorBase::sanitizeName(ila_map_name) + "_" + - std::to_string(n); - CONNECT("", "_raddr", addr_width, true); - CONNECT("", "_rdata", data_width, false); - } - - // ila ports should have been fully connected - // NOTE: in multi inst - for (auto&& np : ila_wports) { - auto n = np.first; - auto& p = np.second; - auto base_name = "__IMEM_" + - VerilogGeneratorBase::sanitizeName(ila_map_name) + "_" + - std::to_string(n); - - ret << ",\n .ila_waddr(" << base_name + "_waddr" - << ")"; - ret << ",\n .ila_wdata(" << base_name + "_wdata" - << ")"; - ret << ",\n .ila_wen (" << base_name + "_wen" - << ")"; - - ILA_DLOG("VtargetGen.AbsMem") - << ".ila_waddr(" << p.waddr << " or " << base_name + "_waddr" - << ")"; - ILA_DLOG("VtargetGen.AbsMem") - << ".ila_wdata(" << p.wdata << " or " << base_name + "_wdata" - << ")"; - ILA_DLOG("VtargetGen.AbsMem") - << ".ila_wen (" << p.wen << " or " << base_name + "_wen" - << ")"; - } - if (ila_wports.size() == 0) - ret << ",\n .ila_wen ( 1'b0 )"; // make sure we don't do any writes if - // no write - - for (auto&& np : ila_rports) { - auto n = np.first; - auto& p = np.second; - - auto base_name = "__IMEM_" + - VerilogGeneratorBase::sanitizeName(ila_map_name) + "_" + - std::to_string(n); - - ret << ",\n .ila_raddr(" << base_name + "_raddr" - << ")"; - ret << ",\n .ila_rdata(" << base_name + "_rdata" - << ")"; - ret << ",\n .ila_ren (" << p.ren << ")"; // this is the start? - } - - ret << " );\n\n"; - - checked = true; - // here negative means abstract its read - concrete_level_encountered.insert(read_abstract ? -concrete_level - : concrete_level); - - return (ret.str()); -} - -bool VlgAbsMem::hasAbsMem() { return concrete_level_encountered.size() > 0; } - -void VlgAbsMem::ClearAbsMemRecord() { - mem_count = 0; - concrete_level_encountered.clear(); -} - -// the parameters are : -// %%%AVOID_ISSUE%%% -// -// - -std::string d1model = R"**##**( - -// 1R 1W (x2) d=1 AW(V=I) DW(V=I) absmem -// only work for CoSA -// Hongce Zhang (hongcez@princeton.edu) - -module absmem( - clk, - rst, - vlg_raddr, - vlg_rdata, - vlg_ren, - vlg_waddr, - vlg_wdata, - vlg_wen, - - vlg_r_rand_input, - - ila_raddr, - ila_rdata, - ila_ren, - ila_waddr, - ila_wdata, - ila_wen, - - ila_r_rand_input, - - compare, - equal, - issue - ); - - -parameter AW = 16; -parameter DW = 8; -parameter TTS = 65536; - -input clk; -input rst; - -input [AW-1:0] vlg_raddr; -output [DW-1:0] vlg_rdata; -input vlg_ren; -input [AW-1:0] vlg_waddr; -input [DW-1:0] vlg_wdata; -input vlg_wen; -input [DW-1:0] vlg_r_rand_input; - - -input [AW-1:0] ila_raddr; -output [DW-1:0] ila_rdata; -input ila_ren; -input [AW-1:0] ila_waddr; -input [DW-1:0] ila_wdata; -input ila_wen; -input [DW-1:0] ila_r_rand_input; - -input compare; -output equal; -input issue; - -(* keep *) reg start_and_on; -(* keep *) reg [DW-1:0] mem[0:TTS-1]; - -wire vlg_ren_real; -wire vlg_wen_real; -wire ila_ren_real; -wire ila_wen_real; - -(* keep *) reg vlg_m_e0; -(* keep *) reg [AW-1:0] vlg_m_a0; -(* keep *) reg [DW-1:0] vlg_m_d0; - - -(* keep *) reg ila_m_e0; -(* keep *) reg [AW-1:0] ila_m_a0; -(* keep *) reg [DW-1:0] ila_m_d0; - -(* keep *) reg vlg_match_ila; -(* keep *) reg ila_match_vlg; - -always @(posedge clk) begin - if(rst) - start_and_on <= 1'b%%%AVOID_ISSUE%%%; - else if(issue) - start_and_on <= 1'b1; -end - -assign vlg_ren_real = vlg_ren & ~compare & start_and_on; -assign vlg_wen_real = vlg_wen & ~compare & start_and_on; -assign ila_ren_real = ila_ren & ~compare & start_and_on; -assign ila_wen_real = ila_wen & ~compare & start_and_on; - - -assign vlg_rdata = vlg_ren_real ? - vlg_m_e0 && vlg_m_a0 == vlg_raddr ? vlg_m_d0 - : - mem[vlg_raddr] : vlg_r_rand_input; - -assign ila_rdata = ila_ren_real ? - ila_m_e0 && ila_m_a0 == ila_raddr ? ila_m_d0 - : - mem[ila_raddr] : ila_r_rand_input; - -always @(posedge clk) begin - if( rst ) begin - vlg_m_e0 <= 1'b0; - end - else begin - if( vlg_m_e0 == 0 && vlg_wen_real) begin - vlg_m_e0 <= 1'b1; - vlg_m_a0 <= vlg_waddr; - vlg_m_d0 <= vlg_wdata; - end - end -end - -always @(posedge clk) begin - if( rst ) begin - ila_m_e0 <= 1'b0; - end - else begin - if( ila_m_e0 == 0 && ila_wen_real) begin - ila_m_e0 <= 1'b1; - ila_m_a0 <= ila_waddr; - ila_m_d0 <= ila_wdata; - end - end -end - -always @(*) begin - vlg_match_ila = 0; - if( vlg_m_e0 ) begin - if(ila_m_e0 == 1 && ila_m_a0 == vlg_m_a0) - vlg_match_ila = ila_m_d0 == vlg_m_d0; - else if(vlg_m_d0 == mem[vlg_m_a0]) - vlg_match_ila = 1; - else - vlg_match_ila = 0; - end - else - vlg_match_ila = 1; -end - -always @(*) begin - ila_match_vlg = 0; - if( ila_m_e0 ) begin - if(vlg_m_e0 == 1 && ila_m_a0 == vlg_m_a0) - ila_match_vlg = ila_m_d0 == vlg_m_d0; - else if(ila_m_d0 == mem[ila_m_a0]) - ila_match_vlg = 1; - else - ila_match_vlg = 0; - end - else - ila_match_vlg = 1; -end - -assign equal = compare && ila_match_vlg && vlg_match_ila; - -endmodule - - )**##**"; - -std::string d1ra = R"**##**( - -// 1R 1W (x2) d=1 AW(V=I) DW(V=I) absmem -// CoSA & Jasper -// --- ra : read abstraction (depth = 1) -// -// Hongce Zhang (hongcez@princeton.edu) - -module absmem_ra( - clk, - rst, - vlg_raddr, - vlg_rdata, - vlg_ren, - vlg_waddr, - vlg_wdata, - vlg_wen, - - vlg_r_rand_input, - - ila_raddr, - ila_rdata, - ila_ren, - ila_waddr, - ila_wdata, - ila_wen, - - ila_r_rand_input, - - compare, - equal, - issue, - read_assume_true - ); - - -parameter AW = 16; -parameter DW = 8; -parameter TTS = 65536; - -input clk; -input rst; - -input [AW-1:0] vlg_raddr; -output [DW-1:0] vlg_rdata; -input vlg_ren; -input [AW-1:0] vlg_waddr; -input [DW-1:0] vlg_wdata; -input vlg_wen; -input [DW-1:0] vlg_r_rand_input; - - -input [AW-1:0] ila_raddr; -output [DW-1:0] ila_rdata; -input ila_ren; -input [AW-1:0] ila_waddr; -input [DW-1:0] ila_wdata; -input ila_wen; -input [DW-1:0] ila_r_rand_input; - -input compare; -output equal; -input issue; -(* keep *) output read_assume_true; - -(* keep *) reg start_and_on; - -wire vlg_ren_real; -wire vlg_wen_real; -wire ila_ren_real; -wire ila_wen_real; - -(* keep *) reg vlg_r_e0; -(* keep *) reg [AW-1:0] vlg_r_a0; -(* keep *) reg [DW-1:0] vlg_r_d0; - - -(* keep *) reg ila_r_e0; -(* keep *) reg [AW-1:0] ila_r_a0; -(* keep *) reg [DW-1:0] ila_r_d0; - -(* keep *) reg vlg_m_e0; -(* keep *) reg [AW-1:0] vlg_m_a0; -(* keep *) reg [DW-1:0] vlg_m_d0; - - -(* keep *) reg ila_m_e0; -(* keep *) reg [AW-1:0] ila_m_a0; -(* keep *) reg [DW-1:0] ila_m_d0; - -(* keep *) reg vlg_match_ila; -(* keep *) reg ila_match_vlg; - -always @(posedge clk) begin - if(rst) - start_and_on <= 1'b%%%AVOID_ISSUE%%%; - else if(issue) - start_and_on <= 1'b1; -end - -assign vlg_ren_real = vlg_ren & ~compare & start_and_on; -assign vlg_wen_real = vlg_wen & ~compare & start_and_on; -assign ila_ren_real = ila_ren & ~compare & start_and_on; -assign ila_wen_real = ila_wen & ~compare & start_and_on; - - -assign vlg_rdata = vlg_ren_real ? ( - (vlg_m_e0 && vlg_m_a0 == vlg_raddr) ? vlg_m_d0 - : vlg_r_rand_input ) : vlg_r_rand_input; - -assign ila_rdata = ila_ren_real ? ( - (ila_m_e0 && ila_m_a0 == ila_raddr) ? ila_m_d0 - : ila_r_rand_input) : ila_r_rand_input; - -always @(posedge clk) begin - if( rst ) begin - vlg_r_e0 <= 1'b0; - end - else begin - //if( vlg_ren_real && ( vlg_r_e0 == 0 || (vlg_r_e0 == 1 && vlg_r_a0 == vlg_raddr) ) ) begin - if( vlg_ren_real && ( vlg_r_e0 == 0) ) begin - vlg_r_e0 <= 1'b1; - vlg_r_a0 <= vlg_raddr; - vlg_r_d0 <= vlg_r_rand_input; // vlg_rdata; - end - end -end - -always @(posedge clk) begin - if( rst ) begin - ila_r_e0 <= 1'b0; - end - else begin - // if( ( ila_ren_real && ( ila_r_e0 == 0 || (ila_r_e0 == 1 && ila_r_a0 == ila_raddr ) ) ) ) - if( ila_ren_real && ( ila_r_e0 == 0) ) begin - ila_r_e0 <= 1'b1; - ila_r_a0 <= ila_raddr; - ila_r_d0 <= ila_r_rand_input; // ila_rdata; - end - /* - else if ( ila_wen_real && ila_r_e0 && ila_r_a0 == ila_waddr ) begin - ila_r_e0 <= ila_r_e0; - ila_r_a0 <= ila_r_a0; - ila_r_d0 <= ila_wdata; - end*/ - end -end - -// we only ensure that the initial read matches, not the read involve the new data (changed by write) -// if you change it, we guarantee nothing - -assign read_assume_true = - (vlg_r_e0 && ila_r_e0 && vlg_r_a0 == ila_r_a0) == 0 || (vlg_r_d0 == ila_r_d0); - -// ------------- WRITE LOGIC ---------------- // - -always @(posedge clk) begin - if( rst ) begin - vlg_m_e0 <= 1'b0; - end - else begin - if( vlg_wen_real && ( vlg_m_e0 == 0 || (vlg_m_e0 == 1'b1 && vlg_m_a0 == vlg_waddr) ) ) begin - vlg_m_e0 <= 1'b1; - vlg_m_a0 <= vlg_waddr; - vlg_m_d0 <= vlg_wdata; - end - end -end - -always @(posedge clk) begin - if( rst ) begin - ila_m_e0 <= 1'b0; - end - else begin - if( ila_wen_real && ( ila_m_e0 == 0 || (ila_m_e0 == 1'b1 && ila_m_a0 == ila_waddr) ) ) begin - ila_m_e0 <= 1'b1; - ila_m_a0 <= ila_waddr; - ila_m_d0 <= ila_wdata; - end - end -end - - -always @(*) begin - vlg_match_ila = 0; - if( vlg_m_e0 ) begin - if(ila_m_e0 == 1 && ila_m_a0 == vlg_m_a0) - vlg_match_ila = ila_m_d0 == vlg_m_d0; - else if(ila_r_e0 == 1 && ila_r_a0 == vlg_m_a0) - vlg_match_ila = ila_r_d0 == vlg_m_d0; - //else if(vlg_m_d0 == mem[vlg_m_a0]) - // vlg_match_ila = 1; - //below is an over-approximation - else - vlg_match_ila = 0; - end - else - vlg_match_ila = 1; -end - -always @(*) begin - ila_match_vlg = 0; - if( ila_m_e0 ) begin - if(vlg_m_e0 == 1 && ila_m_a0 == vlg_m_a0) - ila_match_vlg = ila_m_d0 == vlg_m_d0; - else if(vlg_r_e0 == 1 && vlg_r_a0 == ila_m_a0) - ila_match_vlg = ila_m_d0 == vlg_r_d0; - //else if(ila_m_d0 == mem[ila_m_a0]) - // ila_match_vlg = 1; - else - ila_match_vlg = 0; - end - else - ila_match_vlg = 1; -end - -assign equal = compare && ila_match_vlg && vlg_match_ila; - -endmodule - - - )**##**"; - -void VlgAbsMem::OutputMemFile(std::ostream& os, bool avoid_issue_stage) { - - for (auto&& cl : concrete_level_encountered) { - if (cl == 1) - os << ReplaceAll(d1model, "%%%AVOID_ISSUE%%%", - avoid_issue_stage ? "1" : "0"); - else if (cl == -1) - os << ReplaceAll(d1ra, "%%%AVOID_ISSUE%%%", - avoid_issue_stage ? "1" : "0"); - else - ILA_ASSERT(false) << "depth :" << cl - << " abs mem model is not developed. Future work."; - } -} - -std::set VlgAbsMem::concrete_level_encountered; - -}; // namespace ilang diff --git a/src/vtarget-out/directive.cc b/src/vtarget-out/directive.cc index cdbbe3f04..67525b345 100644 --- a/src/vtarget-out/directive.cc +++ b/src/vtarget-out/directive.cc @@ -13,67 +13,7 @@ namespace ilang { #define VLG_TRUE "`true" // ---------------------- class IntefaceDirectiveRecorder -// ------------------------------- // static function -bool IntefaceDirectiveRecorder::beginsWith(const std::string& c, - const std::string& s) { - return StrStartsWith(c, s); -} - -// static function -bool IntefaceDirectiveRecorder::isSpecialInputDir(const std::string& c) { - return beginsWith(c, "**"); -} - -// static function -bool IntefaceDirectiveRecorder::isSpecialInputDirCompatibleWith( - const std::string& c, const SignalInfoBase& vlg_sig) { - ILA_CHECK(isSpecialInputDir(c)); - if (c == "**KEEP**") - return true; - if (c == "**NC**") - return true; - if (c == "**SO**") - return vlg_sig.is_output(); - if (c == "**RESET**" || c == "**NRESET**" || c == "**CLOCK**" || - c == "**START**") - return (vlg_sig.is_input() && vlg_sig.get_width() == 1); - if (beginsWith(c, "**MEM**")) { - auto first_dot_loc = c.find("."); - auto port_name = c.substr(first_dot_loc + 1); - if (beginsWith(port_name, "waddr") || beginsWith(port_name, "wdata") || - beginsWith(port_name, "wen") || beginsWith(port_name, "raddr") || - beginsWith(port_name, "ren")) - return vlg_sig.is_output(); - if (beginsWith(port_name, "rdata")) - return vlg_sig.is_input(); - ILA_ERROR << "Unknown IO directive in refinement relations:" << c; - return false; - } - ILA_ERROR << "Unknown IO directive in refinement relations:" << c; - return false; -} - -// static function -/* -bool IntefaceDirectiveRecorder::interfaceDeclareTop(const std::string & c) { - ILA_CHECK(isSpecialInputDir(c)); - if(c == "**KEEP**") return true; - if(c == "**NC**") return false; - if(c == "**SO**") return true; - if(c == "**RESET**" || c == "**CLOCK**") return false; - if(beginsWith(c, "**MEM**")) { - auto first_dot_loc = c.find("."); - auto port_name = c.substr(first_dot_loc + 1); - if( beginsWith(port_name,"waddr") || beginsWith(port_name,"wdata") || -beginsWith(port_name,"wen") || beginsWith(port_name,"raddr") || -beginsWith(port_name,"ren") ) return false; if( beginsWith(port_name,"rdata") ) - return false; // - ILA_ERROR<<"Unknown IO directive in refinement relations:"< 3) { - ILA_ERROR << "Bad mem directive:" << refstr; - return; - } - if (dirv.size() == 2) - dirv.push_back("0"); // refer to 0 by default - const auto& ila_mem_name = dirv[0]; - const auto& port_name = dirv[1]; - unsigned port_no = StrToInt(dirv[2]); - // add internal wire __MEM_ilaname_no_..._ - // - - auto ila_minfo = mget(ila_mem_name); - if (ila_minfo.first == 0 || ila_minfo.second == 0) { - ILA_ERROR << "No such memory in ila:" << ila_mem_name - << " refered by refinement relation."; - return; - } - auto addr_w = ila_minfo.first; - auto data_w = ila_minfo.second; - - auto new_wire_name = "__MEM_" + - VerilogGeneratorBase::sanitizeName(ila_mem_name) + - "_" + dirv[2] + "_" + port_name; - -#define ADD_PORT_WIRE(name, w, INFO1, INFO2, io, assign, inf_d) \ - do { \ - ILA_ERROR_IF(width != (w)) \ - << INFO1 " width does not match: vlg:" << short_name << "(" << width \ - << ") " \ - << " ila: " << ila_mem_name << "." INFO2 " (" << (w) << ")"; \ - ILA_ERROR_IF(!io) << name " should be an input to the verilog module."; \ - (assign) = new_wire_name; \ - mod_inst_rec.insert({short_name, {(inf_d), new_wire_name}}); \ - internal_wires.push_back({new_wire_name, (w)}); \ - } while (0); - - abs_mems[ila_mem_name].SetDataWidth(data_w); - abs_mems[ila_mem_name].SetAddrWidth(addr_w); - - if (port_name == "rdata") { - ADD_PORT_WIRE("rdata", data_w, "Data", "data", is_input, - abs_mems[ila_mem_name].vlg_rports[port_no].rdata, - inf_dir_t::MEM_R_D); - } else if (port_name == "raddr") { - ADD_PORT_WIRE("raddr", addr_w, "Addr", "addr", is_output, - abs_mems[ila_mem_name].vlg_rports[port_no].raddr, - inf_dir_t::MEM_R_A); - } else if (port_name == "ren") { - ADD_PORT_WIRE("ren", 1, "Enable signal", "en", is_output, - abs_mems[ila_mem_name].vlg_rports[port_no].ren, - inf_dir_t::MEM_R_EN); - } else if (port_name == "wdata") { - ADD_PORT_WIRE("wdata", data_w, "Data", "data", is_output, - abs_mems[ila_mem_name].vlg_wports[port_no].wdata, - inf_dir_t::MEM_W_D); - } else if (port_name == "waddr") { - ADD_PORT_WIRE("waddr", addr_w, "Addr", "addr", is_output, - abs_mems[ila_mem_name].vlg_wports[port_no].waddr, - inf_dir_t::MEM_W_A); - } else if (port_name == "wen") { - ADD_PORT_WIRE("wen", 1, "Enable signal", "en", is_output, - abs_mems[ila_mem_name].vlg_wports[port_no].wen, - inf_dir_t::MEM_W_EN); - } else { - ILA_ERROR << "no such port:" << port_name - << " on built-in mem abstraction for " << ila_mem_name; - } - return; - } else - ILA_ERROR << "Ignoring unknown verilog interface directive:" << refstr; - - // decide how to connect and signals to create + {short_name, inf_connector_t({inf_dir_t::RESET, "dummy_reset"})}); + } else if (refstr == "**NRESET**") { + ILA_ERROR_IF(!is_input || width != 1) << "Expecting `" << short_name << "` to be input of width 1"; + if (_reset_vlg) + mod_inst_rec.insert( + {short_name, inf_connector_t({inf_dir_t::RESET, "~rst"})}); + else + mod_inst_rec.insert( + {short_name, inf_connector_t({inf_dir_t::RESET, "~dummy_reset"})}); + } else if (refstr == "**CLOCK**") { + ILA_ERROR_IF(!is_input || width != 1) << "Expecting `" << short_name << "` to be input of width 1"; + mod_inst_rec.insert( + {short_name, inf_connector_t({inf_dir_t::CLOCK, "clk"})}); + } else + ILA_ASSERT(false) << "Implementation error. Should not be reachable."; + // decide how to connect and signals to create return; - } // end of isSpecialInputDir - - // exists and not special input directive, connected the name they are given. - // this name should be an ila-input, maybe we can check - - if (is_input) { - // TODO: FIXME: NEED TO CHECK w. ILA - // ILA_ERROR_IF( refstr is not an ila input ) - ILA_ERROR_IF(!chk(refstr, vlg_sig)) - << "Uncompatible input refinement:" << refstr << " for " << short_name - << ". Connect anyway. Please check."; - - mod_inst_rec.insert({short_name, {inf_dir_t::INPUT, "__ILA_I_" + refstr}}); - } - if (is_output) { - ILA_ERROR << "Cannot map output signals to ILA input for :" << refstr - << ", left unconnected."; - mod_inst_rec.insert({short_name, inf_connector_t({inf_dir_t::NC, ""})}); - } // ignoring it - // okay we are done now } // IntefaceDirectiveRecorder::RegisterInterface void IntefaceDirectiveRecorder::Clear(bool reset_vlg) { @@ -378,219 +194,10 @@ void IntefaceDirectiveRecorder::Clear(bool reset_vlg) { input_wires.clear(); internal_wires.clear(); output_wires.clear(); - abs_mems.clear(); - _reset_vlg = reset_vlg; -} - -void IntefaceDirectiveRecorder::SetMemName(const std::string& directive, - const std::string& ila_state_name, - bool abs_read) { - ILA_CHECK(beginsWith(directive, "**")); - if (!beginsWith(directive, "**MEM**")) { - ILA_ERROR << directive << " is not a recognized directive!"; - return; - } - - auto mem_name = directive.substr(7); - auto pos = abs_mems.find(mem_name); - if (pos == abs_mems.end()) { - ILA_INFO << directive << " refers to a new memory!"; - abs_mems.insert(std::make_pair(mem_name, VlgAbsMem())); - pos = abs_mems.find(mem_name); - // return; - } - - pos->second.read_abstract = abs_read; - - if (pos->second.mem_name == "") - pos->second.mem_name = mem_name; - if (pos->second.ila_map_name == "") - pos->second.ila_map_name = ila_state_name; - - // check no duplicate settings - ILA_ERROR_IF(pos->second.mem_name != mem_name) - << "Implementation bug," - << " setting memory abstraction with a different name" - << " old:" << pos->second.mem_name << ", new:" << mem_name; - ILA_ERROR_IF(pos->second.ila_map_name != ila_state_name) - << "Implementation bug," - << " setting memory abstraction with a different name" - << " old:" << pos->second.ila_map_name << ", new:" << ila_state_name; -} - -void IntefaceDirectiveRecorder::SetMemNameAndWidth( - const std::string& directive, const std::string& ila_state_name, - bool abs_read, int ila_addr_width, int ila_data_width) { - - ILA_CHECK(beginsWith(directive, "**")); - if (!beginsWith(directive, "**MEM**")) { - ILA_ERROR << directive << " is not a recognized directive!"; - return; - } - - auto mem_name = directive.substr(7); - auto pos = abs_mems.find(mem_name); - if (pos == abs_mems.end()) { - ILA_INFO << directive << " refers to a new memory!"; - abs_mems.insert(std::make_pair(mem_name, VlgAbsMem())); - pos = abs_mems.find(mem_name); - // return; - } - - pos->second.read_abstract = abs_read; - - if (pos->second.mem_name == "") - pos->second.mem_name = mem_name; - if (pos->second.ila_map_name == "") - pos->second.ila_map_name = ila_state_name; - - // check no duplicate settings - ILA_ERROR_IF(pos->second.mem_name != mem_name) - << "Implementation bug," - << " setting memory abstraction with a different name" - << " old:" << pos->second.mem_name << ", new:" << mem_name; - ILA_ERROR_IF(pos->second.ila_map_name != ila_state_name) - << "Implementation bug," - << " setting memory abstraction with a different name" - << " old:" << pos->second.ila_map_name << ", new:" << ila_state_name; - - ILA_CHECK(ila_addr_width > 0 && ila_data_width > 0); - pos->second.SetAddrWidth(ila_addr_width); - pos->second.SetDataWidth(ila_data_width); -} - -std::string IntefaceDirectiveRecorder::ConnectMemory( - const std::string& directive, const std::string& ila_state_name, - const std::map& rports, - const std::map& wports, int ila_addr_width, - int ila_data_width, bool abs_read) { - ILA_CHECK(beginsWith(directive, "**")); - if (!beginsWith(directive, "**MEM**")) { - ILA_ERROR << directive << " is not a recognized directive!"; - return VLG_TRUE; - } - - auto mem_name = directive.substr(7); - auto pos = abs_mems.find(mem_name); - if (pos == abs_mems.end()) { - ILA_ERROR << directive << " refers to a nonexisting memory!"; - return VLG_TRUE; - } - - // pos->second.read_abstract = abs_read; - SetMemNameAndWidth(directive, ila_state_name, abs_read, ila_addr_width, - ila_data_width); - - // copy the ports - ILA_ERROR_IF(pos->second.ila_rports.size() != 0 || - pos->second.ila_wports.size() != 0) - << mem_name << " seems to have been connected."; - // pos->second.ila_rports = rports; - pos->second.ila_rports.insert(rports.begin(), rports.end()); - // pos->second.ila_wports = wports; - pos->second.ila_wports.insert(wports.begin(), wports.end()); - - return pos->second.MemEQSignalName(); -} // ConnectMemory - -/// Check if some verilog port has been connected, -/// if not, connect it to the wire_name (will not create wire!) -/// if connected, will warn and refuse to connect -/// should be called before GetAbsMemInstString -std::pair -IntefaceDirectiveRecorder::KeepMemoryPorts(const std::string& mem_name, - const std::string& port_name, - bool caller_build_wire) { - -#define check_connect_port(p) \ - if (!(p).empty()) \ - ILA_ERROR << port_name << " has been connected"; \ - else \ - (p) = caller_build_wire ? wire_name : ""; - // set to empty here will cause absmem:CONNECT macro to add wire for it - - auto pos = abs_mems.find(mem_name); - if (pos == abs_mems.end()) { - ILA_ERROR << "No memory named: " << mem_name; - return std::pair( - "KeepMemoryPortsERROR_no_mem_name_" + mem_name, 0); - } - std::string wire_name = - "__MEM_" + VerilogGeneratorBase::sanitizeName(pos->second.ila_map_name) + - "_" + std::to_string(0) + "_" + port_name; - - if (port_name == "raddr") { - check_connect_port(pos->second.vlg_rports[0].raddr); - return std::make_pair(wire_name, pos->second.addr_width); - } else if (port_name == "rdata") { - check_connect_port(pos->second.vlg_rports[0].rdata); - return std::make_pair(wire_name, pos->second.data_width); - } else if (port_name == "ren") { - check_connect_port(pos->second.vlg_rports[0].ren); - return std::make_pair(wire_name, 1); - } else if (port_name == "waddr") { - check_connect_port(pos->second.vlg_wports[0].waddr); - return std::make_pair(wire_name, pos->second.addr_width); - } else if (port_name == "wdata") { - check_connect_port(pos->second.vlg_wports[0].wdata); - return std::make_pair(wire_name, pos->second.data_width); - } else if (port_name == "wen") { - check_connect_port(pos->second.vlg_wports[0].wen); - return std::make_pair(wire_name, 1); - } else - ILA_ERROR << "Unknown port:" << port_name; - return std::pair( - "KeepMemoryPortsERROR_no_port_name_" + port_name, 0); -} - -std::string -IntefaceDirectiveRecorder::GetAbsMemInstString(VerilogGeneratorBase& gen, - const std::string& endCond) { - std::string ret; - for (auto&& m : abs_mems) { - ret += "/*" + m.first + "*/\n"; - ret += m.second.GeneratingMemModuleSignalsInstantiation(gen, endCond); - } - return ret; -} - -void IntefaceDirectiveRecorder::InsertAbsMemAssmpt(assmpt_inserter_t inserter) { - for (auto&& nm_pair : abs_mems) { - for (auto&& assumpt : nm_pair.second.assumpts) - inserter(assumpt); - } -} - -// ------------------------------------------------------------------------ - -// static function -bool StateMappingDirectiveRecorder::isSpecialStateDir(const std::string& c) { - return IntefaceDirectiveRecorder::beginsWith(c, "**"); + _reset_vlg = reset_vlg; } -/// a function to determine if a state map refstr is special directie (**???) -bool StateMappingDirectiveRecorder::isSpecialStateDirMem(const std::string& c) { - return IntefaceDirectiveRecorder::beginsWith(c, "**MEM**"); -} -bool StateMappingDirectiveRecorder::isSpecialUnknownFunctionName(const std::string &funcname) { - if (funcname.length() < 11) - return false; - if (!StrStartsWith(funcname, "__unknown__")) - return false; - if (funcname == "__unknown__") - return true; - for (size_t idx = 11; idx < funcname.length(); ++ idx) - if (!isdigit(funcname.at(idx))) - return false; - return true; -} - -bool StateMappingDirectiveRecorder::isSpecialUnknownFunction(const FuncPtr &func_ptr) { - if (func_ptr->arg_num() > 0) - return false; - return isSpecialUnknownFunctionName(func_ptr->name().str()); -} } // namespace ilang diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index e2d5b2a54..7c007baf2 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -108,165 +108,6 @@ bool VlgSglTgtGen::TryFindVlgState(const std::string& sname) { return false; } -#define SIN(sub, s) (s.find(sub) != std::string::npos) - -/// signals generated in the wrapper, -/// it is normal that you cannot find -/// them in the verilog -std::set wrapper_signals = { - "__START__", "__IEND__", "__ISSUE__", - "__STARTED__", "__RESETED__", "__ENDED__", - "__ENDFLUSH__", "__FLUSHENDED__", "__CYCLE_CNT__"}; - -// for ila state: add __ILA_SO_ -// for verilog signal: keep as it is should be fine -// btw, record all referred vlg name -std::string -VlgSglTgtGen::ModifyCondExprAndRecordVlgName(const VarExtractor::token& t) { - // modify name and ... - const auto& token_tp = t.first; - const auto& sname = t.second; - - if (token_tp == VarExtractor::token_type::UNKN_S) { - ILA_WARN_IF(!IN(sname, wrapper_signals) && !IN(sname, vlg_wrapper.wires)) - << "In refinement relations: unknown reference to name:" << sname - << " keep unchanged."; - return sname; - } else if (token_tp == VarExtractor::token_type::KEEP) - return sname; // NC - else if (token_tp == VarExtractor::token_type::NUM) { - /* - if (_backend == backend_selector::COSA) { - if (SIN("'", sname)) { - auto l = Split(sname, "'"); - - auto& num_l = l.back(); - auto num = num_l.substr(1); // [1:] - int base = 16; - if (num_l[0] == 'd') - base = 10; - else if (num_l[0] == 'h') - base = 16; - else if (num_l[0] == 'b') - base = 2; - else if (num_l[0] == 'o') - base = 8; - else - ILA_ERROR << "unknown base in " << sname << ", assuming 16"; - - unsigned n = StrToInt(num, base); - unsigned int w; - if (l.size() == 2) { - w = StrToInt(l[0]); - } else { - w = ((unsigned int)std::floor(std::log2(n))) + 1; - ILA_WARN << sname << " is considered to be of width " << w; - } - return IntToStr(n) + "_" + IntToStr(w); - } else { - if (SIN("_", sname)) - return sname; // already changed to 0_1 - else { - auto n = StrToInt(sname); - unsigned int w = ((unsigned int)std::floor(std::log2(n))) + 1; - ILA_WARN << sname << " is considered to be of width " << w; - return IntToStr(n) + "_" + IntToStr(w); - } - } - } else if (_backend == backend_selector::JASPERGOLD) { - if (SIN("'", sname)) - return sname; - else { - if (SIN("_", sname)) { - return Split(sname, "_") - .front(); // remove the bitwidth, let jaspergold itself decide - } else - return sname; - } - }*/ - // else -- only leave it here - return sname; // NC - } else if (token_tp == VarExtractor::token_type::ILA_S) { - std::string quote = ""; - auto left_p = sname.find('['); - auto check_s = sname.substr(0, left_p); - auto range_s = left_p != std::string::npos ? sname.substr(left_p) : ""; - // if (_backend == backend_selector::COSA) - // quote = "'"; - // if it refers to ILA state - if (_host->state(check_s)) - return quote + "__ILA_SO_" + check_s + quote + range_s; - // if it uses the reference it self - auto hierName = Split(check_s, "."); - if (hierName.size() == 2) // maybe it contains an unnecessary head - if ((hierName[0] == _ila_mod_inst_name || hierName[0] == "ILA") && - _host->state(hierName[1])) - return quote + "__ILA_SO_" + hierName[1] + quote + range_s; - // should not reachable - ILA_CHECK(false) - << "Implementation bug: should not be reachable. token_tp: ILA_S"; - return sname; - } else if (token_tp == VarExtractor::token_type::ILA_IN) { - auto left_p = sname.find('['); - auto check_s = sname.substr(0, left_p); - auto range_s = left_p != std::string::npos ? sname.substr(left_p) : ""; - - std::string quote = ""; - // if (_backend == backend_selector::COSA) - // quote = "'"; - // if it refers to ILA state - if (_host->input(check_s)) - return quote + "__ILA_I_" + check_s + quote + range_s; - // if it uses the reference it self - auto hierName = Split(check_s, "."); - if (hierName.size() == 2) // maybe it contains an unnecessary head - if ((hierName[0] == _ila_mod_inst_name || hierName[0] == "ILA") && - _host->input(hierName[1])) - return quote + "__ILA_I_" + hierName[1] + quote + range_s; - // should not reachable - ILA_CHECK(false) - << "Implementation bug: should not be reachable. token_tp: ILA_IN"; - return sname; - } else if (token_tp == VarExtractor::token_type::VLG_S) { - - // do nothing for JasperGold - // will not add to the all_referred name, so will not modify verilog - if (_backend == backend_selector::JASPERGOLD) - return sname; - - std::string quote = ""; - auto left_p = sname.find('['); - auto check_s = sname.substr(0, left_p); - auto range_s = left_p != std::string::npos ? sname.substr(left_p) : ""; - auto range_underscore = ReplaceAll(ReplaceAll(range_s, "[", "_"), "]", "_"); - // if (_backend == backend_selector::COSA) - // quote = "'"; - - if (vlg_info_ptr->check_hierarchical_name_type(check_s) != - VerilogInfo::hierarchical_name_type::NONE) { - _all_referred_vlg_names.insert({check_s + range_s, ex_info_t(range_s)}); - auto remove_dot_name = ReplaceAll(check_s, ".", "__DOT__"); - // Convert the check_s to - return quote + remove_dot_name + quote + range_underscore; - } - if (vlg_info_ptr->check_hierarchical_name_type(_vlg_mod_inst_name + "." + - check_s) != - VerilogInfo::hierarchical_name_type::NONE) { - _all_referred_vlg_names.insert( - {_vlg_mod_inst_name + "." + check_s + range_s, ex_info_t(range_s)}); - auto remove_dot_name = ReplaceAll(check_s, ".", "__DOT__"); - return quote + _vlg_mod_inst_name + "__DOT__" + remove_dot_name + quote + - range_underscore; - } - ILA_CHECK(false) - << "Implementation bug: should not be reachable. token_type: VLG_S"; - return sname; - } - ILA_CHECK(false) - << "Implementation bug: should not reachable. Caused by token_type:" - << token_tp; - return sname; -} // static function unsigned VlgSglTgtGen::TypeMatched(const ExprPtr& ila_var, @@ -313,137 +154,14 @@ unsigned VlgSglTgtGen::get_width(const ExprPtr& n) { return VerilogGeneratorBase::get_width(n); } -// static function -bool isEqu(const std::string& c) { return (c.find("=") != std::string::npos); } - -// will create new variables "m?" and return it -// 1. "ila-state":"**MEM**.?" -// 2a. "ila-state":"statename" --> PerStateMap -// 2b. "ila-state":"(cond)&map" --> PerStateMap -// 3. "ila-state":[ "cond&map" ] -// 4. "ila-state":[ {"cond":,"map":}, ] - -// Replace an expr's variable name -std::string VlgSglTgtGen::ReplExpr(const std::string& expr, - bool force_vlg_sts) { - return _vext.Replace(expr, force_vlg_sts, - [this](const VarExtractor::token& t) { - return ModifyCondExprAndRecordVlgName(t); - }); -} - -std::string VlgSglTgtGen::PerStateMap(const std::string& ila_state_name, - const std::string& vlg_st_name) { - if (vlg_st_name.size() == 0) { - ILA_INFO << "Skip mapping ila state:" << ila_state_name; - return VLG_TRUE; - } - - if (isEqu(vlg_st_name)) { // is equ - // not using re here - auto new_expr = ReplExpr(vlg_st_name); - - if (_backend == backend_selector::JASPERGOLD and - new_expr.find('[') != new_expr.npos) { - // this is a jasper gold bug - return new_expr; - } - - std::string map_sig = new_mapping_id(); - vlg_wrapper.add_wire(map_sig, 1, true); - vlg_wrapper.add_output(map_sig, 1); - add_wire_assign_assumption(map_sig, new_expr, "vmap"); - return map_sig; - } - // else it is a vlg signal name - auto ila_state = TryFindIlaVarName(ila_state_name); - if (!ila_state) - return VLG_TRUE; - if (ila_state->sort()->is_mem()) { - // we need to decide if this memory is internal/external; - bool external = _vlg_cfg.extMem; - if (IN(ila_state_name, supplementary_info.memory_export)) - external = supplementary_info.memory_export.at(ila_state_name); - - if (!external) { // if internal - // if you choose to expand the array then we are able to handle with out - // MEM directive - int addr_range = std::pow(2, ila_state->sort()->addr_width()); // 2^N - int specify_range = asthub::GetMemSize(ila_state); - ILA_ERROR_IF(specify_range > addr_range) - << "For memory state: " << ila_state_name << ", its address width is" - << ila_state->sort()->addr_width() << " which can hold " << addr_range - << " addrs" - << ", but range: " << specify_range - << " is specified with SetEntryNum"; - if (specify_range != 0) - addr_range = specify_range; - // construct expansion expression - std::string map_expr; - for (int idx = 0; idx < addr_range; ++idx) { - if (!map_expr.empty()) - map_expr += "&&"; - map_expr += - "( __ILA_SO_" + ila_state_name + "_" + std::to_string(idx) + - " == " + - ReplExpr(vlg_st_name + "[" + std::to_string(idx) + "]", true) + ")"; - } - std::string map_sig = new_mapping_id(); - vlg_wrapper.add_wire(map_sig, 1, true); - vlg_wrapper.add_output(map_sig, 1); - add_wire_assign_assumption(map_sig, map_expr, "vmap"); - return map_sig; - } else { - ILA_ERROR - << "Please use **MEM**.? directive for memory state matching of " - << ila_state_name; - return VLG_TRUE; - } - } - // check for state match -- (no '=' inside at this step) - std::string vlg_state_name = vlg_st_name; - if (vlg_state_name.find(".") == std::string::npos && - vlg_state_name.find("#") == std::string::npos) { - vlg_state_name = _vlg_mod_inst_name + "." + vlg_state_name; - } // auto-add module name - - { // handle [] - auto pos = vlg_state_name.find('['); - auto vlg_state_name_wo_idx = vlg_state_name; - if (pos != vlg_state_name.npos) - vlg_state_name_wo_idx = vlg_state_name_wo_idx.substr(0, pos); - - if (vlg_info_ptr->check_hierarchical_name_type(vlg_state_name_wo_idx) != - VerilogInfo::hierarchical_name_type::NONE) { - // if this is truly a state name - auto vlg_sig_info = vlg_info_ptr->get_signal( - vlg_state_name_wo_idx, supplementary_info.width_info); - ILA_ERROR_IF(!TypeMatched(ila_state, vlg_sig_info)) - << "ila state:" << ila_state_name - << " has mismatched type w. verilog signal:" << vlg_state_name_wo_idx; - } else { - ILA_INFO_IF(!S_IN('#', vlg_state_name_wo_idx)) - << "rfmap: treating: " << vlg_state_name_wo_idx - << " as an expression."; - } - } +std::string VlgSglTgtGen::ReplExpr(const rfmap::RfExpr & in) { + bool replace_dot = _backend != VlgSglTgtGen::backend_selector::JASPERGOLD; + + auto new_node = refinement_map.ReplacingRtlIlaVar(in, replace_dot); + return new_node->to_verilog(); +} - // add signal -- account for jg's bug - if (_backend == backend_selector::JASPERGOLD && - vlg_state_name.find('[') != vlg_state_name.npos) - return ReplExpr(vlg_state_name, true) + " == __ILA_SO_" + - ila_state->name().str(); - - std::string map_sig = new_mapping_id(); - vlg_wrapper.add_wire(map_sig, 1, true); - vlg_wrapper.add_output(map_sig, 1); - add_wire_assign_assumption(map_sig, - ReplExpr(vlg_state_name, true) + " == __ILA_SO_" + - ila_state->name().str(), - "vmap"); - return map_sig; -} // PerStateMap // ila-state -> ref (json) // return a verilog verilog, that should be asserted to be true for this purpose @@ -565,35 +283,14 @@ std::string VlgSglTgtGen::GetStateVarMapExpr(const std::string& ila_state_name, return VLG_TRUE; } // GetStateVarMapExpr -void VlgSglTgtGen::handle_start_condition(nlohmann::json& dc) { - if (!dc.is_array()) { - ILA_ERROR << " not enforcing start condition: expect an array of strings."; - return; - } - for (auto&& pr : dc.items()) { - if (!pr.value().is_string()) { - ILA_ERROR - << " not enforcing start condition: expect an array of strings."; - continue; - } - auto cond = pr.value().get(); - cond = ReplaceAll(ReplaceAll(cond, "$decode$", vlg_ila.decodeNames[0]), - "$valid$", vlg_ila.validName); - add_an_assumption("(~ __START__) || " + ReplExpr(cond), "start_condition"); - // ReplExpr: Yes, you need to translate it to the vlg names +void VlgSglTgtGen::handle_start_condition(const std::vector & dc) { + for (const auto & c : dc) { + auto cond = ReplExpr(c); + cond = ReplaceAll(ReplaceAll(cond, "$decode", vlg_ila.decodeNames[0]), + "$valid", vlg_ila.validName); + add_an_assumption("(~ __START__) || (" + cond +")", "start_condition"); } } // handle_start_condition -// use instruction pointer and the rf_cond to get it (no need to provide) -nlohmann::json& VlgSglTgtGen::get_current_instruction_rf() { - if (_instr_ptr == nullptr) - return empty_json; - auto& instrs = rf_cond["instructions"]; - for (auto&& instr : instrs) { - if (instr["instruction"] == _instr_ptr->name().str()) - return instr; - } - return empty_json; -} }; // namespace ilang diff --git a/src/vtarget-out/inv-syn/rel_chc.cc b/src/vtarget-out/inv-syn/rel_chc.cc index 2dcb52940..2c5e519a1 100644 --- a/src/vtarget-out/inv-syn/rel_chc.cc +++ b/src/vtarget-out/inv-syn/rel_chc.cc @@ -578,10 +578,9 @@ bool static extractSigDefFromLine( std::string ret_tpl_smt; - if (_vtg_config.VerificationSettingAvoidIssueStage) - ret_tpl_smt = dual_ind_inv_reset_start_tmpl; - else - ret_tpl_smt = dual_ind_inv_tmpl; + ret_tpl_smt = dual_ind_inv_reset_start_tmpl; + + { // replacing the init sequence ret_tpl_smt = ReplaceAll(ReplaceAll(ret_tpl_smt, "%BIn%", BIn), "%rstseq%", rstseq); } diff --git a/src/vtarget-out/inv-syn/vtarget_gen_inv_abc.cc b/src/vtarget-out/inv-syn/vtarget_gen_inv_abc.cc index 30e3c2cda..ecb07b8f0 100644 --- a/src/vtarget-out/inv-syn/vtarget_gen_inv_abc.cc +++ b/src/vtarget-out/inv-syn/vtarget_gen_inv_abc.cc @@ -334,7 +334,7 @@ void VlgSglTgtGen_Abc::Export_modify_verilog() { VerilogModifier vlg_mod(vlg_info_ptr, static_cast( _vtg_config.PortDeclStyle), - _vtg_config.CosaAddKeep, + _vtg_config.PonoAddKeep, supplementary_info.width_info); for (auto&& refered_vlg_item : _all_referred_vlg_names) { diff --git a/src/vtarget-out/inv-syn/vtarget_gen_inv_chc.cc b/src/vtarget-out/inv-syn/vtarget_gen_inv_chc.cc index af6bc8672..a56eeefe8 100644 --- a/src/vtarget-out/inv-syn/vtarget_gen_inv_chc.cc +++ b/src/vtarget-out/inv-syn/vtarget_gen_inv_chc.cc @@ -351,7 +351,7 @@ void VlgSglTgtGen_Chc::Export_modify_verilog() { VerilogModifier vlg_mod(vlg_info_ptr, static_cast( _vtg_config.PortDeclStyle), - _vtg_config.CosaAddKeep, + _vtg_config.PonoAddKeep, supplementary_info.width_info); for (auto&& refered_vlg_item : _all_referred_vlg_names) { diff --git a/src/vtarget-out/inv-syn/vtarget_gen_inv_enhance.cc b/src/vtarget-out/inv-syn/vtarget_gen_inv_enhance.cc index 9991937d3..247a7d250 100644 --- a/src/vtarget-out/inv-syn/vtarget_gen_inv_enhance.cc +++ b/src/vtarget-out/inv-syn/vtarget_gen_inv_enhance.cc @@ -320,7 +320,7 @@ void VlgSglTgtGen_Chc_wCNF::Export_modify_verilog() { VerilogModifier vlg_mod(vlg_info_ptr, static_cast( _vtg_config.PortDeclStyle), - _vtg_config.CosaAddKeep, + _vtg_config.PonoAddKeep, supplementary_info.width_info); for (auto&& refered_vlg_item : _all_referred_vlg_names) { diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index 2f0adaf39..c3d6a71b3 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -32,41 +32,37 @@ VlgSglTgtGen::VlgSglTgtGen( output_path, // will be a sub directory of the output_path of its parent const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, const VerilogGenerator::VlgGenConfig& config, - nlohmann::json& _rf_vmap, nlohmann::json& _rf_cond, - VlgTgtSupplementaryInfo& _supplementary_info, VerilogInfo* _vlg_info_ptr, - const std::string& vlg_mod_inst_name, const std::string& ila_mod_inst_name, + const InstrLvlAbsPtr& ila_ptr, + const rfmap::VerilogRefinementMap & refinement, + VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, const vtg_config_t& vtg_config, backend_selector backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr) : _output_path(output_path), _instr_ptr(instr_ptr), _host(ila_ptr), - _vlg_mod_inst_name(vlg_mod_inst_name), - _ila_mod_inst_name(ila_mod_inst_name), + _vlg_mod_inst_name("RTL"), + _ila_mod_inst_name("ILA"), // default option on wrapper vlg_wrapper( - VerilogGenerator::VlgGenConfig(config, // use default configuration - true, + VerilogGenerator::VlgGenConfig(true, // ExternalMem VerilogGeneratorBase::VlgGenConfig:: funcOption::External, // function false, // no start signal + false, // no pass node name false, // no rand init false, // no expand memory false), // no collect ITE unknown wrapper_name), // use given, except for core options vlg_ila(VerilogGeneratorBase::VlgGenConfig( - config, - // except overwriting these: external memory - // if expand memory, then the ila's memory must be internal - config - .extMem, // this depends on the given configuration (default case) - VerilogGeneratorBase::VlgGenConfig::funcOption::External, true, - true, // rand init - true, // for internal should always expand (probe) memory - vtg_config - .IteUnknownAutoIgnore // may collect depends on configuration + false, // default case: internal memory + VerilogGeneratorBase::VlgGenConfig::funcOption::External, // external function + true, // w. start signal + vtg_config.VerilogGenPassNodeName, // pass node name + false, // no rand init + false, // no expand memory + false // no collecte ITE unknown )), // interface mapping directive // -------- CONTROLLING THE RESET CONNECTION ------------- // @@ -78,21 +74,19 @@ VlgSglTgtGen::VlgSglTgtGen( // but if forced, we do; For the design only thing // we do ensure reset also - // state-mapping directive - _sdr(), // currently no // verilog info vlg_info_ptr(_vlg_info_ptr), // variable extractor - _vext( - [this](const std::string& n) -> bool { return TryFindIlaState(n); }, - [this](const std::string& n) -> bool { return TryFindIlaInput(n); }, - [this](const std::string& n) -> bool { return TryFindVlgState(n); }), + //_vext( + // [this](const std::string& n) -> bool { return TryFindIlaState(n); }, + // [this](const std::string& n) -> bool { return TryFindIlaInput(n); }, + // [this](const std::string& n) -> bool { return TryFindVlgState(n); }), // ref to refmaps - rf_vmap(_rf_vmap), rf_cond(_rf_cond), empty_json(nullptr), - supplementary_info(_supplementary_info), + refinement_map(refinement, ??? ), + target_type(target_tp), // whether it is // invariant/instructions - has_flush(false), ready_type(ready_type_t::NA), max_bound(127), + max_bound(127), cnt_width(1), _advanced_param_ptr(adv_ptr), has_gussed_synthesized_invariant( adv_ptr && adv_ptr->_candidate_inv_ptr && @@ -100,14 +94,11 @@ VlgSglTgtGen::VlgSglTgtGen( has_confirmed_synthesized_invariant( adv_ptr && adv_ptr->_inv_obj_ptr && !adv_ptr->_inv_obj_ptr->GetVlgConstraints().empty()), - has_rf_invariant((IN("global invariants", _rf_cond) && - rf_cond["global invariants"].size() != 0) || - (IN("global-invariants", _rf_cond) && - rf_cond["global-invariants"].size() != 0)), + has_rf_invariant(!refinement_map.global_invariants.empty()), mapping_counter(0), property_counter(0), top_mod_name(wrapper_name), vlg_design_files(implementation_srcs), vlg_include_files_path(implementation_include_path), - _vtg_config(vtg_config), _vlg_cfg(config), _backend(backend), + _vtg_config(vtg_config), _backend(backend), _bad_state(false) { ILA_NOT_NULL(_host); @@ -117,33 +108,29 @@ VlgSglTgtGen::VlgSglTgtGen( target_type == target_type_t::INV_SYN_DESIGN_ONLY) << "Implementation bug: unrecognized target type!"; - // reset absmem's counter - VlgAbsMem::ClearAbsMemRecord(); - - if (has_rf_invariant) { - if (IN("global invariants", rf_cond) && - !rf_cond["global invariants"].is_array()) { - ILA_ERROR - << "'global invariants' field in refinement relation has to be a " - "JSON array."; - _bad_state = true; - return; - } - if (IN("global-invariants", rf_cond) && - !rf_cond["global-invariants"].is_array()) { - ILA_ERROR - << "'global-invariants' field in refinement relation has to be a " - "JSON array."; - _bad_state = true; - return; - } - } if (target_type == target_type_t::INSTRUCTIONS) { ILA_NOT_NULL(instr_ptr); + RfmapIlaStateSanityCheck(); + // TODO: insert the memory export directive - vlg_ila.AnnotateMemory(supplementary_info.memory_export); // need to change this + VerilogGeneratorBase::memory_export_annotation_t mem_annotation; + for(unsigned sidx = 0; sidx < _host->state_num(); ++ sidx) { + const auto & s = _host->state(sidx); + if(!s->is_mem()) + continue; + const auto & n = s->name().str(); + auto pos = refinement_map.ila_state_var_map.find(n); + if (pos == refinement_map.ila_state_var_map.end()) + continue; + if(pos->second.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) + mem_annotation.emplace(n,true); + else + mem_annotation.emplace(n,false); + } // end - for each mem state + + vlg_ila.AnnotateMemory(mem_annotation); // need to change this vlg_ila.ExportTopLevelInstr(instr_ptr); @@ -164,69 +151,12 @@ VlgSglTgtGen::VlgSglTgtGen( << instr_ptr->name().str(); _bad_state = true; } - - if (IN("flush constraint", instr) && - not instr["flush constraint"].is_array()) { - ILA_ERROR - << "RF: 'flush constraint' filed must be an array of string for " - << instr_ptr->name().str(); - _bad_state = true; - } - - if (IN("pre-flush end", instr) && !instr["pre-flush end"].is_string()) { - ILA_ERROR << "RF: 'pre-flush end' field must be a string for " - << instr_ptr->name().str(); - _bad_state = true; - } - - if (IN("post-flush end", instr) && - not instr["post-flush end"].is_string()) { - ILA_ERROR << "RF: 'post-flush end' filed must be a string for " - << instr_ptr->name().str(); - _bad_state = true; - } - - if (IN("flush constraint", instr) && - instr["flush constraint"].size() != 0) { - if (IN("pre-flush end", instr) && instr["pre-flush end"].size() != 0 && - IN("post-flush end", instr) && instr["post-flush end"].size() != 0) - has_flush = true; // requiring three items - else { - ILA_ERROR - << "When using flushing, 'pre-flush end' and 'post-flush end' " - << "must be specify"; - _bad_state = true; - } - } - - if (IN("ready signal", instr) && - instr["ready signal"].size() != - 0) // whether a none-empty string or array... - ready_type = (ready_type_t)(ready_type | ready_type_t::READY_SIGNAL); - if (IN("ready bound", instr) && instr["ready bound"].is_number_integer()) - ready_type = (ready_type_t)(ready_type | ready_type_t::READY_BOUND); - if (ready_type == ready_type_t::NA) { - ILA_ERROR << "refinement relation for:" << instr_ptr->name().str() - << " has to specify a ready condition"; - _bad_state = true; - } } // END of target_type == INSTRUCTION else if (target_type == target_type_t::INVARIANTS) { ILA_WARN_IF(instr_ptr != nullptr) << "Provide an instruction " << "when verifying invariants. The instruction will not be used"; } - // if you supply additional invariant in the invariant synthesis - // they will still be a target for invariant generated. - // you can use it to verify the invariants if you like - ILA_CHECK(!(has_flush && - (backend & backend_selector::YOSYS) == backend_selector::YOSYS)) - << "Currently does not support flushing in invariant synthesis." - << "Future work."; - - ILA_CHECK(!(has_flush && vtg_config.VerificationSettingAvoidIssueStage)) - << "it is impossible to avoid issue stage for flushing refinement map, " - << "ignore this configuration option."; } // END of constructor void VlgSglTgtGen::ConstructWrapper_generate_header() { @@ -336,9 +266,7 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { FunctionApplicationFinder func_app_finder(_instr_ptr->update(sname)); for (auto&& func_ptr : func_app_finder.GetReferredFunc()) { // handle the IteUnknown function case - if (_vtg_config.IteUnknownAutoIgnore && - _sdr.isSpecialUnknownFunction(func_ptr)) - continue; + ILA_ERROR_IF(!(IN("functions", rf_vmap) && rf_vmap["functions"].is_object() && IN(func_ptr->name().str(), rf_vmap["functions"]))) @@ -349,8 +277,7 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { } // ISSUE ==> vmap - std::string precondition = - has_flush ? "(~ __ENDFLUSH__) || " : "(~ __IEND__) || "; + std::string precondition = "(~ __IEND__) || "; if (IN(sname, vlg_ila.state_update_ite_unknown)) { auto pos = vlg_ila.state_update_ite_unknown.find(sname); @@ -358,9 +285,6 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { } std::string problem_name = "variable_map_assert"; - if (_vtg_config.PerVariableProblemCosa && - (_backend & backend_selector::YOSYS) != backend_selector::YOSYS) - problem_name += "_" + sname; // for Yosys, we must keep the name the same // so it knows these are for variable map assertions @@ -386,22 +310,6 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { // 6 IEND ---> check varmap // 7 ENDED -// FLUSH case -// 1 RESET -// 2 RESETED ---> assume flush & preflush cond -// ... ---> assume flush & preflush cond -// n ISSUE = pre-flush end ---> assume flush & preflush cond -// n+1 START ---> assume varmap ---> assume inv -// (maybe globally?) n+2 STARTED n+3 STARTED -// ... ... (forever) -// m IEND -// m+1 ENDED ---> assume flush & postflush cond -// ... ENDED (forever) ---> assume flush & postflush cond -// l ENDFLUSH = post-flush end ---> assume flush & postflush cond -// ---> assert varmap l+1 FLUSHENDED ---> assume flush -// & postflush cond -// - // for invariants or for instruction void VlgSglTgtGen::ConstructWrapper() { ILA_CHECK(target_type == target_type_t::INVARIANTS || @@ -469,7 +377,10 @@ void VlgSglTgtGen::ConstructWrapper() { // post value holder --- ABC cannot work on this if (target_type == target_type_t::INSTRUCTIONS) { ConstructWrapper_add_post_value_holder(); + ConstructWrapper_add_delay_unit(); + ConstructWrapper_add_stage_tracker(); } + ConstructWrapper_add_vlg_monitor(); // add monitor -- inside the monitor, there will be // disable logic if it is for invariant type target @@ -479,8 +390,7 @@ void VlgSglTgtGen::ConstructWrapper() { // type // 5.0 add the extra wires to the top module wrapper - if (_backend == backend_selector::COSA || - (_backend & backend_selector::YOSYS) == backend_selector::YOSYS) + if (VlgVerifTgtGenBase::backend_needs_yosys(_backend)) ConstructWrapper_register_extra_io_wire(); ILA_DLOG("VtargetGen") << "STEP:" << 9; @@ -498,7 +408,16 @@ void VlgSglTgtGen::Export_wrapper(const std::string& wrapper_name) { return; } vlg_wrapper.DumpToFile(fout); + + // for append verilog + for(const auto & vlg_monitor : refinement_map.customized_monitor) { + if(vlg_monitor.second.verilog_append.empty()) + continue; + fout << "/***** Monitor for " << vlg_monitor.first << " *****/\n"; + fout << vlg_monitor.second.verilog_append; + } } + /// export the ila verilog void VlgSglTgtGen::Export_ila_vlg(const std::string& ila_vlg_name) { @@ -511,9 +430,7 @@ void VlgSglTgtGen::Export_ila_vlg(const std::string& ila_vlg_name) { ila_file_name = ila_vlg_name; std::ofstream fout; std::string fn; - if (_backend == backend_selector::COSA || - (_backend & backend_selector::YOSYS) == backend_selector::YOSYS || - (_backend == backend_selector::RELCHC)) { + if (VlgVerifTgtGenBase::backend_needs_yosys(_backend)) { fn = os_portable_append_dir(_output_path, top_file_name); fout.open(fn, std::ios_base::app); } else if (_backend == backend_selector::JASPERGOLD) { @@ -525,7 +442,7 @@ void VlgSglTgtGen::Export_ila_vlg(const std::string& ila_vlg_name) { return; } vlg_ila.DumpToFile(fout); -} +} // end of Export_ila_vlg void VlgSglTgtGen::ExportAll(const std::string& wrapper_name, const std::string& ila_vlg_name, @@ -547,6 +464,6 @@ void VlgSglTgtGen::ExportAll(const std::string& wrapper_name, Export_problem(extra_name); Export_script(script_name); -} +} // end of ExportAll } // namespace ilang diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index b1ea955fb..1d9ba22bf 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -35,48 +35,23 @@ namespace ilang { // 6 IEND ---> check varmap // 7 ENDED -// FLUSH case -// 1 RESET -// 2 RESETED ---> assume flush & preflush cond -// ... ---> assume flush & preflush cond -// n ISSUE = pre-flush end ---> assume flush & preflush cond -// n+1 START ---> assume varmap ---> assume inv -// (maybe globally?) n+2 STARTED n+3 STARTED -// ... ... (forever) -// m IEND -// m+1 ENDED ---> assume flush & postflush cond -// ... ENDED (forever) ---> assume flush & postflush cond -// l ENDFLUSH = post-flush end ---> assume flush & postflush cond -// ---> assert varmap l+1 FLUSHENDED ---> assume flush -// & postflush cond -// /// setup reset, add assumptions if necessary void VlgSglTgtGen::ConstructWrapper_reset_setup() { if (target_type == target_type_t::INSTRUCTIONS) { vlg_wrapper.add_input("dummy_reset", 1); vlg_wrapper.add_wire("dummy_reset", 1, true); - if (_vtg_config.InstructionNoReset || - supplementary_info.cosa_yosys_reset_config - .no_reset_after_starting_state) + if (_vtg_config.InstructionNoReset) add_an_assumption(" (~__RESETED__) || (dummy_reset == 0) ", "noreset"); } else if (target_type == target_type_t::INVARIANTS || target_type == target_type_t::INV_SYN_DESIGN_ONLY) { - if (supplementary_info.cosa_yosys_reset_config - .no_reset_after_starting_state) { - if (_backend == backend_selector::COSA) { - add_a_direct_assumption("reset_done = 1_1 -> rst = 0_1", - "noresetagain"); - add_a_direct_assumption("reset_done = 1_1 -> next( reset_done ) = 1_1", - "noresetnextdone"); - } else if (_backend == backend_selector::JASPERGOLD) { + if (_vtg_config.InvariantCheckNoReset) { + if (_backend == backend_selector::JASPERGOLD) { // no need to any thing - } else if ((_backend & backend_selector::YOSYS) == - backend_selector::YOSYS) { + } else if (VlgVerifTgtGenBase::backend_needs_yosys(_backend)) { add_a_direct_assumption("rst == 0", "noreset"); } } - // COSA : direct assumption // JasperGold will not mess with it // yosys : abc needs assumptions but not all of them } @@ -86,35 +61,32 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { // find in rf_cond, how many cycles will be needed max_bound = 0; - auto& instr = get_current_instruction_rf(); + const auto& instr = get_current_instruction_rf(); - if (!instr.is_null() && IN("ready bound", instr) && - instr["ready bound"].is_number_integer()) - max_bound = instr["ready bound"].get(); + if(instr.is_readybound()) + max_bound = instr.ready_bound; else max_bound = _vtg_config.MaxBound; + if(instr.max_bound > max_bound) + max_bound = instr.max_bound; - cnt_width = (int)std::ceil(std::log2(max_bound + 10)); + cnt_width = (int)std::ceil(std::log2(max_bound + 20)); vlg_wrapper.add_reg("__CYCLE_CNT__", cnt_width); // by default it will be an output reg vlg_wrapper.add_stmt("always @(posedge clk) begin"); vlg_wrapper.add_stmt("if (rst) __CYCLE_CNT__ <= 0;"); vlg_wrapper.add_stmt( "else if ( ( __START__ || __STARTED__ ) && __CYCLE_CNT__ < " + - IntToStr(max_bound + 5) + ") __CYCLE_CNT__ <= __CYCLE_CNT__ + 1;"); + IntToStr(max_bound + 10) + ") __CYCLE_CNT__ <= __CYCLE_CNT__ + 1;"); vlg_wrapper.add_stmt("end"); vlg_wrapper.add_reg("__START__", 1); vlg_wrapper.add_stmt("always @(posedge clk) begin"); // how start is triggered - if (_vtg_config.VerificationSettingAvoidIssueStage) { + vlg_wrapper.add_stmt("if (rst) __START__ <= 1;"); vlg_wrapper.add_stmt("else if (__START__ || __STARTED__) __START__ <= 0;"); - } else { - vlg_wrapper.add_stmt("if (rst) __START__ <= 0;"); - vlg_wrapper.add_stmt("else if (__START__ || __STARTED__) __START__ <= 0;"); - vlg_wrapper.add_stmt("else if (__ISSUE__) __START__ <= 1;"); - } + vlg_wrapper.add_stmt("end"); vlg_wrapper.add_reg("__STARTED__", 1); @@ -166,60 +138,29 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { // we don't need additional signals, just make reset drives the design // find the instruction - auto& instr = get_current_instruction_rf(); - ILA_CHECK(!instr.is_null()); + const auto& instr = get_current_instruction_rf(); + // __IEND__ std::string iend_cond = VLG_FALSE; // bool no_started_signal = false; - if (ready_type & ready_type_t::READY_SIGNAL) { - if (instr["ready signal"].is_string()) { - iend_cond += "|| (" + - ReplExpr(instr["ready signal"].get(), true) + - ")"; // force vlg - } else if (instr["ready signal"].is_array()) { - for (auto&& cond : instr["ready signal"]) - if (cond.is_string()) - iend_cond += " || (" + ReplExpr(cond.get()) + ")"; - else - ILA_ERROR << "ready signal field of instruction: " - << _instr_ptr->name().str() - << " has to be string or array or string"; - } else - ILA_ERROR << "ready signal field of instruction: " - << _instr_ptr->name().str() - << " has to be string or array or string"; + if(instr.is_readysignal()) { + iend_cond += "|| (" + ReplExpr(instr.ready_signal) + ")"; + } else { + ILA_ASSERT(instr.is_readybound()); + unsigned bound = instr.ready_bound; + ILA_ERROR_IF(bound == 0) + << "Does not support bound : 0, please use a buffer to hold " + "the signal."; + iend_cond += "|| ( __CYCLE_CNT__ == " + IntToStr(cnt_width) + "'d" + + IntToStr(bound) + ")"; } - if (ready_type & ready_type_t::READY_BOUND) { // can be both applied - if (instr["ready bound"].is_number_integer()) { - int bound = instr["ready bound"].get(); - if (bound > 0) { - // okay now we enforce the bound - iend_cond += "|| ( __CYCLE_CNT__ == " + - ReplExpr(IntToStr(cnt_width) + "'d" + IntToStr(bound)) + - ")"; - } else if (bound == 0) { - // iend_cond += "|| (__START__)"; - // no_started_signal = true; // please don't use && STARTED - ILA_ERROR << "Does not support bound : 0, please use a buffer to hold " - "the signal."; - } else - ILA_ERROR << "ready bound field of instruction: " - << _instr_ptr->name().str() - << " has to a non negative integer"; - } else - ILA_ERROR << "ready bound field of instruction: " - << _instr_ptr->name().str() << " has to a non negative integer"; - } // end of ready bound/condition // max bound for max checking range std::string max_bound_constr; - if (IN("max bound", instr)) { - if (instr["max bound"].is_number_integer()) { - max_bound_constr = - "&& ( __CYCLE_CNT__ <= " + IntToStr(instr["max bound"].get()) + - ")"; - } + if(instr.max_bound != 0) { + max_bound_constr = + "&& ( __CYCLE_CNT__ <= " + IntToStr(instr.max_bound) + ")"; } vlg_wrapper.add_wire("__IEND__", 1, true); @@ -228,7 +169,7 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { // add_wire_assign_assumption("__IEND__", "(" + iend_cond + ")", // "IEND"); // else - auto end_no_recur = has_flush ? "(~ __FLUSHENDED__ )" : "(~ __ENDED__)"; + auto end_no_recur = "(~ __ENDED__)"; add_wire_assign_assumption("__EDCOND__", "(" + iend_cond + ") && __STARTED__ ", "EDCOND"); @@ -239,10 +180,9 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { end_no_recur + max_bound_constr, "IEND"); // handle start decode - ILA_ERROR_IF(IN("start decode", instr)) - << "'start decode' is replaced by start condition!"; - if (IN("start condition", instr)) { - handle_start_condition(instr["start condition"]); + + if (!instr.start_condition.empty()) { + handle_start_condition(instr.start_condition); } else { add_an_assumption("(~ __START__) || (" + vlg_ila.decodeNames[0] + ")", "issue_decode"); // __ISSUE__ |=> decode @@ -250,76 +190,13 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { "issue_valid"); // __ISSUE__ |=> decode } - if (has_flush) { - ILA_CHECK(IN("pre-flush end", instr) && - IN("post-flush end", instr)); // there has to be something - - std::string issue_cond; - if (instr["pre-flush end"].is_string()) - issue_cond = "(" + ReplExpr(instr["pre-flush end"].get()) + - ") && __RESETED__"; - else { - issue_cond = "1"; - ILA_ERROR << "pre-flush end field should be a string!"; - } - vlg_wrapper.add_wire("__ISSUE__", 1, true); - add_wire_assign_assumption("__ISSUE__", issue_cond, "ISSUE"); - - std::string finish_cond; - if (instr["post-flush end"].is_string()) - finish_cond = "(" + ReplExpr(instr["post-flush end"].get()) + - ") && __ENDED__"; - else { - finish_cond = "1"; - ILA_ERROR << "post-flush end field should be a string!"; - } - vlg_wrapper.add_wire("__ENDFLUSH__", 1, true); - add_wire_assign_assumption("__ENDFLUSH__", finish_cond, "ENDFLUSH"); - - vlg_wrapper.add_reg("__FLUSHENDED__", 1); - vlg_wrapper.add_stmt( - "always @(posedge clk) begin\n" - "if(rst) __FLUSHENDED__ <= 0;\n" - "else if( __ENDFLUSH__ && __ENDED__ ) __FLUSHENDED__ <= 1;\n end"); - - // enforcing flush constraints - std::string flush_enforcement = VLG_TRUE; - if (instr["flush constraints"].is_null()) { - // do nothing. we are good - } else if (instr["flush constraints"].is_string()) { - flush_enforcement += - "&& (" + ReplExpr(instr["flush constraints"].get()) + - ")"; - } else if (instr["flush constraints"].is_array()) { - for (auto&& c : instr["flush constraints"]) - if (c.is_string()) - flush_enforcement += "&& (" + ReplExpr(c.get()) + ")"; - else - ILA_ERROR << "flush constraint field of instruction:" - << _instr_ptr->name().str() - << " must be a string or an array of string."; - } else - ILA_ERROR << "flush constraint field of instruction:" - << _instr_ptr->name().str() - << " must be string or array of string."; - - // TODO: preflush and postflush - - add_an_assumption( - "(~ ( __RESETED__ && ~ ( __START__ || __STARTED__ ) ) ) || (" + - flush_enforcement + ")", - "flush_enforce_pre"); - add_an_assumption("(~ ( __ENDED__ )) || (" + flush_enforcement + ")", - "flush_enforce_post"); + vlg_wrapper.add_wire("__ISSUE__", 1, true); + if (_vtg_config.ForceInstCheckReset) { + vlg_wrapper.add_input("__ISSUE__", 1); + } else + add_wire_assign_assumption("__ISSUE__", "1", "ISSUE"); // issue ASAP + // start decode -- issue enforce (e.g. valid, input) - } else { - vlg_wrapper.add_wire("__ISSUE__", 1, true); - if (_vtg_config.ForceInstCheckReset) { - vlg_wrapper.add_input("__ISSUE__", 1); - } else - add_wire_assign_assumption("__ISSUE__", "1", "ISSUE"); // issue ASAP - // start decode -- issue enforce (e.g. valid, input) - } // end of no flush } // ConstructWrapper_add_condition_signals } // namespace ilang diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index 7511d0644..888d36d80 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -95,18 +95,11 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { std::string func_reg_w = func_app.func_name + "_" + IntToStr(func_no) + "_result_wire"; - std::string func_reg = - func_app.func_name + "_" + IntToStr(func_no) + "_result_reg"; - vlg_wrapper.add_reg(func_reg, func_app.result.second); + vlg_wrapper.add_wire(func_reg_w, func_app.result.second, true); // add as a module input, also vlg_wrapper.add_input(func_reg_w, func_app.result.second); - add_reg_cassign_assumption(func_reg, func_reg_w, func_app.result.second, - "__START__", "func_result"); - // vlg_wrapper.add_always_stmt( "if( __START__ ) " + func_reg + " <= " + - // func_reg_w + ";" ); - retStr += " ." + func_app.result.first + "(" + func_reg_w + "),\n"; unsigned argNo = 0; @@ -116,12 +109,9 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { std::string func_arg_w = func_app.func_name + "_" + IntToStr(func_no) + "_arg" + IntToStr(argNo) + "_wire"; - std::string func_arg = func_app.func_name + "_" + IntToStr(func_no) + - "_arg" + IntToStr(argNo) + "_reg"; - vlg_wrapper.add_reg(func_arg, arg.second); + // this should be module output vlg_wrapper.add_wire(func_arg_w, arg.second, true); - add_reg_cassign_assumption(func_arg, func_arg_w, arg.second, "__START__", - "func_arg"); + // vlg_wrapper.add_always_stmt( "if( __START__ ) " + func_arg + " <= " + // func_arg_w + ";" ); @@ -228,11 +218,22 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { auto wdw = "__IMEM_" + ila_name + "_" + IntToStr(no) + "_wdata"; auto waw = "__IMEM_" + ila_name + "_" + IntToStr(no) + "_waddr"; auto wew = "__IMEM_" + ila_name + "_" + IntToStr(no) + "_wen"; + auto wdw_delay = wdw + "_d1"; + auto waw_delay = waw + "_d1"; + auto wew_delay = wew + "_d1"; vlg_wrapper.add_wire(wdw, dw, true); vlg_wrapper.add_wire(waw, aw, true); vlg_wrapper.add_wire(wew, 1, true); + // latch the write signal + vlg_wrapper.add_reg(wdw_delay, dw); + vlg_wrapper.add_reg(waw_delay, aw); + vlg_wrapper.add_reg(wew_delay, 1); + vlg_wrapper.add_always_stmt("if (__START__) " + wdw_delay + " <= " + wdw + ";"); + vlg_wrapper.add_always_stmt("if (__START__) " + waw_delay + " <= " + waw + ";"); + vlg_wrapper.add_always_stmt("if (__START__) " + wew_delay + " <= " + wew + ";"); + retStr += " ." + port.wdata + "(" + wdw + "),\n"; retStr += " ." + port.waddr + "(" + waw + "),\n"; retStr += " ." + port.wen + "(" + wew + "),\n"; @@ -273,29 +274,31 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { void VlgSglTgtGen::ConstructWrapper_add_vlg_input_output() { auto vlg_inputs = - vlg_info_ptr->get_top_module_io(supplementary_info.width_info); - auto& io_map = IN("interface mapping", rf_vmap) - ? rf_vmap["interface mapping"] - : rf_vmap["interface-mapping"]; + vlg_info_ptr->get_top_module_io(refinement_map.width_info); + + ILA_CHECK( + refinement_map.rtl_interface_connection.clock_domain_defs.size() == 1 + && IN("default", refinement_map.rtl_interface_connection.clock_domain_defs)) + << "Not implemented. Cannot handle multi-clock."; + + ILA_CHECK( + refinement_map.rtl_interface_connection.custom_reset_domain_defs.empty() + ) << "Not implemented. Cannot handle customized reset."; + + const auto & clock_pins = refinement_map.rtl_interface_connection.clock_domain_defs.at("default"); + const auto & reset_pins = refinement_map.rtl_interface_connection.reset_pins; + const auto & nreset_pins= refinement_map.rtl_interface_connection.nreset_pins; for (auto&& name_siginfo_pair : vlg_inputs) { - std::string refstr = - IN(name_siginfo_pair.first, io_map) - ? io_map[name_siginfo_pair.first].get() - : ""; + std::string refstr = "**KEEP**"; + if(IN(name_siginfo_pair.first, clock_pins)) + refstr = "**CLOCK**"; + else if (IN(name_siginfo_pair.first, reset_pins)) + refstr = "**RESET**"; + else if (IN(name_siginfo_pair.first, nreset_pins)) + refstr = "**NRESET**"; + _idr.RegisterInterface( - name_siginfo_pair.second, refstr, - // Verifier_compatible_w_ila_input - [this](const std::string& ila_name, - const SignalInfoBase& vlg_sig_info) -> bool { - return TypeMatched(IlaGetInput(ila_name), vlg_sig_info) != 0; - }, - // no need to worry about the nullptr in IlaGetInput, TypeMatched will - // be able to handle. - // Verifier_get_ila_mem_info - [this]( - const std::string& ila_mem_name) -> std::pair { - return GetMemInfo(ila_mem_name); - }); // end of function call: RegisterInterface + name_siginfo_pair.second, refstr); } } // ConstructWrapper_add_vlg_input_output @@ -321,24 +324,23 @@ void VlgSglTgtGen::ConstructWrapper_add_module_instantiation() { // ------------------------ OTERHS (refs) ----------------------------- // void VlgSglTgtGen::ConstructWrapper_register_extra_io_wire() { - for (auto&& refered_vlg_item : _all_referred_vlg_names) { + for (auto&& refered_vlg_item : refinement_map.var_replacement) { + + auto old_name = refered_vlg_item.second.get_orig_name(); + auto new_name = refered_vlg_item.second.get_new_name(); - auto idx = refered_vlg_item.first.find("["); - auto removed_range_name = refered_vlg_item.first.substr(0, idx); + auto idx = old_name.find("["); + auto removed_range_name = old_name.substr(0, idx); auto vlg_sig_info = vlg_info_ptr->get_signal(removed_range_name, - supplementary_info.width_info); + refinement_map.width_info); - auto vname = ReplaceAll( - ReplaceAll(ReplaceAll(refered_vlg_item.first, ".", "__DOT__"), "[", - "_"), - "]", "_"); // + ReplaceAll(ReplaceAll(refered_vlg_item.second.range, "[","_"),"]","_"); // // name for verilog auto width = vlg_sig_info.get_width(); - vlg_wrapper.add_wire(vname, width, 1); // keep - vlg_wrapper.add_output(vname, width); // add as output of the wrapper - _idr.RegisterExtraWire(vname, vname); + vlg_wrapper.add_wire(new_name, width, 1); // keep + vlg_wrapper.add_output(new_name, width); // add as output of the wrapper + _idr.RegisterExtraWire(new_name, new_name); // these will be connected to the verilog module, so register as extra wires // so, later they will be connected } diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index fd0f78341..1dd6e7b10 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -30,105 +30,60 @@ bool VlgSglTgtGen::bad_state_return(void) { return _bad_state; } // bad_state_return -void VlgSglTgtGen::ConstructWrapper_add_additional_mapping_control() { - if (IN("mapping control", rf_vmap)) { - if (!rf_vmap["mapping control"].is_array()) - ILA_ERROR << "mapping control field must be an array of string"; - for (auto&& c : rf_vmap["mapping control"]) { - if (!c.is_string()) { - ILA_ERROR << "mapping control field must be an array of string"; - continue; - } - add_an_assumption(ReplExpr(c.get()), - "additional_mapping_control_assume"); - } +void VlgSglTgtGen::RfmapIlaStateSanityCheck() { +#define ERR_IF(cond,s) do { ILA_ERROR_IF(cond) << (s); _bad_state = true; return; } while(0) + + for(unsigned sidx = 0; sidx < _host->state_num(); ++ sidx) { + const auto & s = _host->state(sidx); + const auto & n = s->name().str(); + ERR_IF(!IN(n, refinement_map.ila_state_var_map), "state `" + n + "` not in refinement map" ); } -} // ConstructWrapper_add_additional_mapping_control -void VlgSglTgtGen::ConstructWrapper_add_rf_assumptions() { - if (IN("assumptions", rf_vmap)) { - if (!rf_vmap["assumptions"].is_array()) - ILA_ERROR << "`assumptions` field must be an array of string"; - for (auto&& c : rf_vmap["assumptions"]) { - if (!c.is_string()) { - ILA_ERROR << "`assumptions` field must be an array of string"; - continue; - } - add_an_assumption(ReplExpr(c.get()), "rfassumptions"); - } + for(unsigned sidx = 0; sidx < _host->input_num(); ++ sidx) { + const auto & s = _host->input(sidx); + const auto & n = s->name().str(); + ERR_IF(!IN(n, refinement_map.ila_input_var_map), "input `" + n + "` not in refinement map" ); } -} // ConstructWrapper_add_rf_assumptions -void VlgSglTgtGen::ConstructWrapper_add_helper_memory() { - auto endCond = - has_flush ? "__ENDFLUSH__ || __FLUSHENDED__" : "__IEND__ || __ENDED__"; - - // here we insert the memory ports - for (auto&& memname_ports_pair : supplementary_info.memory_ports) { - // add wire - for (auto&& port_expr_port : memname_ports_pair.second) { - if (RemoveWhiteSpace(port_expr_port.second).empty()) - _idr.KeepMemoryPorts(memname_ports_pair.first, port_expr_port.first, - false); - // does not need to create extra wires - else { - // create wire as abs_mem_will not - auto wn = _idr.KeepMemoryPorts(memname_ports_pair.first, - port_expr_port.first, true); - vlg_wrapper.add_wire(wn.first, wn.second, true); - vlg_wrapper.add_assign_stmt(wn.first, ReplExpr(port_expr_port.second)); - } - } + for(const auto & n_map_pair : refinement_map.ila_state_var_map) { + ERR_IF(_host->find_state(n_map_pair.first) == nullptr, "state `" + n_map_pair.first + "` not defined in ILA"); + } + + for(const auto & n_map_pair : refinement_map.ila_input_var_map) { + ERR_IF(_host->find_input(n_map_pair.first) == nullptr, "input `" + n_map_pair.first + "` not defined in ILA"); } - auto stmt = _idr.GetAbsMemInstString(vlg_wrapper, endCond); +#undef ERR_IF +} + - if (!((target_type == target_type_t::INV_SYN_DESIGN_ONLY && - !_vtg_config.InvariantSynthesisKeepMemory) || - (target_type == target_type_t::INVARIANTS && - !_vtg_config.InvariantCheckKeepMemory))) - vlg_wrapper.add_stmt(stmt); +void VlgSglTgtGen::ConstructWrapper_add_additional_mapping_control() { + for(const auto & mapc : refinement_map.additional_mapping) { + add_an_assumption(ReplExpr(mapc), "additional_mapping_control_assume"); + } +} // ConstructWrapper_add_additional_mapping_control - // check if we need to insert any assumptions - auto inserter = [this](const std::string& p) -> void { - if (target_type == target_type_t::INSTRUCTIONS) - add_an_assumption(p, "absmem"); - }; - _idr.InsertAbsMemAssmpt(inserter); -} // ConstructWrapper_add_helper_memory +void VlgSglTgtGen::ConstructWrapper_add_rf_assumptions() { + for (const auto & assumpt : refinement_map.assumptions) { + add_an_assumption(ReplExpr(assumpt), "rfassumptions"); + } +} // ConstructWrapper_add_rf_assumptions void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { - if (!IN("functions", rf_vmap)) - return; // do nothing - auto& fm = rf_vmap["functions"]; - if (!fm.is_object()) { - ILA_ERROR << "expect functions field to be funcName -> list of list of " - "pair of (cond,val)."; + if (refinement_map.uf_application.empty()) return; - } // convert vlg_ila.ila_func_app to name->list of func_app std::map name_to_fnapp_vec; for (auto&& func_app : vlg_ila.ila_func_app) { - if (_vtg_config.IteUnknownAutoIgnore) { - if (func_app.args.empty() && - _sdr.isSpecialUnknownFunctionName(func_app.func_name)) - continue; - } name_to_fnapp_vec[func_app.func_name].push_back(func_app); } - for (auto&& it : fm.items()) { - const auto& funcName = it.key(); - const auto& list_of_time_of_apply = it.value(); - if (!list_of_time_of_apply.is_array()) { - ILA_ERROR << funcName - << ": expect functions field to be funcName -> list of list of " - "pair of (cond,val)."; - continue; - } - if (!IN(funcName, name_to_fnapp_vec)) { + for (const auto & uf_app : refinement_map.uf_application) { + const auto& funcName = uf_app.first; + const auto& list_of_time_of_apply = uf_app.second.func_applications; + if(!IN(funcName, name_to_fnapp_vec)) { // ILA_WARN << "uninterpreted function mapping:" << funcName // << " does not exist. Skipped."; continue; @@ -140,263 +95,201 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { << " not matched. Skipped."; continue; } - auto& ila_app_list = name_to_fnapp_vec[funcName]; - size_t idx = 0; - for (auto&& each_apply : list_of_time_of_apply.items()) { - if (!each_apply.value().is_array()) { - ILA_ERROR << funcName - << ": expecting mapping to be list of pair of (cond,val)."; - idx++; - continue; - } + for (auto&& each_apply : list_of_time_of_apply) { + auto& ila_app_item = ila_app_list[idx]; idx++; - if (each_apply.value().size() != (ila_app_item.args.size() + 1) * 2) { - ILA_ERROR << "ila func app expect: (1(retval) + " - << ila_app_item.args.size() << "(args) )*2" - << " items. Given:" << each_apply.value().size() + if (each_apply.arg_map.size() != ila_app_item.args.size()) { + ILA_ERROR << "ila func app expect: " + << ila_app_item.args.size() << " (args)." + << " Given:" << each_apply.arg_map.size() << " items, for func: " << funcName; continue; } - auto val_arg_map_str_vec = - each_apply.value().get>(); + const auto & arg_apply = each_apply.arg_map; + const auto & result_apply = each_apply.result_map; + std::string func_result_wire = funcName + "_" + IntToStr(idx - 1) + "_result_wire"; - std::string func_reg = funcName + "_" + IntToStr(idx - 1) + "_result_reg"; - // okay now get the chance - auto val_cond = ReplExpr(val_arg_map_str_vec[0]); - auto val_map = ReplExpr(val_arg_map_str_vec[1], - true); // force vlg name on the mapping - auto res_map = "~(" + val_cond + ")||(" + func_reg + "==" + val_map + ")"; + auto res_map = "~( __START__ )||(" + func_result_wire + "==" + ReplExpr(result_apply) + ")"; std::string prep = VLG_TRUE; - for (size_t arg_idx = 2; arg_idx < val_arg_map_str_vec.size(); - arg_idx += 2) { - const auto& cond = ReplExpr(val_arg_map_str_vec[arg_idx]); - const auto& map = ReplExpr(val_arg_map_str_vec[arg_idx + 1], true); + size_t arg_idx = 0; + for (const auto & each_arg : arg_apply) { std::string func_arg = funcName + "_" + IntToStr(idx - 1) + "_arg" + - IntToStr(arg_idx / 2 - 1) + "_reg"; + IntToStr(arg_idx++) + "_wire"; - prep += "&&(~(" + cond + ")||((" + func_arg + ") == (" + map + ")))"; + prep += "&&(~( __START__ )||((" + func_arg + ") == (" + ReplExpr(each_arg) + ")))"; } - + // ( + // (decode |-> arg0_output == ??@?? ) && (decode |-> arg1_output == ??@?? ) + // && ... + // ) |-> ( + // (decode |-> result_input == ??@??) + // ) add_an_assumption("~(" + prep + ") || (" + res_map + ")", "funcmap"); } // for each apply in the list of apply - name_to_fnapp_vec.erase(funcName); // remove from it + name_to_fnapp_vec.erase(funcName); // remove from it } + // check for unmapped func for (auto&& nf : name_to_fnapp_vec) ILA_ERROR << "lacking function map for func:" << nf.first; } // ConstructWrapper_add_uf_constraints -int VlgSglTgtGen::ConstructWrapper_add_post_value_holder_handle_obj( - nlohmann::json& pv_cond_val, const std::string& pv_name, int width, - bool create_reg) { - - std::string cond = VLG_TRUE; - std::string val = "'hx"; - std::string original_val_field; - - for (auto&& cond_val_pair : pv_cond_val.items()) { - if (cond_val_pair.key() == "cond") - cond = ReplExpr(cond_val_pair.value(), true); - else if (cond_val_pair.key() == "val") { - original_val_field = cond_val_pair.value(); - StrTrim(original_val_field); - val = ReplExpr(original_val_field, true); - } else if (cond_val_pair.key() == "width") { - if (cond_val_pair.value().is_string()) { - ILA_CHECK(cond_val_pair.value().get() == "auto") - << "Expecting width to be unsigned int / auto"; - ILA_CHECK(!original_val_field.empty()) - << "You must first provide `val` field before auto"; - if (original_val_field.find("[") != original_val_field.npos) - original_val_field = - original_val_field.substr(0, original_val_field.find("[")); - if (S_IN("=", original_val_field)) { - ILA_WARN << "Creating value-holder for conditions"; - width = 1; - } else if (vlg_info_ptr->check_hierarchical_name_type( - original_val_field) != - VerilogInfo::hierarchical_name_type::NONE) { - auto vlg_sig_info = vlg_info_ptr->get_signal( - original_val_field, supplementary_info.width_info); - width = vlg_sig_info.get_width(); - } else if (vlg_info_ptr->check_hierarchical_name_type( - _vlg_mod_inst_name + "." + original_val_field) != - VerilogInfo::hierarchical_name_type::NONE) { - auto vlg_sig_info = vlg_info_ptr->get_signal( - _vlg_mod_inst_name + "." + original_val_field, - supplementary_info.width_info); - width = vlg_sig_info.get_width(); - } else { - ILA_ERROR << "Cannot auto-determine value-holder width for val:" - << original_val_field; - width = 0; - } - } else - width = cond_val_pair.value().get(); - } else - ILA_ERROR << "Unexpected key: " << cond_val_pair.key() - << " in post-value-holder, expecting 0-2 or cond/val/width"; - } - ILA_WARN_IF(val == "'hx") << "val field is not provided for " << pv_name; - ILA_WARN_IF(cond == VLG_TRUE) << "cond field is not provided for " << pv_name; - ILA_ERROR_IF(width <= 0 && create_reg) - << "Cannot create signal for " << pv_name << " : unknown width!"; - if (width >= 0 && create_reg) { // error - // ILA_ERROR << "width of post-value-holder `" << pv_name << "` is - // unknown!"; - vlg_wrapper.add_reg(pv_name, width); - } - add_reg_cassign_assumption(pv_name, val, width, cond, "post_value_holder"); - return width; -} +void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { + for(const auto & delay_unit : refinement_map.aux_delays) { + const auto & name = delay_unit.first; + const auto & du = delay_unit.second; + + ILA_ERROR_IF(du.num_cycle == 0) << "Cannot delay 0 cycle"; + std::string last_reg; + for(size_t didx = 1; didx <= du.num_cycle; ++ didx) { + auto curr_name = name+"_d_"+std::to_string(didx); + auto prev_name = name+"_d_"+std::to_string(didx-1); + vlg_wrapper.add_reg(curr_name, delay_unit.second.width); + if(didx == 1) { + // delay from signal + auto rhs = ReplExpr(du.signal); + if (du.delay_type != rfmap::SignalDelay::delay_typeT::SINGLE && du.width > 1) + rhs = "|(" + rhs + ")"; + vlg_wrapper.add_always_stmt(curr_name + " <= " + rhs); + } else { + vlg_wrapper.add_always_stmt(curr_name + " <= " + prev_name + " ;"); + } + if(didx == du.num_cycle) + last_reg = curr_name; + } // end - for each delay + if(du.delay_type == rfmap::SignalDelay::delay_typeT::SINGLE) { + vlg_wrapper.add_wire(name, du.width); + vlg_wrapper.add_assign_stmt(name, last_reg); + continue; + } // else + if(du.delay_type == rfmap::SignalDelay::delay_typeT::TO_INFINITE) { + auto summary_var = name+"_inf_"; + vlg_wrapper.add_reg(summary_var, 1); + vlg_wrapper.add_init_stmt(summary_var + "<= 1'b0;"); + vlg_wrapper.add_always_stmt("if( " + last_reg + ") " + summary_var + " <= 1'b1;"); + vlg_wrapper.add_wire(name, 1); + vlg_wrapper.add_assign_stmt(name, summary_var + " || " + last_reg); + continue; + } + // finally the range + // if (du.delay_type == rfmap::SignalDelay::delay_typeT::RANGE) + ILA_ERROR_IF(du.upper_bnd <= du.num_cycle) << "in `##[l:u]`, we need `l < u` "; + std::string or_reduce = last_reg; + for(size_t didx = du.num_cycle+1; didx <= du.upper_bnd; ++ didx) { + auto curr_name = name+"_d_"+std::to_string(didx); + auto prev_name = name+"_d_"+std::to_string(didx-1); + vlg_wrapper.add_reg(curr_name, 1); + vlg_wrapper.add_always_stmt(curr_name + " <= " + prev_name + " ;"); + + or_reduce += " || " + curr_name; + } + vlg_wrapper.add_wire(name, 1); + vlg_wrapper.add_assign_stmt(name, or_reduce); + } // end for each delay unit +} // end ConstructWrapper_add_delay_unit + +void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { + for(const auto & n_tracker : refinement_map.phase_tracker) { + const auto & name = n_tracker.first; + const auto & tracker = n_tracker.second; + for (const auto & vardef : tracker.var_defs) { + const auto & vn = vardef.first; + if ( vardef.second.type == rfmap::GeneralVerilogMonitor::VarDef::var_type::REG ) + vlg_wrapper.add_reg(vn, vardef.second.width); + else + vlg_wrapper.add_wire(vn, vardef.second.width); + } + for ( const auto & event_alias : tracker.event_alias) { + vlg_wrapper.add_wire( event_alias.first, 1); + vlg_wrapper.add_assign_stmt(event_alias.first, ReplExpr(event_alias.second)); + } + unsigned sidx = 0; + for (const auto & stage : tracker.rules) { + std::string stage_name = stage.stage_name.empty() ? "stage" + std::to_string(sidx) : stage.stage_name; + vlg_wrapper.add_reg(stage_name , 1); + + vlg_wrapper.add_always_stmt("if(" + ReplExpr(stage.enter_rule) + ") begin " + stage_name + " <= 1'b1;" ); + for(const auto & action : stage.enter_action) + vlg_wrapper.add_always_stmt(action.LHS + " <= " + ReplExpr(action.RHS)); + vlg_wrapper.add_always_stmt("end"); + vlg_wrapper.add_always_stmt("else if(" + ReplExpr(stage.exit_rule) + ") begin " + stage_name + " <= 1'b0;"); + for(const auto & action : stage.exit_action) + vlg_wrapper.add_always_stmt(action.LHS + " <= " + ReplExpr(action.RHS)); + vlg_wrapper.add_always_stmt("end"); + + sidx ++; + } // for each stage + } // for each tracker +} // ConstructWrapper_add_stage_tracker void VlgSglTgtGen::ConstructWrapper_add_post_value_holder() { - if (!IN("post-value-holder", rf_vmap) && !IN("value-holder", rf_vmap)) - return; // no need for it - ILA_WARN_IF(IN("post-value-holder", rf_vmap)) - << "The name `post-value-holder` will be deprecated in the future, " - << "please use `value-holder` instead"; - auto& post_val_rec = IN("value-holder", rf_vmap) - ? rf_vmap["value-holder"] - : rf_vmap["post-value-holder"]; - if (!post_val_rec.is_object()) { - ILA_ERROR << "Expect (post-)value-holder to be map-type"; - return; + for(const auto & post_val_holder : refinement_map.value_recorder) { + const auto & pv_name = post_val_holder.first; + vlg_wrapper.add_reg(pv_name, post_val_holder.second.width); + add_reg_cassign_assumption(pv_name, + ReplExpr(post_val_holder.second.value), + post_val_holder.second.width, + ReplExpr(post_val_holder.second.condition), + "post_value_holder"); } - for (auto&& item : post_val_rec.items()) { - const auto& pv_name = item.key(); - auto& pv_cond_val = item.value(); - ILA_ERROR_IF(!(pv_cond_val.is_array() || pv_cond_val.is_object())) - << "Expecting (post-)value-holder's content to be list or map type"; - if (pv_cond_val.is_array() && - (!pv_cond_val.empty() && - (pv_cond_val.begin()->is_array() || - pv_cond_val.begin()->is_object()))) { // multiple condition - int w = 0; - bool first = true; - for (auto ptr = pv_cond_val.begin(); ptr != pv_cond_val.end(); ++ptr) { - w = ConstructWrapper_add_post_value_holder_handle_obj(*ptr, pv_name, w, - first); - first = false; - } - } else { // it is just a single line - ConstructWrapper_add_post_value_holder_handle_obj(pv_cond_val, pv_name, 0, - true); - } - } // for item } // ConstructWrapper_add_post_value_holder void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { - if (!IN("verilog-inline-monitors", rf_vmap)) - return; // no need for it - - auto& monitor_rec = rf_vmap["verilog-inline-monitors"]; - if (!monitor_rec.is_object()) { - ILA_ERROR << "Expect verilog-inline-monitors to be map-type"; + if(refinement_map.customized_monitor.empty()) return; - } + + const auto& monitor_rec = refinement_map.customized_monitor; + + for (auto&& m_rec : monitor_rec) { + const auto& mname = m_rec.first; // actually no use + const auto& mdef = m_rec.second; // generalMonitor - for (auto&& m_rec : monitor_rec.items()) { - const auto& mname = m_rec.key(); // actually no use - auto& mdef = m_rec.value(); - ILA_ERROR_IF(!(mdef.is_object())) - << "Expect verilog-inline-monitors's element to be map type"; std::string vlg_expr; std::vector repl_list; - bool keep_for_non_instruction_target = false; - if (IN("keep-for-invariants", mdef) && - mdef["keep-for-invariants"].get()) - keep_for_non_instruction_target = true; + bool keep_for_non_instruction_target = mdef.keep_for_invariant; + if (target_type != target_type_t::INSTRUCTIONS && !keep_for_non_instruction_target) continue; - for (auto&& vlg_inp_pair : mdef.items()) { - if (vlg_inp_pair.key() == "verilog") { - auto& vlg_field = vlg_inp_pair.value(); - if (vlg_field.is_string()) { - vlg_expr = vlg_field.get(); - } else if (vlg_field.is_array() or vlg_field.is_object()) { - for (auto&& line : vlg_field.items()) { - if (!line.value().is_string()) { - ILA_ERROR << "Expecting string/list-of-string in `verilog` field " - "of `verilog-inline-monitors`"; - continue; - } - vlg_expr += line.value().get() + "\n"; - } - } else - ILA_ERROR << "Expecting string/list-of-string in `verilog` field of " - "`verilog-inline-monitors`"; - } else if (vlg_inp_pair.key() == "refs") { - auto& ref_field = vlg_inp_pair.value(); - if (ref_field.is_string()) - repl_list.push_back(vlg_inp_pair.value().get()); - else if (ref_field.is_array()) { - for (auto&& vlg_name : ref_field.items()) { - if (!vlg_name.value().is_string()) { - ILA_ERROR << "Expecting string/list-of-string in `refs` field of " - "`verilog-inline-monitors`"; - continue; - } - repl_list.push_back(vlg_name.value().get()); - } - } else - ILA_ERROR << "Expecting string/list-of-string in `refs` field of " - "`verilog-inline-monitors`"; - } else if (vlg_inp_pair.key() == "defs") { - if (vlg_inp_pair.value().is_array()) { - auto& defs = vlg_inp_pair.value(); - for (auto&& def : defs.items()) { - std::string defname; - int width = 0; - std::string type; - - for (auto&& nwt : def.value().items()) { - // name , width , type - if (nwt.key() == "0" || nwt.key() == "name") { - defname = nwt.value().get(); - } else if (nwt.key() == "1" || nwt.key() == "width") { - width = nwt.value().get(); - } else if (nwt.key() == "2" || nwt.key() == "type") { - type = nwt.value().get(); - } else - ILA_ERROR << "Expecting key in [0,2] or [name,width,type]"; - } - - if (defname.empty() || width == 0 || - (type != "reg" && type != "wire")) - ILA_ERROR << "Cannot create monitor for " << mname; - else { - if (type == "reg") - vlg_wrapper.add_reg(defname, width); - else - vlg_wrapper.add_wire(defname, width, true); - } - } // for each def in the array - } else - ILA_ERROR << "Expecting list-of-map in `defs` field of " - "`verilog-inline-monitors`"; - } else if (vlg_inp_pair.key() == "keep-for-invariants") { - ILA_ASSERT(vlg_inp_pair.value().get() == - keep_for_non_instruction_target); - } else - ILA_ERROR << "Unexpected key: " << vlg_inp_pair.key() - << " in verilog-inline-monitors, expecting " - "verilog/refs/defs/keep-for-invariants"; - } // for vlg_inp_pair - for (const auto& w : repl_list) { - const std::string repl = ReplExpr(w, true); - vlg_expr = ReplaceAll(vlg_expr, w, repl); + + for (const auto & n_def : mdef.var_defs) { + if(n_def.second.type == rfmap::GeneralVerilogMonitor::VarDef::var_type::REG) + vlg_wrapper.add_reg(n_def.first, n_def.second.width); + else + vlg_wrapper.add_wire(n_def.first, n_def.second.width); + } + + std::vector> replace_list; + for (const auto & vref : mdef.var_uses) { + auto vref_node = ::verilog_expr::VExprAst::MakeVar(vref); + auto new_name = ReplExpr(vref_node); + replace_list.push_back(std::make_pair(vref, new_name)); } - vlg_wrapper.add_stmt(vlg_expr); + + auto vlog_inline = mdef.verilog_inline; + for (const auto & old_new_pair : replace_list) { + vlog_inline = ReplaceAll(vlog_inline, old_new_pair.first, old_new_pair.second); + } + vlg_wrapper.add_stmt(vlog_inline); + } // for monitor_rec.items() } // ConstructWrapper_add_vlg_monitor + +const rfmap::InstructionCompleteCondition & VlgSglTgtGen::get_current_instruction_rf() { + ILA_NOT_NULL(_instr_ptr); + const auto & inst_name = _instr_ptr->name().c_str(); + auto pos = refinement_map.inst_complete_cond.find(inst_name); + ILA_ERROR_IF(pos == refinement_map.inst_complete_cond.end()) + << "Cannot find the completion condition for " << inst_name; + return pos->second; +} // get_current_instruction_rf + } // namespace ilang diff --git a/src/vtarget-out/supplementary_info.cc b/src/vtarget-out/supplementary_info.cc deleted file mode 100644 index 55f347838..000000000 --- a/src/vtarget-out/supplementary_info.cc +++ /dev/null @@ -1,103 +0,0 @@ -/// \file Source for Verilog Verification Supplementary Information -/// this is useful to provide our tool information that it cannot -/// or may not be able to figure out itself - -#include -#include -#include -#include - -namespace ilang { - -VlgTgtSupplementaryInfo::VlgTgtSupplementaryInfo() {} - -void VlgTgtSupplementaryInfo::FromJson(nlohmann::json& vmap) { - if (!IN("annotation", vmap)) - return; - const auto& supplementary_info = vmap["annotation"]; - if (!supplementary_info.is_object()) { - ILA_ERROR << "Unable to parse `annotation` field, expect a map."; - return; - } - if (IN("width", supplementary_info) && - supplementary_info["width"].is_object()) { - for (auto&& nw : supplementary_info["width"].items()) { - width_info.insert(std::make_pair(nw.key(), nw.value().get())); - } - } - - if (IN("memory-ports", supplementary_info) && - supplementary_info["memory-ports"].is_object()) { - std::set ports = {"ren", "wen", "raddr", - "waddr", "rdata", "wdata"}; - for (auto&& p : supplementary_info["memory-ports"].items()) { - std::string port = p.key(); - auto pos = port.find('.'); - - ILA_ERROR_IF(pos == port.npos) - << "memory-ports should follow NAME.PORT format"; - if (pos == port.npos) - continue; - - if (!p.value().is_string()) { - ILA_ERROR << "memory-ports's must be string->string map"; - continue; - } - - auto port_expr = p.value().get(); - auto mem_name = port.substr(0, pos); - auto port_name = port.substr(pos + 1); - if (!IN(port_name, ports)) { - ILA_ERROR << "port name : " << port_name - << " should be one of ren/wen/raddr/waddr/rdata/wdata"; - continue; - } - memory_ports[mem_name].insert(std::make_pair(port_name, port_expr)); - } - } - - if (IN("memory", supplementary_info) && - supplementary_info["memory"].is_object()) { - for (auto&& nw : supplementary_info["memory"].items()) { - std::string memory_export_directive = nw.value().get(); - memory_export_type directive = memory_export_type_external; - if (memory_export_directive == "internal") - directive = memory_export_type_internal; - else if (memory_export_directive == "external") - directive = memory_export_type_external; - else - ILA_ERROR << "Unsupported memory export directive:" - << memory_export_directive << ", expect internal/external"; - memory_export.insert(std::make_pair(nw.key(), directive)); - } - } - - // reset sequence annotation - if (IN("reset", supplementary_info) && - supplementary_info["reset"].is_object()) { - if (IN("cycle", supplementary_info["reset"])) { - if (supplementary_info["reset"]["cycle"].is_number_unsigned()) { - unsigned cycle = supplementary_info["reset"]["cycle"].get(); - ILA_ERROR_IF(cycle == 0) << "reset cycle must >= 1"; - cosa_yosys_reset_config.reset_cycles = cycle; - } else - ILA_ERROR - << "`cycle` field in `reset` annotation must be unsigned integer"; - } - if (IN("no-reset-after", supplementary_info["reset"])) { - if (supplementary_info["reset"]["no-reset-after"].is_boolean()) { - cosa_yosys_reset_config.no_reset_after_starting_state = - supplementary_info["reset"]["no-reset-after"].get(); - } else - ILA_ERROR - << "`no-reset-after` field in `reset` annotation must be boolean"; - } - ILA_ERROR_IF(IN("reset-state", supplementary_info["reset"])) - << "reset-state is not implemented yet."; - ILA_ERROR_IF(IN("reset-sequence", supplementary_info["reset"])) - << "reset-sequence is not implemented yet."; - } - -} // VlgTgtSupplementaryInfo - -}; // namespace ilang diff --git a/src/vtarget-out/var_extract.cc b/src/vtarget-out/var_extract.cc deleted file mode 100644 index 2efaaaebb..000000000 --- a/src/vtarget-out/var_extract.cc +++ /dev/null @@ -1,196 +0,0 @@ -/// \file Source of variable extractor -/// This is use to extract variable from expression (string) -/// See whether it is ila-state(I/O) / vlg-state and ... -/// and change their name if needed and generate a string -// --- Hongce Zhang - -#include - -#include - -#include -#include - -namespace ilang { - -VarExtractor::VarExtractor(str_j is_ila_state, str_j is_ila_input, - str_j is_vlg_sig) - : _is_ila_state(is_ila_state), _is_ila_input(is_ila_input), - _is_vlg_sig(is_vlg_sig) {} - -// mi == ila_inst_name / vlg_inst_name -bool VarExtractor::contains_mod_inst_name(const std::string& s, - const std::string& mi) { - ILA_ERROR_IF(mi == "") - << "Implementation bug: set the module instances name first"; - return Split(s, ".").front() == mi; -} - -std::string VarExtractor::GenString() const { - std::string ret; - for (auto&& t_s_pair : _tokens) - ret += t_s_pair.second; - return ret; -} - -bool isStateBegin(unsigned char c) { - return std::isalpha(c) || c == '#' || c == '_' || c == '$' ; -} - -bool isStateCont(unsigned char c, size_t idx, const std::string& s) { - if (std::isalpha(c) || std::isdigit(c) || c == '.' || c == '_' || c == ']' || c == '$') - return true; - if (!s.empty() && s.front() == '#' && c == '#') - return true; - else if (c == '[') { - auto rp = s.find(']', idx); - auto rc = s.find(':', idx); - if (rc < rp) - return false; - // s[a:b], for this type, we make sure the whole of s is connected - // basically, it assumes that the rf will not refer to multiple elements - // but actually we need to check - return true; - // we are not sure of it actually - } - return false; -} - -bool isNumBegin(unsigned char c) { return isdigit(c) || c == '\''; } - -bool isNumCont(unsigned char c) { - return isdigit(c) || isalpha(c) || c == '\''; -} - -// [A-Za-z_][A-Za-z0-9\.]+ ==> state -// ['0-9][A-Za-z0-9']+ ==> num -void VarExtractor::ParseToExtract(const std::string& in, - bool force_vlg_statename) { - _tokens.clear(); - if (in.empty()) { - ILA_ERROR << "Parsing an empty refinement string!"; - return; - } - - auto l = in.length(); - - bool is_num = isNumBegin(in.at(0)); - bool is_state = isStateBegin(in.at(0)); - ILA_CHECK(!(is_num && is_state)) << "Implementation bug"; - - size_t left = 0; - size_t idx = 1; - - for (; idx < l; ++idx) { - bool is_num_new = - (is_num && isNumCont(in.at(idx))) || isNumBegin(in.at(idx)); - bool is_state_new = (is_state && isStateCont(in.at(idx), idx, in)) || - isStateBegin(in.at(idx)); - - if (is_num && is_state) { - ILA_CHECK(false) << "This should not be possible"; - } else if (is_num && !is_state) { // in the num matching - if (!is_num_new) { // leave matching - is_num = false; - _tokens.push_back({token_type::NUM, in.substr(left, idx - left)}); - left = idx; - if (is_state_new) - is_state = true; - } - } else if (is_state && !is_num) { // in the state matching - if (!is_state_new) { // leave matching - is_state = false; - auto subs = in.substr(left, idx - left); - token_type tp; - if (!subs.empty() && subs.front() == '#' && - subs.find('#', 1) != subs.npos) { - _tokens.push_back({KEEP, ReplaceAll(subs, "#", "")}); - left = idx; - if (is_num_new) - is_num = true; - } // if # # [2:3] .. like this , will not convert at all - else { // else normal ones - // deal with [] - auto left_p = subs.find('['); - auto check_s = - subs.substr(0, left_p); // the string use to check no [] - - if (_is_ila_state(check_s) && !force_vlg_statename) - tp = ILA_S; - else if (_is_ila_input(check_s) && !force_vlg_statename) - tp = ILA_IN; - else if (_is_vlg_sig(check_s)) - tp = VLG_S; - else - tp = UNKN_S; - _tokens.push_back({tp, subs}); - left = idx; - if (is_num_new) - is_num = true; - } // when no ## - } - } else if (!is_state && !is_num) { // not in the matching - // see if we need to start matching - ILA_CHECK(!(is_num_new && is_state_new)) - << "This should not be possible"; - if (is_num_new || is_state_new) { - _tokens.push_back({token_type::KEEP, in.substr(left, idx - left)}); - left = idx; - } - if (is_num_new) { - // copy [left, idx (not including) ] to KEEP - is_num = true; - is_state = false; - } else if (is_state_new) { - // copy [left, idx (not including) ] to KEEP - is_num = false; - is_state = true; - } - - } else - ILA_CHECK(false) << "Implementation bug, should not be reachable!"; - } - ILA_CHECK(!(is_num && is_state)) << "Implementation bug"; - // copy the last if necessary - if (left < idx) { - auto subs = in.substr(left, idx - left); - if (is_num) - _tokens.push_back({token_type::NUM, subs}); - else if (is_state) { - if (!subs.empty() && subs.front() == '#' && - subs.find('#', 1) != subs.npos) - _tokens.push_back({KEEP, ReplaceAll(subs, "#", "")}); - else { - token_type tp; - auto left_p = subs.find('['); - auto check_s = subs.substr(0, left_p); // the string use to check no [] - if (_is_ila_state(check_s) && !force_vlg_statename) - tp = ILA_S; - else if (_is_ila_input(check_s) && !force_vlg_statename) - tp = ILA_IN; - else if (_is_vlg_sig(check_s)) - tp = VLG_S; - else - tp = UNKN_S; - _tokens.push_back({tp, subs}); - } // no # - } else { - _tokens.push_back({token_type::KEEP, subs}); - } - } -} - -void VarExtractor::ForEachTokenReplace(str_r replacer) { - size_t idx = -1; - for (auto&& p : _tokens) { - idx++; - auto rep = replacer(p); - if (rep == p.second) - continue; - _tokens[idx] = std::make_pair(p.first, rep); - } -} - -// Find the strings like this : - -}; // namespace ilang diff --git a/src/vtarget-out/vlg_mod.cc b/src/vtarget-out/vlg_mod.cc index 0dc1bedc6..df3471ab9 100644 --- a/src/vtarget-out/vlg_mod.cc +++ b/src/vtarget-out/vlg_mod.cc @@ -289,7 +289,7 @@ VerilogModifier::RecordConnectSigName(const std::string& vlg_sig_name, auto vname = ReplaceAll(vlg_sig_name, ".", "__DOT__") + - ReplaceAll(ReplaceAll(suffix, "[", "_"), "]", "_"); // name for verilog + "_"+ ReplaceAll(suffix,"'","") +"_"; // name for verilog auto mod_hier_name = Split(vlg_sig_name, "."); auto hier = mod_hier_name.size(); auto last_level_name = mod_hier_name[hier - 1]; @@ -326,7 +326,7 @@ VerilogModifier::RecordConnectSigName(const std::string& vlg_sig_name, loc = vlg_info_ptr->get_endmodule_loc(inst_name); // this the endmodule location assign_map[loc.first].push_back( - assign_item_t(loc.second, vname, width, short_name + suffix)); + assign_item_t(loc.second, vname, width, short_name + "["+ suffix+"]")); return vlg_sig_t({vname, width}); } // RecordConnectSigName diff --git a/src/vtarget-out/vtarget_gen_cosa.cc b/src/vtarget-out/vtarget_gen_cosa.cc index ee116d963..9134400f2 100644 --- a/src/vtarget-out/vtarget_gen_cosa.cc +++ b/src/vtarget-out/vtarget_gen_cosa.cc @@ -250,7 +250,7 @@ void VlgSglTgtGen_Cosa::Export_modify_verilog() { VerilogModifier vlg_mod(vlg_info_ptr, static_cast( _vtg_config.PortDeclStyle), - _vtg_config.CosaAddKeep, + _vtg_config.PonoAddKeep, supplementary_info.width_info); for (auto&& refered_vlg_item : _all_referred_vlg_names) { diff --git a/src/vtarget-out/vtarget_gen_relchc.cc b/src/vtarget-out/vtarget_gen_relchc.cc index 1e41df9ca..5a0e20f70 100644 --- a/src/vtarget-out/vtarget_gen_relchc.cc +++ b/src/vtarget-out/vtarget_gen_relchc.cc @@ -214,7 +214,7 @@ void VlgSglTgtGen_Relchc::Export_modify_verilog() { VerilogModifier vlg_mod(vlg_info_ptr, static_cast( _vtg_config.PortDeclStyle), - _vtg_config.CosaAddKeep, + _vtg_config.PonoAddKeep, supplementary_info.width_info); // add mod stmt (wire something ... like that) diff --git a/src/vtarget-out/vtarget_gen_yosys.cc b/src/vtarget-out/vtarget_gen_yosys.cc index 0426fce00..fc2d5ec6c 100644 --- a/src/vtarget-out/vtarget_gen_yosys.cc +++ b/src/vtarget-out/vtarget_gen_yosys.cc @@ -406,16 +406,17 @@ void VlgSglTgtGen_Yosys::Export_modify_verilog() { VerilogModifier vlg_mod(vlg_info_ptr, static_cast( _vtg_config.PortDeclStyle), - _vtg_config.CosaAddKeep, + _vtg_config.PonoAddKeep, supplementary_info.width_info); - for (auto&& refered_vlg_item : _all_referred_vlg_names) { - auto idx = refered_vlg_item.first.find("["); - auto removed_range_name = refered_vlg_item.first.substr(0, idx); + for (auto&& refered_vlg_item : refinement_map.var_replacement) { + auto old_name = refered_vlg_item.second.get_orig_name(); + auto idx = old_name.find("["); + auto removed_range_name = old_name.substr(0, idx); vlg_mod.RecordKeepSignalName(removed_range_name); // auto sig = // no use, this is too late, vlg_wrapper already exported vlg_mod.RecordConnectSigName(removed_range_name, - refered_vlg_item.second.range); + refered_vlg_item.second.range_o); // vlg_wrapper.add_output(sig.first, sig.second); } vlg_mod.FinishRecording(); From 61fe609a04f7b9b386acb9a0ad008ed692ae07f2 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 21 Jun 2021 16:58:36 -0400 Subject: [PATCH 19/78] update vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 882a86bff..10d544861 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 882a86bffae53166f03adb00f808d89b948b9491 +Subproject commit 10d544861341a9cf9f26f0d71fe1d87f6d651430 From 1f2838362f428bf11c09d94b1926add31312de6b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 21 Jun 2021 17:26:50 -0400 Subject: [PATCH 20/78] rfexpr2smt --- include/ilang/rfmap-in/rfexpr_to_smt.h | 30 ++ include/ilang/rfmap-in/rfmap_typecheck.h | 13 + include/ilang/rfmap-in/verilog_rfmap.h | 2 + include/ilang/vtarget-out/vtarget_gen_impl.h | 23 +- src/rfmap-in/CMakeLists.txt | 1 + src/rfmap-in/rfexpr_to_smt.cc | 353 +++++++++++++++++++ src/rfmap-in/rfmap_typecheck.cc | 227 +++++++++++- src/rfmap-in/verilog_rfmap.cc | 16 +- src/vtarget-out/gen_util.cc | 86 +++++ src/vtarget-out/single_target.cc | 36 +- src/vtarget-out/single_target_connect.cc | 2 + src/vtarget-out/vtarget_gen_impl.cc | 83 ----- src/vtarget-out/vtarget_gen_relchc.cc | 1 - src/vtarget-out/vtarget_gen_yosys.cc | 8 +- 14 files changed, 739 insertions(+), 142 deletions(-) create mode 100644 include/ilang/rfmap-in/rfexpr_to_smt.h create mode 100644 src/rfmap-in/rfexpr_to_smt.cc diff --git a/include/ilang/rfmap-in/rfexpr_to_smt.h b/include/ilang/rfmap-in/rfexpr_to_smt.h new file mode 100644 index 000000000..38503eb02 --- /dev/null +++ b/include/ilang/rfmap-in/rfexpr_to_smt.h @@ -0,0 +1,30 @@ +/// \file rfexpr_to_smt.cc Refinement map to smt-lib2 +/// Hongce Zhang (hongcez@princeton.edu) + + +#ifndef ILANG_RFEXPR_TO_SMT_H__ +#define ILANG_RFEXPR_TO_SMT_H__ + +#include + +namespace ilang { +namespace rfmap { + +struct RfExpr2Smt{ + +public: + static std::string to_smt2(const RfExpr &in, bool request_bool); + +protected: + // helper function + static std::string to_smt2_const(const std::shared_ptr & in, bool request_bool); + static std::string to_smt2_var(const std::shared_ptr & in, bool request_bool); + +}; // struct RfExpr2Smt + + +} // namespace rfmap +} // namespace ilang + + +#endif // ILANG_RFEXPR_TO_SMT_H__ diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index 1785f5bcd..58f539dbc 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -32,6 +32,8 @@ class TypeAnnotation : ::ilang::rfmap::RfVarTypeOrig(r) {} }; // TypeAnnotation + +/// \class structure for recording variable replacement struct VarReplacement { RfExpr origvar; // this is certainly a var RfExpr newvar; // this is certainly a var @@ -92,6 +94,8 @@ struct VarReplacement { } }; +// convert RfExpr constant -> out +bool _compute_const(const RfExpr & in, unsigned & out); // type infer rules // @@ -141,10 +145,15 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { // ... ? void TraverseAllRfExpr(std::function func); + /// used by vtarget_gen to replace rtl/ila vars RfExpr ReplacingRtlIlaVar(const RfExpr & in, bool replace_dot); + /// the replacement used for creating new wires std::map var_replacement; // including rtl/ilas/ilav + /// determine if a rf expr is a boolean expr + static bool IsLastLevelBooleanOp(const RfExpr & in); + protected: void initialize(); @@ -154,6 +163,10 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { void TraverseCondMap(SingleVarMap & inout, std::function func) ; var_typecheck_t typechecker; + + // internal use only, does not do recursion itself + // therefore, an order of invocation is needed + void infer_type_op(const RfExpr & inout) ; private: // help with naming diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 0ad63710d..1f0f9ac20 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -231,6 +231,8 @@ struct VerilogRefinementMap { VerilogRefinementMap(const std::string & varmap_json_file, const std::string & instcond_json_file); + static RfExpr ParseRfExprFromString(const std::string & in); + }; // VerilogRefinementMap } // namespace ilang diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index c600d30f7..a6606f32d 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -163,18 +163,16 @@ class VlgSglTgtGen { static unsigned get_width(const ExprPtr& n); /// Parse and modify a condition string std::string ReplExpr(const rfmap::RfExpr & in); + /// treat `in` as var map, if it is not a Boolean, add `==` + std::string TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn); /// handle a single string map (s-name/equ-string) std::string PerStateMap(const std::string& ila_state_name_or_equ, const std::string& vlg_st_name); /// handle a var map - /// will create new variables "m?" and return it - /// 1. "ila-state":"**MEM**.?" - /// 2a. "ila-state":"statename" --> PerStateMap - /// 2b. "ila-state":"(cond)&map" --> PerStateMap - /// 3. "ila-state":[ "cond&map" ] - /// 4. "ila-state":[ {"cond":,"map":}, ] - std::string GetStateVarMapExpr(const std::string& ila_state_name, - nlohmann::json& m, bool is_assert = false); + void Gen_varmap_assumpt_assert(const std::string& ila_state_name, + const rfmap::IlaVarMapping &vmap, const std::string & problem_name, bool true_for_assumpt_false_for_assert, + const std::string & prefix, const std::string & suffix); + /// add a start condition if it is given void handle_start_condition(const std::vector & dc); /// Find the current instruction-mapping @@ -444,20 +442,11 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { /// generate the runable script name const std::vector& GetRunnableScriptName() const; - /// return the result from parsing supplymentary information - const VlgTgtSupplementaryInfo& GetSupplementaryInfo() const; -protected: - // --------------------- METHODS ---------------------------- // - /// subroutine for generating synthesis using chc targets protected: /// If it is bad state, return true and display a message bool bad_state_return(void); - /// load json from a file name to the given j - void load_json(const std::string& fname, nlohmann::json& j); - /// Get instance name from rfmap - void set_module_instantiation_name(); private: /// If it is in a bad state diff --git a/src/rfmap-in/CMakeLists.txt b/src/rfmap-in/CMakeLists.txt index 6ea9bd03a..3a3f77874 100644 --- a/src/rfmap-in/CMakeLists.txt +++ b/src/rfmap-in/CMakeLists.txt @@ -4,5 +4,6 @@ target_sources(${ILANG_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/verilog_rfmap.cc ${CMAKE_CURRENT_SOURCE_DIR}/rfmap_typecheck.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rfexpr_to_smt.cc ) diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc new file mode 100644 index 000000000..bd9277d96 --- /dev/null +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -0,0 +1,353 @@ +/// \file rfexpr_to_smt.cc Refinement map to smt-lib2 +/// Hongce Zhang (hongcez@princeton.edu) + +#include +#include +#include + +#include + + +namespace ilang { +namespace rfmap { + + +static std::vector voperator_str_smt = { + "bvmul", // STAR + "bvadd", + "bvsub", + "bvshl", + "bvashr", + "bvshl", + "bvlshr", + "bvudiv", + "#notsupported", // POW ** + "bvurem", + "bvuge", + "bvule", + "bvugt", + "bvult", + "not", + "and", + "or", + "=", + "=", + "#special", + "#special", + "bvnot", + "bvand", + "bvor", + "bvxor", + "bvxnor", + "bvnand", + "bvnor", // B_NOR + "#special", // select/extract [idx] operator A[i1][i2] -> index(index(A,i1),i2) A[i1[i2]] index(A, index(i1,i2)) + "#special", // extract [i1:i2] ternary + "#special", // extract [i1:+i2] ternary + "#special", // extract [i1:-i2] ternary + "store", // store A:<3>:5:<4>:6:<5>:7 (not supported yet) + "#notsupported", // AT + "ite", // ternary + /*special ops*/ + "#special", // function app + "concat", + "#special", // REPEAT if it is const we can handle + /*Placeholder*/ + "MK_CONST", + "MK_VAR", + + "#notsupported" // delay +}; + +static RfMapVarType get_type(const RfExpr & in) { + auto tp = in->get_annotation(); + if (tp == nullptr) + return RfMapVarType(); + return tp->type; +} + +static std::string smt_const(unsigned value, unsigned width) { + auto ret = IntToStrCustomBase(value, 2, false); + if(ret.length() > width) + throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + + std::string zero; + if(width > ret.length()) + for (unsigned idx = 0; idx < width - ret.length(); ++ idx) + zero += "0"; + return "#b" + zero + ret; +} // smt_const + +static std::string split_bit(const std::string & opstr, + unsigned width, const std::string & childstr) { + if(width <= 1) + return childstr; + + std::vector child; + for(unsigned idx = 0; idx < width; ++ idx) { + auto ext = "(_ extract " + std::to_string(idx) + " " + std::to_string(idx) + ")"; + child.push_back("(" + ext + " " + childstr + ")"); + } + + std::string ret = "(" + opstr + " " + child.at(0) + " " + child.at(1)+")"; + for (unsigned idx = 2; idx < child.size(); ++ idx) + ret = "(" + opstr + " " + ret + " " + child.at(idx) +")"; + return ret; +} + +// make sure in_bool -> out_bool +static std::string bvboolconvert(bool out_bool, bool in_bool, size_t inwidth, const std::string & in) { + if(in_bool == out_bool) + return in; + if(in_bool && !out_bool) + return "(ite " + in + " #b1 #b0)"; + // else: !in_bool && out_bool + return "(not (= " + in + " "+ smt_const(0, inwidth) +"))"; +} + +std::string RfExpr2Smt::to_smt2_const(const std::shared_ptr & in, bool request_bool) { + unsigned out; + bool succ = _compute_const(in, out); + if(!succ) + throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + + auto b_w_l = in->get_constant(); + auto width = std::get<1>(b_w_l); + return bvboolconvert(request_bool, false, width, smt_const(out, width) ); + +} // to_smt2_const + +std::string RfExpr2Smt::to_smt2_var(const std::shared_ptr & in, bool request_bool) { + RfMapVarType tp = in->get_annotation()->type; + auto ret = "|" + in->get_name().first+"|"; + if(!tp.is_array()) + ret = bvboolconvert(request_bool, false, tp.unified_width(), ret); + return ret; +} // to_smt2_var + + +std::string RfExpr2Smt::to_smt2(const RfExpr &in, bool request_bool) { + if(in->is_var()) { + auto ptr = std::dynamic_pointer_cast(in); + ILA_NOT_NULL(ptr); + return to_smt2_var(ptr, request_bool); + } + if (in->is_constant()) { + auto ptr = std::dynamic_pointer_cast(in); + ILA_NOT_NULL(ptr); + return to_smt2_const(ptr, request_bool); + } + + auto op_ = in->get_op(); + const auto & child_ = in->get_child(); + + assert(op_ != verilog_expr::voperator::MK_CONST && op_ != verilog_expr::voperator::MK_CONST); + + unsigned idx = static_cast(op_); + assert(idx < voperator_str_smt.size()); + auto opstr = voperator_str_smt.at(idx); + if (opstr == "#notsupported") + throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2, opstr ); + // TODO: + + if ( child_.size() == 1 && + (op_ == verilog_expr::voperator::L_NEG)) { + + RfMapVarType tp = get_type(child_.at(0)); + return bvboolconvert(request_bool, true, tp.unified_width(), + "("+opstr + " " + to_smt2(child_.at(0), true)+")"); + } + + if ( child_.size() == 1 && + (op_ == verilog_expr::voperator::B_NEG)) { + + RfMapVarType tp = get_type(child_.at(0)); + return bvboolconvert(request_bool, false, tp.unified_width(), + "("+opstr + " " + to_smt2(child_.at(0), false)+")"); + } + + if (child_.size() == 1 && + op_ == verilog_expr::voperator::PLUS) { + + RfMapVarType tp = get_type(child_.at(0)); + return bvboolconvert(request_bool, false, tp.unified_width(), + to_smt2(child_.at(0), false)); + } + + if (child_.size() == 1 && + op_ == verilog_expr::voperator::MINUS) { + + + RfMapVarType tp = get_type(child_.at(0)); + return bvboolconvert(request_bool, false, tp.unified_width(), + "(bvsub " + smt_const(0,tp.unified_width()) + " "+to_smt2(child_.at(0), false)); + } + + if (child_.size() == 1 && + ( op_ == verilog_expr::voperator::B_AND || + op_ == verilog_expr::voperator::B_NAND || + op_ == verilog_expr::voperator::B_OR || + op_ == verilog_expr::voperator::B_NOR || + op_ == verilog_expr::voperator::B_XOR || + op_ == verilog_expr::voperator::B_EQU + )) { + + RfMapVarType tp = get_type(child_.at(0)); + + return bvboolconvert(request_bool, false, tp.unified_width(), + split_bit(opstr, tp.unified_width(), to_smt2(child_.at(0), false))); + } + + RfMapVarType parent_tp = get_type(in); + + // binary or more + switch(op_) { + case verilog_expr::voperator::STAR: // mul + case verilog_expr::voperator::PLUS: + case verilog_expr::voperator::MINUS: + case verilog_expr::voperator::ASL: + case verilog_expr::voperator::ASR: + case verilog_expr::voperator::LSL: + case verilog_expr::voperator::LSR: + case verilog_expr::voperator::DIV: + case verilog_expr::voperator::MOD: + assert(child_.size() == 2); + return bvboolconvert(request_bool, false, parent_tp.unified_width(), + "("+opstr+" " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+")" + ); + break; + + case verilog_expr::voperator::GTE: + case verilog_expr::voperator::LTE: + case verilog_expr::voperator::GT: + case verilog_expr::voperator::LT: + case verilog_expr::voperator::C_EQ: + case verilog_expr::voperator::L_EQ: + assert(child_.size() == 2); + return bvboolconvert(request_bool, true, parent_tp.unified_width(), + "("+opstr+" " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+")" + ); + + break; + + case verilog_expr::voperator::C_NEQ: + case verilog_expr::voperator::L_NEQ: + assert(child_.size() == 2); + return bvboolconvert(request_bool, true, parent_tp.unified_width(), + "(not (= " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+"))" + ); + break; + + case verilog_expr::voperator::L_AND: + case verilog_expr::voperator::L_OR: + assert(child_.size() == 2); + return bvboolconvert(request_bool, true, parent_tp.unified_width(), + "(" + opstr + " " + to_smt2(child_.at(0),true) + " " + to_smt2(child_.at(1),true)+")" + ); + break; + + case verilog_expr::voperator::B_AND: + case verilog_expr::voperator::B_OR: + case verilog_expr::voperator::B_XOR: + case verilog_expr::voperator::B_EQU: + case verilog_expr::voperator::B_NAND: + case verilog_expr::voperator::B_NOR: + assert(child_.size() == 2); + return bvboolconvert(request_bool, false, parent_tp.unified_width(), + "(" + opstr + " " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+")" + ); + break; + + + default: + break; + } // end switch + + if(op_ == verilog_expr::voperator::INDEX) { + RfMapVarType tp = get_type(child_.at(0)); + if(tp.is_array()) { + return bvboolconvert(request_bool, false, tp.unified_width(), + "(select " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false) + ")"); + } // else is bv + // request to index to be constant + unsigned bitidx; + bool succ = _compute_const(child_.at(1),bitidx); + if(!succ) + throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + auto bitidxstr = std::to_string(bitidx); + return bvboolconvert(request_bool, false,1, + "((_ extract " + bitidxstr + " " + bitidxstr+") " + to_smt2(child_.at(0),false)+")"); + } + + if(op_ == verilog_expr::voperator::IDX_PRT_SEL_PLUS || + op_ == verilog_expr::voperator::IDX_PRT_SEL_MINUS || + op_ == verilog_expr::voperator::RANGE_INDEX + ) { + + unsigned l,r; + bool succ = _compute_const(child_.at(1),l); + succ = succ && _compute_const(child_.at(2),r); + if(!succ) + throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + + if(op_ == verilog_expr::voperator::IDX_PRT_SEL_PLUS) + r = l + r - 1; + else if (op_ == verilog_expr::voperator::IDX_PRT_SEL_MINUS) + r = l - r + 1; + auto lstr = std::to_string(l); + auto rstr = std::to_string(r); + return bvboolconvert(request_bool, false,l-r+1, + "((_ extract " + lstr + " " + rstr+") " + to_smt2(child_.at(0),false)+")"); + } + + if (op_ == verilog_expr::voperator::STORE_OP) { + return "(store " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+")"; + } + + if (op_ == verilog_expr::voperator::TERNARY) { + RfMapVarType tp = get_type(child_.at(1)); + if(tp.is_array()) + return "(ite " + to_smt2(child_.at(0), true) + " " + + to_smt2(child_.at(1), false) + " " + + to_smt2(child_.at(2), false) +")"; + return bvboolconvert(request_bool, false, tp.unified_width(), + "(ite " + to_smt2(child_.at(0), true) + " " + + to_smt2(child_.at(1), false) + " " + + to_smt2(child_.at(2), false) +")"); + } + + if (op_ == verilog_expr::voperator::FUNCTION_APP) + throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2); + + if (op_ == verilog_expr::voperator::CONCAT) { + assert( in->get_child_cnt() == 2 ); + return bvboolconvert(request_bool, false, parent_tp.unified_width(), + "(concat " + to_smt2(child_.at(0), false) + " " + + to_smt2(child_.at(1), false) + ")"); + } + + if (op_ == verilog_expr::voperator::REPEAT) { + assert( in->get_child_cnt() == 2 ); + unsigned ntimes; + if(!_compute_const(in->child(0), ntimes)) + throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + assert(ntimes > 0); + std::string ret = "(concat"; + std::string c1 = to_smt2(child_.at(1), false); + for(unsigned idx = 0; idx < ntimes; ++idx) + ret += " " + c1; + ret += ")"; + return ret; + } + throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2); + + return ""; + +} // end to_smt + + + +} // namespace rfmap +} // namespace ilang + + diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 0923dd4c4..761bf76cc 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -91,16 +91,18 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( // put back the annotation? in new expr? } // end if it is unknown - bool is_array = tp.type.is_array(); - if(!replace_internal_wire || is_array) { - auto ret_copy = std::make_shared(*var_ptr); - ret_copy->set_annotation(std::make_shared(tp)); - return ret_copy; - // 1 will not do replacement - // 2 will not record that - } if(tp.var_ref_type == RfVarTypeOrig::VARTYPE::RTLV) { + + bool is_array = tp.type.is_array(); + if(!replace_internal_wire || is_array) { + auto ret_copy = std::make_shared(*var_ptr); + ret_copy->set_annotation(std::make_shared(tp)); + return ret_copy; + // 1 will not do replacement + // 2 will not record that + } + auto new_name = ReplaceAll(n.first, ".", "__DOT__"); auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); new_node->set_annotation(std::make_shared(tp)); @@ -125,6 +127,13 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( return ret_copy; // will return the annotated one anyway } // is_var else if (in->is_constant()) { + if(in->get_annotation() == nullptr) { + RfVarTypeOrig tp; + auto cptr = std::dynamic_pointer_cast(in); + ILA_NOT_NULL(cptr); + tp.type = RfMapVarType(std::get<1>(cptr->get_constant())); // base, width,... + in->set_annotation(std::make_shared(tp)); + } return in; // no annotation needed } else { // check type @@ -135,9 +144,13 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( ret_copy->get_child().at(idx), replace_internal_wire); } // for each child - if(ret_copy->child(0)->is_var() && ret_copy->get_op() == verilog_expr::voperator::INDEX) { + if(!replace_internal_wire && + ret_copy->child(0)->is_var() && + ret_copy->get_op() == verilog_expr::voperator::INDEX) { + std::shared_ptr annotate = ret_copy->child(0)->get_annotation(); + if(annotate != nullptr && annotate->type.is_array()) { assert(ret_copy->get_child_cnt() == 2); auto array_index = ret_copy->child(1); @@ -159,14 +172,16 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( new_node->set_annotation(new_annotation); var_replacement.emplace(orig_name, VarReplacement(in, new_node, range_o)); - return new_node; + return new_node; } else { ILA_CHECK(false) << "FIXME: currently does not handle dynamic index into array"; } // end if it is const } - } - return ret_copy; - } + } // special handling for array[idx] + // to determine the type of ret_copy + infer_type_op(ret_copy); + return ret_copy; // may use new_node instead in the special case + } // end of is_op assert(false); // Should not be reachable } // AnnotateSignalsAndCollectRtlVars @@ -411,6 +426,184 @@ bool _compute_const(const RfExpr & in, unsigned & out) { return true; } +bool TypedVerilogRefinementMap::IsLastLevelBooleanOp(const RfExpr & in) { + std::set boolean_op = { + verilog_expr::voperator::GTE, + verilog_expr::voperator::LTE, + verilog_expr::voperator::GT, + verilog_expr::voperator::LT, + verilog_expr::voperator::C_EQ, + verilog_expr::voperator::L_EQ, + verilog_expr::voperator::C_NEQ, + verilog_expr::voperator::L_NEQ, + verilog_expr::voperator::L_NEG, + verilog_expr::voperator::L_AND, + verilog_expr::voperator::L_OR + }; + + if(in->is_constant() || in->is_var()) + return false; + auto op = in->get_op(); + return (boolean_op.find(op) == boolean_op.end()); +} + +void TypedVerilogRefinementMap::infer_type_op(const RfExpr & inout) { + assert( + inout->get_op() != verilog_expr::voperator::MK_CONST && + inout->get_op() != verilog_expr::voperator::MK_VAR ); + + if(inout->get_op() == verilog_expr::voperator::STAR || + inout->get_op() == verilog_expr::voperator::PLUS || + inout->get_op() == verilog_expr::voperator::MINUS || + inout->get_op() == verilog_expr::voperator::DIV || + inout->get_op() == verilog_expr::voperator::POW || + inout->get_op() == verilog_expr::voperator::MOD || + inout->get_op() == verilog_expr::voperator::B_NEG || + inout->get_op() == verilog_expr::voperator::B_AND || + inout->get_op() == verilog_expr::voperator::B_OR || + inout->get_op() == verilog_expr::voperator::B_XOR || + inout->get_op() == verilog_expr::voperator::B_NAND || + inout->get_op() == verilog_expr::voperator::B_NOR + ) { + // the max of the args + unsigned nchild = inout->get_child_cnt(); + unsigned maxw = 0; + for(size_t idx = 0; idx < nchild; idx ++) { + RfMapVarType t = inout->child(idx)->get_annotation()->type; + if(t.is_bv()) + maxw = std::max(maxw, t.unified_width()); + } + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(maxw); + inout->set_annotation(new_annotation); + return; + } + + if ( + inout->get_op() == verilog_expr::voperator::ASL || + inout->get_op() == verilog_expr::voperator::ASR || + inout->get_op() == verilog_expr::voperator::LSL || + inout->get_op() == verilog_expr::voperator::LSR || + inout->get_op() == verilog_expr::voperator::AT + ) { // the left type + assert( inout->get_child_cnt() == 2); + inout->set_annotation(inout->child(0)->get_annotation()); + return; + } else if ( inout->get_op() == verilog_expr::voperator::DELAY) { + // arg 1: width of first + // arg 2: width is 1 !!! + assert(inout->get_child_cnt() == 1 || inout->get_child_cnt() == 2); + if (inout->get_child_cnt() == 2) { + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(1); + inout->set_annotation(new_annotation); + return ; + } + + // set return type to be the same as the first one + inout->set_annotation(inout->child(0)->get_annotation()); + return; + + } else if ( + inout->get_op() == verilog_expr::voperator::GTE || + inout->get_op() == verilog_expr::voperator::LTE || + inout->get_op() == verilog_expr::voperator::GT || + inout->get_op() == verilog_expr::voperator::LT || + inout->get_op() == verilog_expr::voperator::C_EQ || + inout->get_op() == verilog_expr::voperator::L_EQ || + inout->get_op() == verilog_expr::voperator::C_NEQ || + inout->get_op() == verilog_expr::voperator::L_NEQ || + inout->get_op() == verilog_expr::voperator::L_NEG || + inout->get_op() == verilog_expr::voperator::L_AND || + inout->get_op() == verilog_expr::voperator::L_OR + ) { + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(1); + inout->set_annotation(new_annotation); + return ; + } else if (inout->get_op() == verilog_expr::voperator::INDEX) { + RfMapVarType child_type = inout->child(0)->get_annotation()->type; + + auto new_annotation = std::make_shared(); + if (child_type.is_array()) + new_annotation->type = RfMapVarType(child_type.unified_width()); + // TODO: check index within ? + else + new_annotation->type = RfMapVarType(1); + inout->set_annotation(new_annotation); + return; + } else if ( + inout->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || + inout->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { + assert(inout->get_child().size() == 3); + unsigned diff = 0; + bool succ = _compute_const(inout->child(2), diff /*ref*/); + ILA_ASSERT(succ); + + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(diff); + inout->set_annotation(new_annotation); + + // TODO: check index within ? + return; + + } else if (inout->get_op() == verilog_expr::voperator::RANGE_INDEX) { + assert(inout->get_child_cnt() == 3); + unsigned l,r; + + bool succ = _compute_const(inout->child(1), l /*ref*/), + succ = succ && _compute_const(inout->child(2), r /*ref*/); + ILA_ASSERT(succ); + + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(std::max(l,r)-std::min(l,r) + 1); + inout->set_annotation(new_annotation); + + return ; + } else if (inout->get_op() == verilog_expr::voperator::STORE_OP) { + inout->set_annotation(inout->child(0)->get_annotation()); + return; + + } else if (inout->get_op() == verilog_expr::voperator::TERNARY) { + inout->set_annotation(inout->child(1)->get_annotation()); + return; + } else if (inout->get_op() == verilog_expr::voperator::FUNCTION_APP) { + ILA_ASSERT(false); + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(0); + inout->set_annotation(new_annotation); + return; + } else if(inout->get_op() == verilog_expr::voperator::CONCAT) { + unsigned nchild = inout->get_child_cnt(); + unsigned sumw = 0; + for(size_t idx = 0; idx < nchild; idx ++) { + RfMapVarType t = ( inout->child(idx)->get_annotation()->type ); + sumw += t.unified_width(); + } + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(sumw); + inout->set_annotation(new_annotation); + return; + } else if (inout->get_op() == verilog_expr::voperator::REPEAT) { + assert( inout->get_child_cnt() == 2 ); + unsigned ntimes; + if(!_compute_const(inout->child(0), ntimes)) + ILA_ASSERT(false); + auto tp = ( inout->child(1)->get_annotation()->type ); + + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(tp.unified_width()*ntimes); + inout->set_annotation(new_annotation); + + return ; + } + ILA_ASSERT(false) << "BUG: Operator " << int(inout->get_op()) << " is not handled"; + + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(0); + inout->set_annotation(new_annotation); +} // infer_type_op + RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in) { if(in->is_constant()) { @@ -489,6 +682,8 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in in->get_op() == verilog_expr::voperator::LT || in->get_op() == verilog_expr::voperator::C_EQ || in->get_op() == verilog_expr::voperator::L_EQ || + in->get_op() == verilog_expr::voperator::C_NEQ || + in->get_op() == verilog_expr::voperator::L_NEQ || in->get_op() == verilog_expr::voperator::L_NEG || in->get_op() == verilog_expr::voperator::L_AND || in->get_op() == verilog_expr::voperator::L_OR @@ -497,7 +692,7 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in } else if (in->get_op() == verilog_expr::voperator::INDEX) { RfMapVarType child_type = TypeInferTravserRfExpr(in->child(0)); if (child_type.is_array()) - return child_type.unified_width(); // data width + return RfMapVarType(child_type.unified_width()); // data width // TODO: check index within ? if (child_type.is_bv()) return RfMapVarType(1); @@ -505,6 +700,7 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in } else if ( in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { + assert(in->get_child().size() == 3); unsigned diff; bool succ = _compute_const(in->child(2), diff /*ref*/); // TODO: check index within ? @@ -520,7 +716,7 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in if(!succ) return RfMapVarType(); // TODO: check width! - return std::max(l,r)-std::min(l,r) + 1; + return RfMapVarType(std::max(l,r)-std::min(l,r) + 1); } else if (in->get_op() == verilog_expr::voperator::STORE_OP) { // TODO: check width! // actually not implemented @@ -552,6 +748,7 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in auto tp = TypeInferTravserRfExpr(in->child(1)); return RfMapVarType(tp.unified_width()*ntimes); } + ILA_ASSERT(false) << "BUG: Operator " << int(in->get_op()) << " is not handled"; } // end of else has op return RfMapVarType(); } // TypeInferTravserRfExpr diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 3a43daa84..79da8a875 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -74,8 +74,8 @@ bool load_json(const std::string& fname, nlohmann::json& j) { static bool ParseRfExprErrFlag = false; -RfExpr ParseRfMapExpr(const std::string & in) { - // TODO + +RfExpr VerilogRefinementMap::ParseRfExprFromString(const std::string & in) { Vexp::Interpreter intp; std::stringstream ss; ss << in; @@ -84,11 +84,19 @@ RfExpr ParseRfMapExpr(const std::string & in) { intp.parse(); return intp.GetAstRoot(); } catch (verilog_expr::VexpException &e) { - ParseRfExprErrFlag = true; + } return nullptr; } +RfExpr ParseRfMapExpr(const std::string & in) { + // TODO + auto ret = VerilogRefinementMap::ParseRfExprFromString(in) + if (ret == nullptr) + ParseRfExprErrFlag = true; + return ret; +} + RfExpr ParseRfMapExprJson(nlohmann::json & in) { return ParseRfMapExpr(in.get()); } @@ -422,7 +430,7 @@ std::string JsonRfmapParsePhaseTracker(PhaseTracker & tracker, nlohmann::json & auto LHS = a.substr(0,pos); auto RHS = a.substr(pos+2); PhaseTracker::Assignment assign; - StrTrim(LHS); + StrTrim(LHS); // you don't need to trim RHS (parsing will help) assign.LHS = LHS; assign.RHS = ParseRfMapExpr(RHS); ws.enter_action.push_back(assign); diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 7c007baf2..418a0b02e 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -162,6 +162,92 @@ std::string VlgSglTgtGen::ReplExpr(const rfmap::RfExpr & in) { return new_node->to_verilog(); } +std::string VlgSglTgtGen::TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn) { + if(refinement_map.IsLastLevelBooleanOp(in)) + return ReplExpr(in); + auto vnode = verilog_expr::VExprAst::MakeVar("ILA."+ila_vn); + auto eq_node = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, vnode, in); + return ReplExpr(eq_node); +} + +void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, + const rfmap::IlaVarMapping &vmap, const std::string & problem_name, bool true_for_assumpt_false_for_assert, + const std::string & prefix, const std::string & suffix) { + +#define ADD_CONSTR(p1) do{ \ + if(true_for_assumpt_false_for_assert) \ + add_an_assumption(prefix + (p1) + suffix, problem_name); \ + else \ + add_an_assertion(prefix + (p1) + suffix, problem_name); \ + }while(0) + + bool is_mem = _host->state(ila_state_name)->is_mem(); + if(!is_mem) { + ILA_ERROR_IF(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) + << "ila sv " << ila_state_name << " is not memory!"; + if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::SINGLE) { + ADD_CONSTR(TranslateMap(vmap.single_map.single_map, ila_state_name)); + } else if (vmap.type == rfmap::IlaVarMapping::StateVarMapType::CONDITIONAL) { + std::vector all_mappings; + std::string prev_neg; // make sure it is a priority condition lists + for (const auto & cond_map_pair : vmap.single_map.cond_map) { + std::string cond_expr = ReplExpr(cond_map_pair.first); + std::string vmap_expr = TranslateMap(cond_map_pair.second, ila_state_name); + + all_mappings.push_back("~ (" + prev_neg + "(" + cond_expr + ") ) || (" + + vmap_expr + ")"); + prev_neg += "~(" + cond_expr + ")&&"; + } // end for each condition map item + ILA_ERROR_IF(all_mappings.empty()) << "Conditional map is empty!"; + auto map_str = "(" + Join(all_mappings, " )&&( ") + ")"; + ADD_CONSTR(map_str); + } // end map type + } else { + if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { + // TODO: (note: multiple ports!) + // assume : START |-> + // ( ila.ren && rtl.renexpr && (ila.raddr == rtl.raddrexpr) |-> + // (ila.rdata === rtl.rdataexpr) ) + + // assert : IEND |-> + // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> + // (ila.wdata_d1 == rtl.wdataexpr) && (ila.waddr_d1 == rtl.waddrexpr) ) ) + + + } // same for jg/non-jg + else { + bool is_jg = _backend == backend_selector::JASPERGOLD; + bool is_pono = _backend == backend_selector::PONO; + if(is_jg) { + // same as non-mem var + if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::SINGLE) { + ADD_CONSTR(TranslateMap(vmap.single_map.single_map, ila_state_name)); + } else if (vmap.type == rfmap::IlaVarMapping::StateVarMapType::CONDITIONAL) { + std::vector all_mappings; + std::string prev_neg; // make sure it is a priority condition lists + for (const auto & cond_map_pair : vmap.single_map.cond_map) { + std::string cond_expr = ReplExpr(cond_map_pair.first); + std::string vmap_expr = TranslateMap(cond_map_pair.second, ila_state_name); + + all_mappings.push_back("~ (" + prev_neg + "(" + cond_expr + ") ) || (" + + vmap_expr + ")"); + prev_neg += "~(" + cond_expr + ")&&"; + } // end for each condition map item + ILA_ERROR_IF(all_mappings.empty()) << "Conditional map is empty!"; + auto map_str = "(" + Join(all_mappings, " )&&( ") + ")"; + ADD_CONSTR(map_str); + } // end map type + } else { + //TODO: to smt-lib2 + ILA_CHECK(is_pono) << "Only PONO/JG backend can handle array eq property"; + if () + + } // end of is_jg / else + } // end of is_extmem / else + } // end for memory-case + +#undef ADD_CONSTR +} // end of Gen_varmap_assumpt_assert // ila-state -> ref (json) // return a verilog verilog, that should be asserted to be true for this purpose diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index c3d6a71b3..103253c44 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -165,6 +165,13 @@ void VlgSglTgtGen::ConstructWrapper_generate_header() { vlg_wrapper.add_preheader("\n" + _vtg_config.WrapperPreheader + "\n"); } // ConstructWrapper_generate_header +void VlgSglTgtGen::ConstructWrapper_add_inputmap_assumptions() { + + for (const auto & iv_rfmap : refinement_map.ila_input_var_map) { + + } +} + // for special memory, we don't need to do anything? void VlgSglTgtGen::ConstructWrapper_add_varmap_assumptions() { ILA_CHECK(target_type == target_type_t::INSTRUCTIONS) @@ -175,44 +182,33 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assumptions() { for (size_t state_idx = 0; state_idx < _host->state_num(); ++state_idx) ila_state_names.insert(_host->state(state_idx)->name().str()); - nlohmann::json& state_mapping = IN("state mapping", rf_vmap) - ? rf_vmap["state mapping"] - : rf_vmap["state-mapping"]; - for (auto& i : state_mapping.items()) { - auto sname = i.key(); - if (!IN(sname, ila_state_names)) { + for (const auto & sv_rfmap : refinement_map.ila_state_var_map) { + const auto & sname = sv_rfmap.first; + if(!IN(sname, ila_state_names)) { ILA_ERROR << sname << " is not a state of the ILA:" << _host->name().str(); continue; } + if (_vtg_config.OnlyAssumeUpdatedVarsEq && _instr_ptr->update(sname) == nullptr) { ILA_DLOG("VtargetGen") << "Skip assume EQ on variable:" << sname << " for instruction:" << _instr_ptr->name().str(); continue; } - ila_state_names.erase(sname); - // __START__ ==> vmap ILA_DLOG("VtargetGen.ConstructWrapper_add_varmap_assumptions") << sname; std::string problem_name = "variable_map_assume_"; - if (_vtg_config.PerVariableProblemCosa && - _backend != backend_selector::RELCHC) - problem_name += "_" + sname; - // if we are targeting yosys, we should make sure they have the same - // problem_name so the it knowns these are the assumptions for varmap - + if (_backend == backend_selector::RELCHC) { - - add_an_assumption(GetStateVarMapExpr(sname, i.value()), problem_name); + Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, true, "", "" ); // its signal reference will be replaced, but this should be fine // because the names on any level is the same! } else - add_an_assumption("(~ __START__ )|| (" + - GetStateVarMapExpr(sname, i.value()) + ")", - problem_name); - } + Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, true, "(~ __START__ )|| (", ")" ); + } // end for each state variable + ILA_DLOG("VtargetGen") << "STEP:" << "5.2.2"; // check for unmapped states diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index 888d36d80..1112929e0 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -328,6 +328,8 @@ void VlgSglTgtGen::ConstructWrapper_register_extra_io_wire() { auto old_name = refered_vlg_item.second.get_orig_name(); auto new_name = refered_vlg_item.second.get_new_name(); + if(StrStartsWith(new_name, "__ILA_")) + continue; auto idx = old_name.find("["); auto removed_range_name = old_name.substr(0, idx); diff --git a/src/vtarget-out/vtarget_gen_impl.cc b/src/vtarget-out/vtarget_gen_impl.cc index 7517f7768..768836055 100644 --- a/src/vtarget-out/vtarget_gen_impl.cc +++ b/src/vtarget-out/vtarget_gen_impl.cc @@ -357,95 +357,12 @@ void VlgVerifTgtGen::GenerateTargets(void) { } } // end of function GenerateTargets -void VlgVerifTgtGen::set_module_instantiation_name() { - if (bad_state_return()) - return; - // use the content in the refinement relations to determine the instance name - auto& model_specified = rf_vmap["models"]; - for (auto&& name_description_pair : model_specified.items()) { - if (name_description_pair.key() == "ILA") { - _ila_mod_inst_name = name_description_pair.value(); - } else if (name_description_pair.key() == "VERILOG") { - _vlg_mod_inst_name = name_description_pair.value(); - } else - ILA_ERROR << "Unknown model specification:" << name_description_pair.key() - << " expect VERILOG or ILA"; - } - // if unset - if (_vlg_mod_inst_name == "") { - ILA_WARN - << "Verilog top module instance name not set, assuming to be VERILOG"; - _vlg_mod_inst_name = "VERILOG"; - } - if (_ila_mod_inst_name == "") { - ILA_WARN << "ILA top module instance name not set, assuming to be ILA"; - _ila_mod_inst_name = "ILA"; - } -} // set_module_instantiation_name - bool VlgVerifTgtGen::bad_state_return(void) { ILA_ERROR_IF(_bad_state) << "VlgVerifTgtGen is in a bad state, cannot proceed."; return _bad_state; } // bad_state_return -// return npos if no comments in -static size_t find_comments(const std::string& line) { - enum state_t { PLAIN, STR, LEFT } state, next_state; - state = PLAIN; - size_t ret = 0; - for (const auto& c : line) { - if (state == PLAIN) { - if (c == '/') - next_state = LEFT; - else if (c == '"') - next_state = STR; - else - next_state = PLAIN; - } else if (state == STR) { - if (c == '"' || c == '\n') - next_state = PLAIN; - // the '\n' case is in case we encounter some issue to find - // the ending of a string - else - next_state = STR; - } else if (state == LEFT) { - if (c == '/') { - ILA_CHECK(ret > 0); - return ret - 1; - } else - next_state = PLAIN; - } - state = next_state; - ++ret; - } - return std::string::npos; -} - -void VlgVerifTgtGen::load_json(const std::string& fname, nlohmann::json& j) { - if (bad_state_return()) - return; - std::ifstream fin(fname); - - if (!fin.is_open()) { - ILA_ERROR << "Cannot read from file:" << fname; - _bad_state = true; - return; - } - - // remove the comments - std::string contents; - std::string line; - while (std::getline(fin, line)) { - auto comment_begin = find_comments(line); - if (comment_begin != std::string::npos) - contents += line.substr(0, comment_begin); - else - contents += line; - contents += "\n"; - } - j = nlohmann::json::parse(contents); -} // load_json #ifdef INVSYN_INTERFACE diff --git a/src/vtarget-out/vtarget_gen_relchc.cc b/src/vtarget-out/vtarget_gen_relchc.cc index 5a0e20f70..f7fa224ba 100644 --- a/src/vtarget-out/vtarget_gen_relchc.cc +++ b/src/vtarget-out/vtarget_gen_relchc.cc @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff --git a/src/vtarget-out/vtarget_gen_yosys.cc b/src/vtarget-out/vtarget_gen_yosys.cc index fc2d5ec6c..badaa7e85 100644 --- a/src/vtarget-out/vtarget_gen_yosys.cc +++ b/src/vtarget-out/vtarget_gen_yosys.cc @@ -12,7 +12,6 @@ #include #include #include -#include namespace ilang { @@ -407,10 +406,15 @@ void VlgSglTgtGen_Yosys::Export_modify_verilog() { static_cast( _vtg_config.PortDeclStyle), _vtg_config.PonoAddKeep, - supplementary_info.width_info); + refinement_map.width_info); for (auto&& refered_vlg_item : refinement_map.var_replacement) { auto old_name = refered_vlg_item.second.get_orig_name(); + auto new_name = refered_vlg_item.second.get_new_name(); + + if(StrStartsWith(new_name, "__ILA_")) + continue; + auto idx = old_name.find("["); auto removed_range_name = old_name.substr(0, idx); vlg_mod.RecordKeepSignalName(removed_range_name); From e207e89216f3dd0550d842f8b75bee3703192759 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 2 Jul 2021 21:52:58 -0400 Subject: [PATCH 21/78] rfexpr to smt test WIP --- include/ilang/rfmap-in/rfexpr_to_smt.h | 31 +++++- include/ilang/rfmap-in/rfmap_typecheck.h | 37 +++++-- src/rfmap-in/rfexpr_to_smt.cc | 43 ++++---- src/rfmap-in/rfmap_typecheck.cc | 128 +++++++++++++++-------- src/vtarget-out/gen_util.cc | 5 +- test/t_rfexpr_smt_out.cc | 63 +++++++++++ 6 files changed, 232 insertions(+), 75 deletions(-) create mode 100644 test/t_rfexpr_smt_out.cc diff --git a/include/ilang/rfmap-in/rfexpr_to_smt.h b/include/ilang/rfmap-in/rfexpr_to_smt.h index 38503eb02..aa81bebb3 100644 --- a/include/ilang/rfmap-in/rfexpr_to_smt.h +++ b/include/ilang/rfmap-in/rfexpr_to_smt.h @@ -10,15 +10,40 @@ namespace ilang { namespace rfmap { +struct SmtType: public RfMapVarType { + bool bool_or_bv; + + SmtType() : RfMapVarType(1), bool_or_bv(true) {} + SmtType(unsigned w) : RfMapVarType(w), bool_or_bv(false) {} + SmtType(unsigned a, unsigned d) : RfMapVarType(a,d), bool_or_bv(false) {} + SmtType(const RfMapVarType &r, bool request_bool) : + RfMapVarType(r), bool_or_bv(request_bool) {} + + bool is_bool() const { return bool_or_bv && (RfMapVarType::is_bv()); } + bool is_bv() const { return (!bool_or_bv) && (RfMapVarType::is_bv()); } + bool operator=(const SmtType & r) const { + if(bool_or_bv != r.bool_or_bv) + return false; + if(type != r.type) + return false; + if(type == TYPE::BV) + return width == r.width; + if(type == TYPE::MEM) + return data_width == r.data_width && addr_width == r.addr_width; + return false; // unknown type , unknown + } // operator= + +}; // SmtType + struct RfExpr2Smt{ public: - static std::string to_smt2(const RfExpr &in, bool request_bool); + static std::string to_smt2(const RfExpr &in, SmtType expected_type); protected: // helper function - static std::string to_smt2_const(const std::shared_ptr & in, bool request_bool); - static std::string to_smt2_var(const std::shared_ptr & in, bool request_bool); + static std::string to_smt2_const(const std::shared_ptr & in, SmtType expected_type); + static std::string to_smt2_var(const std::shared_ptr & in, SmtType expected_type); }; // struct RfExpr2Smt diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index 58f539dbc..e221563e7 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -106,10 +106,34 @@ bool _compute_const(const RfExpr & in, unsigned & out); // try find_rtl_type -> TypeAnnotation // type annotation & checking & replacing : all-together -struct TypedVerilogRefinementMap : public VerilogRefinementMap { +class TypeAnalysisUtility { - // type definitions +public: typedef std::function var_typecheck_t; + TypeAnalysisUtility(var_typecheck_t type_checker) : typechecker(type_checker) { } + +public: + /// Annotate the type of a refinement expression + /// and this process will be recursive + // this function is to help with unit testing + void AnnotateType(const RfExpr & inout); + +protected: + var_typecheck_t typechecker; + + // internal use only, does not do recursion itself + // therefore, an order of invocation is needed + static void infer_type_based_on_op_child(const RfExpr & inout) ; + +}; // struct TypeAnalysisUtility + + +struct TypedVerilogRefinementMap : + public VerilogRefinementMap, + public TypeAnalysisUtility { + + // type definitions + using var_typecheck_t = TypeAnalysisUtility::var_typecheck_t; using VarDef = GeneralVerilogMonitor::VarDef; // constructor @@ -162,11 +186,7 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { void TraverseRfExpr(RfExpr & inout, std::function func) ; void TraverseCondMap(SingleVarMap & inout, std::function func) ; - var_typecheck_t typechecker; - // internal use only, does not do recursion itself - // therefore, an order of invocation is needed - void infer_type_op(const RfExpr & inout) ; private: // help with naming @@ -178,7 +198,10 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap { void collect_inline_delay_func(RfExpr & inout); void CollectInlineDelayValueHolder(); - RfMapVarType TypeInferTravserRfExpr(const RfExpr & in); + // this function is used in value holder/delay : width determination + // will use all_var_def_types + RfMapVarType TypeInferTravserRfExpr(const RfExpr & in); + void ComputeDelayValueHolderWidth(); }; // TypedVerilogRefinementMap diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc index bd9277d96..4532facfa 100644 --- a/src/rfmap-in/rfexpr_to_smt.cc +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -104,8 +104,16 @@ static std::string bvboolconvert(bool out_bool, bool in_bool, size_t inwidth, co // else: !in_bool && out_bool return "(not (= " + in + " "+ smt_const(0, inwidth) +"))"; } - -std::string RfExpr2Smt::to_smt2_const(const std::shared_ptr & in, bool request_bool) { +// typeconvert +// intype == outtype +// bv_n -> bool +// bool -> bv_n +// bv_n -> bv_(n+m) +// E: truncate +// E: array -> ? +// E: ? -> array + +std::string RfExpr2Smt::to_smt2_const(const std::shared_ptr & in, SmtType expected_type) { unsigned out; bool succ = _compute_const(in, out); if(!succ) @@ -117,7 +125,7 @@ std::string RfExpr2Smt::to_smt2_const(const std::shared_ptr & in, bool request_bool) { +std::string RfExpr2Smt::to_smt2_var(const std::shared_ptr & in, SmtType expected_type) { RfMapVarType tp = in->get_annotation()->type; auto ret = "|" + in->get_name().first+"|"; if(!tp.is_array()) @@ -126,7 +134,7 @@ std::string RfExpr2Smt::to_smt2_var(const std::shared_ptris_var()) { auto ptr = std::dynamic_pointer_cast(in); ILA_NOT_NULL(ptr); @@ -154,33 +162,32 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, bool request_bool) { (op_ == verilog_expr::voperator::L_NEG)) { RfMapVarType tp = get_type(child_.at(0)); - return bvboolconvert(request_bool, true, tp.unified_width(), - "("+opstr + " " + to_smt2(child_.at(0), true)+")"); + return type_convert( expected_type, SmtType(tp,true), + "("+opstr + " " + to_smt2(child_.at(0), SmtType(tp,true) )+")"); } if ( child_.size() == 1 && (op_ == verilog_expr::voperator::B_NEG)) { RfMapVarType tp = get_type(child_.at(0)); - return bvboolconvert(request_bool, false, tp.unified_width(), - "("+opstr + " " + to_smt2(child_.at(0), false)+")"); + return type_convert(expected_type, SmtType(tp,false), + "("+opstr + " " + to_smt2(child_.at(0), SmtType(tp,false))+")"); } if (child_.size() == 1 && op_ == verilog_expr::voperator::PLUS) { - RfMapVarType tp = get_type(child_.at(0)); - return bvboolconvert(request_bool, false, tp.unified_width(), - to_smt2(child_.at(0), false)); + RfMapVarType tp = get_type(in); + return type_convert(expected_type, SmtType(tp,false), + to_smt2(child_.at(0), SmtType(tp,false))); } if (child_.size() == 1 && op_ == verilog_expr::voperator::MINUS) { - - RfMapVarType tp = get_type(child_.at(0)); - return bvboolconvert(request_bool, false, tp.unified_width(), - "(bvsub " + smt_const(0,tp.unified_width()) + " "+to_smt2(child_.at(0), false)); + RfMapVarType tp = get_type(in); + return type_convert(expected_type, SmtType(tp,false), + "(bvsub " + smt_const(0,tp.unified_width()) + " "+to_smt2(child_.at(0), SmtType(tp,false))); } if (child_.size() == 1 && @@ -192,10 +199,10 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, bool request_bool) { op_ == verilog_expr::voperator::B_EQU )) { - RfMapVarType tp = get_type(child_.at(0)); + RfMapVarType tp = get_type(in); - return bvboolconvert(request_bool, false, tp.unified_width(), - split_bit(opstr, tp.unified_width(), to_smt2(child_.at(0), false))); + return type_convert(expected_type, SmtType(tp,false), + split_bit(opstr, tp.unified_width(), to_smt2(child_.at(0), SmtType(tp,false)))); } RfMapVarType parent_tp = get_type(in); diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 761bf76cc..e4fa2b6b3 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -20,7 +20,7 @@ std::string TypedVerilogRefinementMap::new_id() { TypedVerilogRefinementMap::TypedVerilogRefinementMap( const VerilogRefinementMap & refinement, var_typecheck_t type_checker - ) : VerilogRefinementMap(refinement), counter(0), typechecker(type_checker) { + ) : VerilogRefinementMap(refinement), counter(0), TypeAnalysisUtility(type_checker) { initialize(); } @@ -29,7 +29,7 @@ TypedVerilogRefinementMap::TypedVerilogRefinementMap( const std::string & instcond_json_file, var_typecheck_t type_checker ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), - counter(0), typechecker(type_checker) { + counter(0), TypeAnalysisUtility(type_checker) { initialize(); } // TypedVerilogRefinementMap::TypedVerilogRefinementMap @@ -48,6 +48,7 @@ void TypedVerilogRefinementMap::initialize() { } // initialize +// this function will iteratively make a new copy of the whole AST. RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( const RfExpr & in, bool replace_internal_wire) @@ -127,14 +128,15 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( return ret_copy; // will return the annotated one anyway } // is_var else if (in->is_constant()) { - if(in->get_annotation() == nullptr) { + auto cptr = std::dynamic_pointer_cast(in); + ILA_NOT_NULL(cptr); + auto ret_copy = std::make_shared(*cptr); + if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { RfVarTypeOrig tp; - auto cptr = std::dynamic_pointer_cast(in); - ILA_NOT_NULL(cptr); tp.type = RfMapVarType(std::get<1>(cptr->get_constant())); // base, width,... - in->set_annotation(std::make_shared(tp)); + ret_copy->set_annotation(std::make_shared(tp)); } - return in; // no annotation needed + return ret_copy; // no annotation needed } else { // check type auto ret_copy = std::make_shared(*in); @@ -175,11 +177,16 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( return new_node; } else { ILA_CHECK(false) << "FIXME: currently does not handle dynamic index into array"; + // HZ note: in the future we can do this + // by allowing array shadowing, this will definitely need smt-lib2 expression + // or Jasper's capability, because we can never connect a whole Verilog array out + // using Yosys's SVA. + } // end if it is const } } // special handling for array[idx] // to determine the type of ret_copy - infer_type_op(ret_copy); + infer_type_based_on_op_child(ret_copy); return ret_copy; // may use new_node instead in the special case } // end of is_op assert(false); // Should not be reachable @@ -447,7 +454,74 @@ bool TypedVerilogRefinementMap::IsLastLevelBooleanOp(const RfExpr & in) { return (boolean_op.find(op) == boolean_op.end()); } -void TypedVerilogRefinementMap::infer_type_op(const RfExpr & inout) { +void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { + for(auto & name_delay_pair: aux_delays) { + if(name_delay_pair.second.width == 0) { + auto tp = TypeInferTravserRfExpr(name_delay_pair.second.signal); + ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; + ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_delay_pair.second.signal->to_verilog(); + name_delay_pair.second.width = tp.unified_width(); + + // replendish all_var_def_types + VarDef internal_var_def; + internal_var_def.width = tp.unified_width(); + internal_var_def.type = VarDef::var_type::REG; + + all_var_def_types.emplace(name_delay_pair.first, internal_var_def); + } + } + for (auto & name_vr : value_recorder) { + if (name_vr.second.width == 0) { + auto tp = TypeInferTravserRfExpr(name_vr.second.value); + ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; + ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_vr.second.value->to_verilog(); + name_vr.second.width = tp.unified_width(); + + // replendish all_var_def_types + VarDef internal_var_def; + internal_var_def.width = tp.unified_width(); + internal_var_def.type = VarDef::var_type::REG; + + all_var_def_types.emplace(name_vr.first, internal_var_def); + } + } // replendish internal defined vars +} // ComputeDelayValueHolderWidth + +// ------------------------------------------------------------------ +// type inference rules + +// differences from TypedVerilogRefinementMap::ReplacingRtlIlaVar +// 1. no var replacement (__ILA_I_, __ILA_SO_, __DOT__), array[idx] +// 2. no special name handling +void TypeAnalysisUtility::AnnotateType(const RfExpr & inout) { + auto tp_annotate = inout->get_annotation(); + + if(inout->is_var()) { + auto var_ptr = std::dynamic_pointer_cast(inout); + ILA_NOT_NULL(var_ptr); + auto n = var_ptr->get_name(); + + if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { + auto rtl_ila_tp = typechecker(n.first); + inout->set_annotation(std::make_shared(rtl_ila_tp)); + } + } else if (inout->is_constant()) { + if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { + RfVarTypeOrig tp; + auto cptr = std::dynamic_pointer_cast(inout); + ILA_NOT_NULL(cptr); + tp.type = RfMapVarType(std::get<1>(cptr->get_constant())); // base, width,... + inout->set_annotation(std::make_shared(tp)); + } // end if no annotation + } else { // op + for (size_t idx = 0 ; idx < inout->get_child_cnt(); ++ idx) + AnnotateType(inout->child(idx)); + infer_type_based_on_op_child(inout); + // for each child + } // end if-else- op +} // TypeAnalysisUtility::AnnotateType + +void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr & inout) { assert( inout->get_op() != verilog_expr::voperator::MK_CONST && inout->get_op() != verilog_expr::voperator::MK_VAR ); @@ -753,42 +827,6 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in return RfMapVarType(); } // TypeInferTravserRfExpr -void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { - for(auto & name_delay_pair: aux_delays) { - if(name_delay_pair.second.width == 0) { - auto tp = TypeInferTravserRfExpr(name_delay_pair.second.signal); - ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; - ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_delay_pair.second.signal->to_verilog(); - name_delay_pair.second.width = tp.unified_width(); - - // replendish all_var_def_types - VarDef internal_var_def; - internal_var_def.width = tp.unified_width(); - internal_var_def.type = VarDef::var_type::REG; - - all_var_def_types.emplace(name_delay_pair.first, internal_var_def); - } - } - for (auto & name_vr : value_recorder) { - if (name_vr.second.width == 0) { - auto tp = TypeInferTravserRfExpr(name_vr.second.value); - ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; - ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_vr.second.value->to_verilog(); - name_vr.second.width = tp.unified_width(); - - // replendish all_var_def_types - VarDef internal_var_def; - internal_var_def.width = tp.unified_width(); - internal_var_def.type = VarDef::var_type::REG; - - all_var_def_types.emplace(name_vr.first, internal_var_def); - } - } - // replendish internal defined vars - - -} // ComputeDelayValueHolderWidth - } // namespace rfmap } // namespace ilang diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 418a0b02e..8fc6f4ec6 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -213,7 +213,7 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> // (ila.wdata_d1 == rtl.wdataexpr) && (ila.waddr_d1 == rtl.waddrexpr) ) ) - + #error "connect according to the above" } // same for jg/non-jg else { bool is_jg = _backend == backend_selector::JASPERGOLD; @@ -240,7 +240,8 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, } else { //TODO: to smt-lib2 ILA_CHECK(is_pono) << "Only PONO/JG backend can handle array eq property"; - if () + + #error "to smtlib2, need ReplacingRtlIlaVar first which will infer type" } // end of is_jg / else } // end of is_extmem / else diff --git a/test/t_rfexpr_smt_out.cc b/test/t_rfexpr_smt_out.cc new file mode 100644 index 000000000..0c0210146 --- /dev/null +++ b/test/t_rfexpr_smt_out.cc @@ -0,0 +1,63 @@ +/// \file +/// Unit test for refinement expression to smt-lib2 + +#include + +#include "unit-include/config.h" +#include "unit-include/util.h" + +// use rfmap::VerilogRefinementMap::ParseRfExprFromString +// to parse a refinement expression +// and use rfmap::RfExpr2Smt::to_smt2 to translate to smt-lib2 +// but you need type annotation first +// this flow is used in array handling with pono + +namespace ilang { + + +#define PRINT_SMT(s, b) do { \ + std::string rfstr = (s); \ + auto rfexpr = rfmap::VerilogRefinementMap::ParseRfExprFromString(rfstr); \ + annotator.AnnotateType(rfexpr); \ + std::cout << RfExpr2Smt::to_smt2(rfexpr, (b)) << std::endl; \ +} while(0) + +TEST(TestRfexpr, ToSmt) { + // 1. construct var to rf_var_type map + // and the function to map that + // 2. annotate the type + // 3. convert + std::map var_type = + { + {"a", rfmap::RfMapVarType(16) }, + {"b", rfmap::RfMapVarType(8) }, + {"c", rfmap::RfMapVarType(1) }, + {"array1", rfmap::RfMapVarType(16,8) }, + {"array2", rfmap::RfMapVarType(16,8) }, + {"array3", rfmap::RfMapVarType(8,16) } + }; + + auto check_var_type = + [&var_type](const std::string & n) -> rfmap::RfVarTypeOrig { + RfVarTypeOrig ret; + auto pos = var_type.find(n); + if(pos != var_type.end()) + ret.type = pos->second; + return ret; + }; + + rfmap::TypeAnalysisUtility annotator(check_var_type); + + + PRINT_SMT("a[4] == b[4]" , true); + PRINT_SMT("a[5:4] + c[4:3] != array1[a][2:1]" , true); + PRINT_SMT(" c ? array1 : array2 " , false); + PRINT_SMT(" c == 1'b1? array1 : array2 " , false); + PRINT_SMT(" array3[b+1] " , false); + + + +} // TEST(TestRfexpr, ToSmt) + +} // namespace ilang + From e465c787e13e51bc577b9f559ee7caf65b1ba8a7 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 7 Jul 2021 07:41:14 -0400 Subject: [PATCH 22/78] rfexpr 2 smt --- include/ilang/rfmap-in/rfexpr_to_smt.h | 2 +- src/rfmap-in/rfexpr_to_smt.cc | 229 +++++++++++++++++-------- 2 files changed, 162 insertions(+), 69 deletions(-) diff --git a/include/ilang/rfmap-in/rfexpr_to_smt.h b/include/ilang/rfmap-in/rfexpr_to_smt.h index aa81bebb3..a8c819ccf 100644 --- a/include/ilang/rfmap-in/rfexpr_to_smt.h +++ b/include/ilang/rfmap-in/rfexpr_to_smt.h @@ -21,7 +21,7 @@ struct SmtType: public RfMapVarType { bool is_bool() const { return bool_or_bv && (RfMapVarType::is_bv()); } bool is_bv() const { return (!bool_or_bv) && (RfMapVarType::is_bv()); } - bool operator=(const SmtType & r) const { + bool operator==(const SmtType & r) const { if(bool_or_bv != r.bool_or_bv) return false; if(type != r.type) diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc index 4532facfa..582028932 100644 --- a/src/rfmap-in/rfexpr_to_smt.cc +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -95,15 +95,59 @@ static std::string split_bit(const std::string & opstr, return ret; } +static SmtType common_type(RfMapVarType tp1, RfMapVarType tp2) { + if(tp1.is_array() || tp2.is_array()) { + ILA_CHECK(tp2.is_array() && tp1.is_array() && + tp2.addr_width == tp1.addr_width && + tp2.data_width == tp1.data_width); + return SmtType(tp1, false); + } + + if(tp1.is_bv() && tp2.is_bv()) { + return SmtType( std::max(tp1.unified_width(), tp2.unified_width()) ); + } + + if(tp1.is_unknown() || tp2.is_unknown()) { + if (!tp1.is_unknown()) + return SmtType(tp1,false); + if (!tp2.is_unknown()) + return SmtType(tp2,false); + } + ILA_CHECK(false) << "unable to determine common type"; +} + +static std::string extend_width(const std::string & in, unsigned inw, unsigned outw) { + ILA_CHECK(outw > inw); + return "(concat " + smt_const(0, outw-inw) + " " + in + ")"; +} // make sure in_bool -> out_bool -static std::string bvboolconvert(bool out_bool, bool in_bool, size_t inwidth, const std::string & in) { - if(in_bool == out_bool) +static std::string type_convert(SmtType out_tp, SmtType in_tp, const std::string & in) { + if(out_tp == in_tp) return in; - if(in_bool && !out_bool) - return "(ite " + in + " #b1 #b0)"; - // else: !in_bool && out_bool - return "(not (= " + in + " "+ smt_const(0, inwidth) +"))"; + + if(out_tp.is_bool() && in_tp.is_bv()) { + return "(not (= " + in + " "+ smt_const(0, in_tp.unified_width()) +"))"; + } + + if(in_tp.is_bool() && out_tp.is_bv()) { + return extend_width("(ite " + in + " #b1 #b0)",1,out_tp.unified_width()) ; + } + + if(in_tp.is_bv() && out_tp.is_bv() && + in_tp.unified_width() != out_tp.unified_width()) + { + ILA_ASSERT(out_tp.unified_width() > in_tp.unified_width()) + << "[Convert to SMT] cutting input bit-vector, not allowed."; + return extend_width(in, in_tp.unified_width(), out_tp.unified_width()); + } + + if(in_tp.is_array() || out_tp.is_array()) { + ILA_CHECK(false) << "Unable to convert array of different sizes"; + } + ILA_CHECK(false) << "Unable to convert types"; + return "|ERROR|"; } + // typeconvert // intype == outtype // bv_n -> bool @@ -121,15 +165,16 @@ std::string RfExpr2Smt::to_smt2_const(const std::shared_ptrget_constant(); auto width = std::get<1>(b_w_l); - return bvboolconvert(request_bool, false, width, smt_const(out, width) ); + return type_convert(expected_type, SmtType(width), smt_const(out, width) ); } // to_smt2_const std::string RfExpr2Smt::to_smt2_var(const std::shared_ptr & in, SmtType expected_type) { - RfMapVarType tp = in->get_annotation()->type; + RfMapVarType tp = get_type(in); auto ret = "|" + in->get_name().first+"|"; if(!tp.is_array()) - ret = bvboolconvert(request_bool, false, tp.unified_width(), ret); + ret = type_convert(expected_type, SmtType(tp.unified_width()), ret); + ILA_ASSERT(expected_type == SmtType(tp,false)); return ret; } // to_smt2_var @@ -138,21 +183,21 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { if(in->is_var()) { auto ptr = std::dynamic_pointer_cast(in); ILA_NOT_NULL(ptr); - return to_smt2_var(ptr, request_bool); + return to_smt2_var(ptr, expected_type); } if (in->is_constant()) { auto ptr = std::dynamic_pointer_cast(in); ILA_NOT_NULL(ptr); - return to_smt2_const(ptr, request_bool); + return to_smt2_const(ptr, expected_type); } auto op_ = in->get_op(); const auto & child_ = in->get_child(); - assert(op_ != verilog_expr::voperator::MK_CONST && op_ != verilog_expr::voperator::MK_CONST); + ILA_ASSERT(op_ != verilog_expr::voperator::MK_CONST && op_ != verilog_expr::voperator::MK_CONST); unsigned idx = static_cast(op_); - assert(idx < voperator_str_smt.size()); + ILA_ASSERT(idx < voperator_str_smt.size()); auto opstr = voperator_str_smt.at(idx); if (opstr == "#notsupported") throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2, opstr ); @@ -218,9 +263,11 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { case verilog_expr::voperator::LSR: case verilog_expr::voperator::DIV: case verilog_expr::voperator::MOD: - assert(child_.size() == 2); - return bvboolconvert(request_bool, false, parent_tp.unified_width(), - "("+opstr+" " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+")" + ILA_ASSERT(child_.size() == 2); + return type_convert(expected_type, SmtType(parent_tp,false), + "(" + opstr+" " + + to_smt2(child_.at(0),SmtType(parent_tp,false)) + " " + + to_smt2(child_.at(1),SmtType(parent_tp,false))+")" ); break; @@ -230,26 +277,38 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { case verilog_expr::voperator::LT: case verilog_expr::voperator::C_EQ: case verilog_expr::voperator::L_EQ: - assert(child_.size() == 2); - return bvboolconvert(request_bool, true, parent_tp.unified_width(), - "("+opstr+" " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+")" - ); - - break; + ILA_ASSERT(child_.size() == 2); + { + SmtType common_tp = common_type(get_type(child_.at(0)), get_type(child_.at(1))); + return type_convert(expected_type, SmtType(parent_tp,true), + "(" + opstr + + " " + to_smt2(child_.at(0),common_tp) + + " " + to_smt2(child_.at(1),common_tp)+")" + ); + } + break; case verilog_expr::voperator::C_NEQ: case verilog_expr::voperator::L_NEQ: - assert(child_.size() == 2); - return bvboolconvert(request_bool, true, parent_tp.unified_width(), - "(not (= " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+"))" - ); - break; + ILA_ASSERT(child_.size() == 2); + { // expect common_type to make bool false? + SmtType common_tp = common_type(get_type(child_.at(0)), get_type(child_.at(1))); + return type_convert(expected_type, SmtType(parent_tp,true), + "(not (= " + + to_smt2(child_.at(0),common_tp) + " " + + to_smt2(child_.at(1),common_tp) + "))" + ); + break; + } case verilog_expr::voperator::L_AND: case verilog_expr::voperator::L_OR: - assert(child_.size() == 2); - return bvboolconvert(request_bool, true, parent_tp.unified_width(), - "(" + opstr + " " + to_smt2(child_.at(0),true) + " " + to_smt2(child_.at(1),true)+")" + ILA_ASSERT(child_.size() == 2); + return type_convert(expected_type, SmtType(parent_tp,true), + "(" + opstr + + " " + to_smt2(child_.at(0),SmtType(get_type(child_.at(0)),true)) + + " " + to_smt2(child_.at(1),SmtType(get_type(child_.at(1)),true)) + + ")" ); break; @@ -259,13 +318,19 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { case verilog_expr::voperator::B_EQU: case verilog_expr::voperator::B_NAND: case verilog_expr::voperator::B_NOR: - assert(child_.size() == 2); - return bvboolconvert(request_bool, false, parent_tp.unified_width(), - "(" + opstr + " " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+")" - ); - break; + { + SmtType common_tp = common_type(get_type(child_.at(0)), get_type(child_.at(1))); + + ILA_ASSERT(child_.size() == 2); + return type_convert(expected_type, SmtType(parent_tp, false), + "(" + opstr + + " " + to_smt2(child_.at(0),common_tp) + + " " + to_smt2(child_.at(1),common_tp) + + ")" + ); + break; + } - default: break; } // end switch @@ -273,8 +338,10 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { if(op_ == verilog_expr::voperator::INDEX) { RfMapVarType tp = get_type(child_.at(0)); if(tp.is_array()) { - return bvboolconvert(request_bool, false, tp.unified_width(), - "(select " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false) + ")"); + return type_convert(expected_type, SmtType(tp.unified_width()), + "(select " + to_smt2(child_.at(0), SmtType(tp, false) ) + + " " + + to_smt2(child_.at(1), SmtType(tp.addr_width)) + ")"); } // else is bv // request to index to be constant unsigned bitidx; @@ -282,9 +349,13 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { if(!succ) throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); auto bitidxstr = std::to_string(bitidx); - return bvboolconvert(request_bool, false,1, - "((_ extract " + bitidxstr + " " + bitidxstr+") " + to_smt2(child_.at(0),false)+")"); - } + return type_convert(expected_type, SmtType(1) /* (_ BitVec 1) */, + "((_ extract " + bitidxstr + " " + bitidxstr+") " + + to_smt2( child_.at(0), + SmtType(tp, false) + ) + + ")" ); + } // end if INDEX if(op_ == verilog_expr::voperator::IDX_PRT_SEL_PLUS || op_ == verilog_expr::voperator::IDX_PRT_SEL_MINUS || @@ -303,48 +374,70 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { r = l - r + 1; auto lstr = std::to_string(l); auto rstr = std::to_string(r); - return bvboolconvert(request_bool, false,l-r+1, - "((_ extract " + lstr + " " + rstr+") " + to_smt2(child_.at(0),false)+")"); - } + RfMapVarType tp = get_type(child_.at(0)); + return type_convert(expected_type, SmtType(l-r+1), + "((_ extract " + lstr + " " + rstr+") " + + to_smt2( child_.at(0), + SmtType(tp, false) + ) + + ")"); + } // IDX_PRT_SEL_PLUS, IDX_PRT_SEL_MINUS, RANGE_INDEX if (op_ == verilog_expr::voperator::STORE_OP) { - return "(store " + to_smt2(child_.at(0),false) + " " + to_smt2(child_.at(1),false)+")"; - } + SmtType tp0(get_type(child_.at(0)), false); + SmtType tp1(get_type(child_.at(1)), false); + // no need to convert + ILA_ASSERT(expected_type == tp0); + return "(store " + + to_smt2(child_.at(0),tp0) + " " + + to_smt2(child_.at(1),tp1) + ")"; + // do not convert as we are unable to do so + } // STORE_OP if (op_ == verilog_expr::voperator::TERNARY) { - RfMapVarType tp = get_type(child_.at(1)); - if(tp.is_array()) - return "(ite " + to_smt2(child_.at(0), true) + " " + - to_smt2(child_.at(1), false) + " " + - to_smt2(child_.at(2), false) +")"; - return bvboolconvert(request_bool, false, tp.unified_width(), - "(ite " + to_smt2(child_.at(0), true) + " " + - to_smt2(child_.at(1), false) + " " + - to_smt2(child_.at(2), false) +")"); + RfMapVarType parent_tp = get_type(in); + // you need to handle the case of array + SmtType common_tp = common_type(get_type(child_.at(1)), get_type(child_.at(2))); + + if(parent_tp.is_array()) { + // do not convert as we are unable to do so + return "(ite " + to_smt2(child_.at(0), SmtType() ) + " " + + to_smt2(child_.at(1), common_tp) + " " + + to_smt2(child_.at(2), common_tp) + ")"; + } // else + + return type_convert(expected_type, common_tp, + "(ite " + to_smt2(child_.at(0), SmtType()) + " " + + to_smt2(child_.at(1), common_tp) + " " + + to_smt2(child_.at(2), common_tp) + ")"); } if (op_ == verilog_expr::voperator::FUNCTION_APP) throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2); if (op_ == verilog_expr::voperator::CONCAT) { - assert( in->get_child_cnt() == 2 ); - return bvboolconvert(request_bool, false, parent_tp.unified_width(), - "(concat " + to_smt2(child_.at(0), false) + " " + - to_smt2(child_.at(1), false) + ")"); - } + ILA_ASSERT( in->get_child_cnt() == 2 ); + return type_convert(expected_type, SmtType(parent_tp,false), + "(concat " + + to_smt2(child_.at(0), SmtType(get_type(child_.at(0)), false) ) + " " + + to_smt2(child_.at(1), SmtType(get_type(child_.at(1)), false) ) + ")"); + } // CONCAT if (op_ == verilog_expr::voperator::REPEAT) { - assert( in->get_child_cnt() == 2 ); + ILA_ASSERT( in->get_child_cnt() == 2 ); unsigned ntimes; if(!_compute_const(in->child(0), ntimes)) throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); - assert(ntimes > 0); - std::string ret = "(concat"; - std::string c1 = to_smt2(child_.at(1), false); - for(unsigned idx = 0; idx < ntimes; ++idx) - ret += " " + c1; - ret += ")"; - return ret; + ILA_ASSERT(ntimes > 0); + std::string c1 = to_smt2( + child_.at(1), + SmtType(get_type(child_.at(1)),false) ); + std::string ret = "(concat " + c1 + " " + c1 + ")" ; + + for(unsigned idx = 2; idx < ntimes; ++idx) + ret = "(concat " + ret + " " + c1 + ")"; + + return type_convert(expected_type, SmtType(parent_tp,false), ret); } throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2); From 3c4124121fe1ccaad610f12be99bd520f85e3560 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 7 Jul 2021 09:29:49 -0400 Subject: [PATCH 23/78] add rfexpr 2 smt convert test --- test/CMakeLists.txt | 1 + test/t_rfexpr_smt_out.cc | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b4cad2fff..5174459ac 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -76,6 +76,7 @@ package_add_test(${ILANG_TEST_MAIN} t_smt_shim.cc t_smt_switch_itf.cc t_smt_trans.cc + t_rfexpr_smt_out.cc t_sort.cc t_symbol.cc t_unroll_seq.cc diff --git a/test/t_rfexpr_smt_out.cc b/test/t_rfexpr_smt_out.cc index 0c0210146..8928ac089 100644 --- a/test/t_rfexpr_smt_out.cc +++ b/test/t_rfexpr_smt_out.cc @@ -19,7 +19,10 @@ namespace ilang { std::string rfstr = (s); \ auto rfexpr = rfmap::VerilogRefinementMap::ParseRfExprFromString(rfstr); \ annotator.AnnotateType(rfexpr); \ - std::cout << RfExpr2Smt::to_smt2(rfexpr, (b)) << std::endl; \ + std::cout << rfmap::RfExpr2Smt::to_smt2(rfexpr, \ + (b) ? rfmap::SmtType() : \ + rfmap::SmtType( (rfexpr->get_annotation())->type, false )) \ + << std::endl; \ } while(0) TEST(TestRfexpr, ToSmt) { @@ -39,7 +42,7 @@ TEST(TestRfexpr, ToSmt) { auto check_var_type = [&var_type](const std::string & n) -> rfmap::RfVarTypeOrig { - RfVarTypeOrig ret; + rfmap::RfVarTypeOrig ret; auto pos = var_type.find(n); if(pos != var_type.end()) ret.type = pos->second; @@ -49,13 +52,12 @@ TEST(TestRfexpr, ToSmt) { rfmap::TypeAnalysisUtility annotator(check_var_type); - PRINT_SMT("a[4] == b[4]" , true); - PRINT_SMT("a[5:4] + c[4:3] != array1[a][2:1]" , true); - PRINT_SMT(" c ? array1 : array2 " , false); - PRINT_SMT(" c == 1'b1? array1 : array2 " , false); - PRINT_SMT(" array3[b+1] " , false); - - + PRINT_SMT("a[4] == b[4]" , true); // should be (extract) + PRINT_SMT("a[5:4] + c[4:3] != array1[a][2:1]" , true); // extract and select + PRINT_SMT(" c ? array1 : array2 " , false); // should handle array well + PRINT_SMT(" c == 1'b1? array1 : array2 " , false); // should be able to convert + PRINT_SMT(" array3[b+1] " , false); // should set the right type of 1 + PRINT_SMT(" a+b == c " , true); // should expand b, c } // TEST(TestRfexpr, ToSmt) From 758fff6f677c70b13d640729a768fa2602097ea4 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 13 Jul 2021 19:52:56 -0700 Subject: [PATCH 24/78] gen_util mod WIP --- include/ilang/rfmap-in/rfexpr_to_smt.h | 2 + include/ilang/rfmap-in/rfmap_typecheck.h | 32 +- include/ilang/rfmap-in/rfvar_type.h | 2 +- include/ilang/rfmap-in/verilog_rfmap.h | 5 +- include/ilang/verilog-out/verilog_gen.h | 7 + include/ilang/vtarget-out/vtarget_gen_impl.h | 42 +- src/rfmap-in/rfexpr_to_smt.cc | 9 + src/rfmap-in/rfmap_typecheck.cc | 446 +++++++++++-------- src/rfmap-in/verilog_rfmap.cc | 9 +- src/verilog-out/verilog_gen.cc | 23 +- src/vtarget-out/gen_util.cc | 195 ++++++-- src/vtarget-out/single_target.cc | 4 +- src/vtarget-out/single_target_as.cc | 77 +++- test/unit-data/vpipe/vmem/cond-rd.json | 2 +- test/unit-data/vpipe/vmem/cond.json | 2 +- 15 files changed, 604 insertions(+), 253 deletions(-) diff --git a/include/ilang/rfmap-in/rfexpr_to_smt.h b/include/ilang/rfmap-in/rfexpr_to_smt.h index a8c819ccf..236b3ee50 100644 --- a/include/ilang/rfmap-in/rfexpr_to_smt.h +++ b/include/ilang/rfmap-in/rfexpr_to_smt.h @@ -33,6 +33,8 @@ struct SmtType: public RfMapVarType { return false; // unknown type , unknown } // operator= + std::string type_to_smt2() const; + }; // SmtType struct RfExpr2Smt{ diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index e221563e7..a4096d38e 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -127,10 +127,21 @@ class TypeAnalysisUtility { }; // struct TypeAnalysisUtility +class RfExprAstUtility { +public: + /// determine if a rf expr is a boolean expr + static bool IsLastLevelBooleanOp(const RfExpr & in); + /// get the variables from a expression + static void GetVars(const RfExpr & in, + std::unordered_map & vars_out); + static RfVarTypeOrig GetType(const RfExpr & in); +}; + struct TypedVerilogRefinementMap : public VerilogRefinementMap, - public TypeAnalysisUtility { + public TypeAnalysisUtility, + public RfExprAstUtility { // type definitions using var_typecheck_t = TypeAnalysisUtility::var_typecheck_t; @@ -140,12 +151,16 @@ struct TypedVerilogRefinementMap : TypedVerilogRefinementMap( const std::string & varmap_json_file, const std::string & instcond_json_file, - var_typecheck_t type_checker + var_typecheck_t type_checker, + const std::string & ila_inst_decode_signal_name, + const std::string & ila_valid_signal_name ); TypedVerilogRefinementMap( const VerilogRefinementMap & refinement, - var_typecheck_t type_checker + var_typecheck_t type_checker, + const std::string & ila_inst_decode_signal_name, + const std::string & ila_valid_signal_name ); @@ -175,13 +190,14 @@ struct TypedVerilogRefinementMap : /// the replacement used for creating new wires std::map var_replacement; // including rtl/ilas/ilav - /// determine if a rf expr is a boolean expr - static bool IsLastLevelBooleanOp(const RfExpr & in); - protected: - void initialize(); - void CollectInternallyDefinedVars(); + void initialize( + const std::string & ila_inst_decode_signal_name, + const std::string & ila_valid_signal_name); + void CollectInternallyDefinedVars( + const std::string & ila_inst_decode_signal_name, + const std::string & ila_valid_signal_name); void TraverseRfExpr(RfExpr & inout, std::function func) ; void TraverseCondMap(SingleVarMap & inout, std::function func) ; diff --git a/include/ilang/rfmap-in/rfvar_type.h b/include/ilang/rfmap-in/rfvar_type.h index 5045146a4..11c8e325d 100644 --- a/include/ilang/rfmap-in/rfvar_type.h +++ b/include/ilang/rfmap-in/rfvar_type.h @@ -27,7 +27,7 @@ struct RfMapVarType { RfMapVarType(unsigned w) : type(TYPE::BV), width(w) {} /// for array type RfMapVarType(unsigned a, unsigned d) : type(TYPE::MEM), addr_width(a), data_width(d) {} - unsigned unified_width() { return type == RfMapVarType::TYPE::BV ? width : data_width; } + unsigned unified_width() const { return type == RfMapVarType::TYPE::BV ? width : data_width; } }; class RfVarTypeOrig { diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 1f0f9ac20..ce5f20ae3 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -27,7 +27,7 @@ namespace rfmap { */ typedef verilog_expr::VExprAst::VExprAstPtr RfExpr; - +typedef verilog_expr::VExprAstVar::VExprAstVarPtr RfVar; /* "ILA_mem_state_var_2" : { // case 4 : external RTL memory @@ -48,12 +48,15 @@ struct SingleVarMap{ }; struct ExternalMemPortMap { + bool wport_mapped; + bool rport_mapped; SingleVarMap wen_map; SingleVarMap waddr_map; SingleVarMap wdata_map; SingleVarMap ren_map; SingleVarMap raddr_map; SingleVarMap rdata_map; + ExternalMemPortMap() : wport_mapped(false), rport_mapped(false) {} }; // struct ExternalMemPortMap struct IlaVarMapping { diff --git a/include/ilang/verilog-out/verilog_gen.h b/include/ilang/verilog-out/verilog_gen.h index b6d3550b7..1be78d3c1 100644 --- a/include/ilang/verilog-out/verilog_gen.h +++ b/include/ilang/verilog-out/verilog_gen.h @@ -477,6 +477,13 @@ class VerilogGenerator : public VerilogGeneratorBase { void ExportIla(const InstrLvlAbsPtr& ila_ptr_); /// Parse an instruction void ExportTopLevelInstr(const InstrPtr& instr_ptr_); + + /// for VerilogVerificationTargetGen + // get valid signal name in advace + std::string GetValidSignalName(const InstrPtr& instr_ptr_) const; + // get decode signal name in advace + std::string GetDecodeSignalName(const InstrPtr& instr_ptr_) const; + }; // class VerilogGenerator }; // namespace ilang diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index a6606f32d..5ecedd6aa 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -165,9 +165,16 @@ class VlgSglTgtGen { std::string ReplExpr(const rfmap::RfExpr & in); /// treat `in` as var map, if it is not a Boolean, add `==` std::string TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn); - /// handle a single string map (s-name/equ-string) - std::string PerStateMap(const std::string& ila_state_name_or_equ, - const std::string& vlg_st_name); + + /// translate a conditional map to vlg expression + std::string condition_map_to_str( + const std::vector> & cond_map, + const std::string & ila_state_name); + + std::string non_mem_map_to_str( + const rfmap::SingleVarMap & single_map, + const std::string & ila_state_name); + /// handle a var map void Gen_varmap_assumpt_assert(const std::string& ila_state_name, const rfmap::IlaVarMapping &vmap, const std::string & problem_name, bool true_for_assumpt_false_for_assert, @@ -290,10 +297,21 @@ class VlgSglTgtGen { protected: // helper function to be implemented by COSA/JASPER /// Add an assumption -- backend dependent - virtual void add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) = 0; + virtual void add_a_direct_assumption(const std::string& aspt, + const std::string& dspt) = 0; /// Add an assertion - virtual void add_a_direct_assertion(const std::string& asst, + virtual void add_a_direct_assertion(const std::string& aspt, + const std::string& dspt) = 0; + + /// Add SMT-lib2 assumption + virtual void add_a_direct_smt_assumption(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) = 0; + /// Add SMT-lib2 assertion + virtual void add_a_direct_smt_assertion(const std::string& arg, + const std::string& ret, + const std::string& body, const std::string& dspt) = 0; // helper function to be implemented by COSA, Yosys, invsyn, jasper is not @@ -304,6 +322,18 @@ class VlgSglTgtGen { virtual void add_an_assertion(const std::string& asst, const std::string& dspt); + // Add SMT assumption (using rfexpr) + virtual void add_smt_assumption( + const std::unordered_map & vars, + const rfmap::RfExpr & body, + const std::string & dspt); + + // Add SMT assertion (using rfexpr) + virtual void add_smt_assertion( + const std::unordered_map & vars, + const rfmap::RfExpr & body, + const std::string & dspt); + /// Add an assignment which in JasperGold could be an assignment, but in CoSA /// has to be an assumption virtual void add_wire_assign_assumption(const std::string& varname, diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc index 582028932..18a78963c 100644 --- a/src/rfmap-in/rfexpr_to_smt.cc +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -12,6 +12,15 @@ namespace ilang { namespace rfmap { +std::string SmtType::type_to_smt2() const { + if(is_bool()) + return "Bool"; + if(is_bv()) + return "(_ BitVec "+std::to_string(unified_width())+")"; + ILA_ERROR_IF(!is_array()) << "Does not know how to translate unknown type"; + return "(Array (_ BitVec " +std::to_string(addr_width)+") (_ BitVec " + std::to_string(data_width)+"))"; +} + static std::vector voperator_str_smt = { "bvmul", // STAR "bvadd", diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index e4fa2b6b3..f611b2c91 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -6,6 +6,7 @@ #include #include +#include #include namespace ilang { @@ -19,28 +20,37 @@ std::string TypedVerilogRefinementMap::new_id() { TypedVerilogRefinementMap::TypedVerilogRefinementMap( const VerilogRefinementMap & refinement, - var_typecheck_t type_checker + var_typecheck_t type_checker, + const std::string & ila_inst_decode_signal_name, + const std::string & ila_valid_signal_name ) : VerilogRefinementMap(refinement), counter(0), TypeAnalysisUtility(type_checker) { - initialize(); + initialize(ila_inst_decode_signal_name,ila_valid_signal_name); } TypedVerilogRefinementMap::TypedVerilogRefinementMap( const std::string & varmap_json_file, const std::string & instcond_json_file, - var_typecheck_t type_checker + var_typecheck_t type_checker, + const std::string & ila_inst_decode_signal_name, + const std::string & ila_valid_signal_name ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), counter(0), TypeAnalysisUtility(type_checker) { - initialize(); + initialize(ila_inst_decode_signal_name,ila_valid_signal_name); } // TypedVerilogRefinementMap::TypedVerilogRefinementMap -void TypedVerilogRefinementMap::initialize() { +void TypedVerilogRefinementMap::initialize( + const std::string & ila_inst_decode_signal_name, + const std::string & ila_valid_signal_name) { // collect those with unknown types // a. delay // b. value holder CollectInlineDelayValueHolder(); // collect those new vars with user-defined types - CollectInternallyDefinedVars(); + CollectInternallyDefinedVars( + ila_inst_decode_signal_name, + ila_valid_signal_name + ); // determine the types of delay and value holder ComputeDelayValueHolderWidth(); @@ -91,6 +101,7 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( } // put back the annotation? in new expr? } // end if it is unknown + ILA_WARN_IF(tp.type.is_unknown()) << "type of var: " << (n.second?"#":"") << n.first << " is still unknown."; if(tp.var_ref_type == RfVarTypeOrig::VARTYPE::RTLV) { @@ -252,7 +263,10 @@ void TypedVerilogRefinementMap::CollectInlineDelayValueHolder() { } -void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { +void TypedVerilogRefinementMap::CollectInternallyDefinedVars( + const std::string & ila_inst_decode_signal_name, + const std::string & ila_valid_signal_name +) { for (const auto & n_st : phase_tracker) { for (const auto & var_def : n_st.second.event_alias ) { VarDef tmp; @@ -280,11 +294,15 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { } // add internal signals - { + { // add decode,commit, $decode, $valid VarDef tmp; tmp.width = 1; tmp.type = VarDef::var_type::WIRE; - all_var_def_types.emplace("decode", tmp); + auto onebit_anno = std::make_shared(); + onebit_anno->type = RfMapVarType(1); + onebit_anno->var_ref_type = RfVarTypeOrig::VARTYPE::INTERNAL; + + all_var_def_types.emplace("decode", tmp); // these are the stage info all_var_def_types.emplace("commit", tmp); // decode and commit stage replacement @@ -293,12 +311,36 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { verilog_expr::VExprAst::MakeSpecialName("decode"), verilog_expr::VExprAst::MakeSpecialName("__START__") )); + var_replacement.emplace("commit", VarReplacement( verilog_expr::VExprAst::MakeSpecialName("commit"), verilog_expr::VExprAst::MakeSpecialName("__IEND__") )); - } + + var_replacement.at("decode").newvar->set_annotation(onebit_anno); + var_replacement.at("commit").newvar->set_annotation(onebit_anno); + + all_var_def_types.emplace("$decode", tmp); // these are the ila.decode/ila.valid info + all_var_def_types.emplace("$valid", tmp); + + + // decode and commit stage replacement + var_replacement.emplace("$decode", + VarReplacement( + verilog_expr::VExprAst::MakeSpecialName("$decode"), + verilog_expr::VExprAst::MakeSpecialName(ila_inst_decode_signal_name) + )); + var_replacement.emplace("$valid", + VarReplacement( + verilog_expr::VExprAst::MakeSpecialName("commit"), + verilog_expr::VExprAst::MakeSpecialName(ila_valid_signal_name) + )); + + var_replacement.at("$decode").newvar->set_annotation(onebit_anno); + var_replacement.at("$valid").newvar->set_annotation(onebit_anno); + + } // end of add decode,commit, $decode, $valid } // CollectInternallyDefinedVars @@ -433,26 +475,7 @@ bool _compute_const(const RfExpr & in, unsigned & out) { return true; } -bool TypedVerilogRefinementMap::IsLastLevelBooleanOp(const RfExpr & in) { - std::set boolean_op = { - verilog_expr::voperator::GTE, - verilog_expr::voperator::LTE, - verilog_expr::voperator::GT, - verilog_expr::voperator::LT, - verilog_expr::voperator::C_EQ, - verilog_expr::voperator::L_EQ, - verilog_expr::voperator::C_NEQ, - verilog_expr::voperator::L_NEQ, - verilog_expr::voperator::L_NEG, - verilog_expr::voperator::L_AND, - verilog_expr::voperator::L_OR - }; - if(in->is_constant() || in->is_var()) - return false; - auto op = in->get_op(); - return (boolean_op.find(op) == boolean_op.end()); -} void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { for(auto & name_delay_pair: aux_delays) { @@ -487,9 +510,221 @@ void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { } // replendish internal defined vars } // ComputeDelayValueHolderWidth -// ------------------------------------------------------------------ -// type inference rules +RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in) { + + if(in->is_constant()) { + auto c = std::dynamic_pointer_cast(in)->get_constant(); + return RfMapVarType(std::get<1>(c)); + } else if (in->is_var()) { + auto n = std::dynamic_pointer_cast(in)->get_name(); + + auto pos_def_var = all_var_def_types.find(n.first); + + if(n.second) { // is a special name + // check special name first + if (pos_def_var != all_var_def_types.end()) + return RfMapVarType(pos_def_var->second.width); + + RfVarTypeOrig rtl_ila_vartype = typechecker(n.first); + if (!rtl_ila_vartype.type.is_unknown()) + return rtl_ila_vartype.type; + // then rtl ila name + } else { + // check rtl ila name first + // then special name + RfVarTypeOrig rtl_ila_vartype = typechecker(n.first); + if (!rtl_ila_vartype.type.is_unknown()) + return rtl_ila_vartype.type; + if (pos_def_var != all_var_def_types.end()) + return RfMapVarType(pos_def_var->second.width); + + } // if # ... # else not + return RfMapVarType(); // unknown type + } else { // has op + if(in->get_op() == verilog_expr::voperator::STAR || + in->get_op() == verilog_expr::voperator::PLUS || + in->get_op() == verilog_expr::voperator::MINUS || + in->get_op() == verilog_expr::voperator::DIV || + in->get_op() == verilog_expr::voperator::POW || + in->get_op() == verilog_expr::voperator::MOD || + in->get_op() == verilog_expr::voperator::B_NEG || + in->get_op() == verilog_expr::voperator::B_AND || + in->get_op() == verilog_expr::voperator::B_OR || + in->get_op() == verilog_expr::voperator::B_XOR || + in->get_op() == verilog_expr::voperator::B_NAND || + in->get_op() == verilog_expr::voperator::B_NOR + ) { + // the max of the args + unsigned nchild = in->get_child_cnt(); + unsigned maxw = 0; + for(size_t idx = 0; idx < nchild; idx ++) { + RfMapVarType t = TypeInferTravserRfExpr( in->child(idx) ); + if(t.is_bv()) + maxw = std::max(maxw, t.unified_width()); + } + return RfMapVarType(maxw); + } else if ( + in->get_op() == verilog_expr::voperator::ASL || + in->get_op() == verilog_expr::voperator::ASR || + in->get_op() == verilog_expr::voperator::LSL || + in->get_op() == verilog_expr::voperator::LSR || + in->get_op() == verilog_expr::voperator::AT + ) { // the left type + assert( in->get_child_cnt() == 2); + return TypeInferTravserRfExpr(in->child(0)); + } else if ( in->get_op() == verilog_expr::voperator::DELAY) { + // arg 1: width of first + // arg 2: width is 1 !!! + assert(in->get_child_cnt() == 1 || in->get_child_cnt() == 2); + if (in->get_child_cnt() == 2) + return RfMapVarType(1); + + // set return type to be the same as the first one + return TypeInferTravserRfExpr(in->child(0)); + } else if ( + in->get_op() == verilog_expr::voperator::GTE || + in->get_op() == verilog_expr::voperator::LTE || + in->get_op() == verilog_expr::voperator::GT || + in->get_op() == verilog_expr::voperator::LT || + in->get_op() == verilog_expr::voperator::C_EQ || + in->get_op() == verilog_expr::voperator::L_EQ || + in->get_op() == verilog_expr::voperator::C_NEQ || + in->get_op() == verilog_expr::voperator::L_NEQ || + in->get_op() == verilog_expr::voperator::L_NEG || + in->get_op() == verilog_expr::voperator::L_AND || + in->get_op() == verilog_expr::voperator::L_OR + ) { + return RfMapVarType(1); + } else if (in->get_op() == verilog_expr::voperator::INDEX) { + RfMapVarType child_type = TypeInferTravserRfExpr(in->child(0)); + if (child_type.is_array()) + return RfMapVarType(child_type.unified_width()); // data width + // TODO: check index within ? + if (child_type.is_bv()) + return RfMapVarType(1); + return RfMapVarType(); // UNKNOWN type + } else if ( + in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || + in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { + assert(in->get_child().size() == 3); + unsigned diff; + bool succ = _compute_const(in->child(2), diff /*ref*/); + // TODO: check index within ? + if (succ) + return RfMapVarType(diff); + return RfMapVarType(); + } else if (in->get_op() == verilog_expr::voperator::RANGE_INDEX) { + assert(in->get_child_cnt() == 3); + unsigned l,r; + + bool succ = _compute_const(in->child(1), l /*ref*/), + succ = succ && _compute_const(in->child(2), r /*ref*/); + if(!succ) + return RfMapVarType(); + // TODO: check width! + return RfMapVarType(std::max(l,r)-std::min(l,r) + 1); + } else if (in->get_op() == verilog_expr::voperator::STORE_OP) { + // TODO: check width! + // actually not implemented + return TypeInferTravserRfExpr(in->child(0)); + } else if (in->get_op() == verilog_expr::voperator::TERNARY) { + auto left = TypeInferTravserRfExpr(in->child(1)); + auto right = TypeInferTravserRfExpr(in->child(2)); + if(left.is_array() || right.is_array()) + return left; // TODO: check compatibility + return RfMapVarType(std::max(left.unified_width(), right.unified_width())); + } else if (in->get_op() == verilog_expr::voperator::FUNCTION_APP) { + return RfMapVarType(); + } else if(in->get_op() == verilog_expr::voperator::CONCAT) { + unsigned nchild = in->get_child_cnt(); + unsigned sumw = 0; + for(size_t idx = 0; idx < nchild; idx ++) { + RfMapVarType t = TypeInferTravserRfExpr( in->child(idx) ); + if(t.is_bv()) + sumw += t.unified_width(); + else + return RfMapVarType(); // cannot decide + } + return RfMapVarType(sumw); + } else if (in->get_op() == verilog_expr::voperator::REPEAT) { + assert( in->get_child_cnt() == 2 ); + unsigned ntimes; + if(!_compute_const(in->child(0), ntimes)) + return RfMapVarType(); + auto tp = TypeInferTravserRfExpr(in->child(1)); + return RfMapVarType(tp.unified_width()*ntimes); + } + ILA_ASSERT(false) << "BUG: Operator " << int(in->get_op()) << " is not handled"; + } // end of else has op + return RfMapVarType(); +} // TypeInferTravserRfExpr + + +// -------------------------------------------------------- +// RfExprAstUtility +// -------------------------------------------------------- + + +RfVarTypeOrig RfExprAstUtility::GetType(const RfExpr & in) { + auto anno = in->get_annotation(); + ILA_NOT_NULL(anno); + return *anno; +} + +void RfExprAstUtility::GetVars(const RfExpr & in, + std::unordered_map & vars_out) +{ + // bfs walk + std::vector > stack; + stack.push_back(std::make_pair(in, false)); + while(!stack.empty()) { + auto & back = stack.back(); + if(back.second) { + stack.pop_back(); + continue; + } + // back.second == false + back.second = true; + for(const auto & c : back.first->get_child()) + stack.push_back(std::make_pair(c, false)); + if(back.first->is_var()) { + ILA_ASSERT(back.first->get_child().size() == 0); + verilog_expr::VExprAstVar::VExprAstVarPtr varptr = + std::dynamic_pointer_cast(back.first); + ILA_NOT_NULL(varptr); + vars_out.emplace(varptr->get_name().first, varptr); + } + } // end while (stack is not empty) +} // end of GetVars + +bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr & in) { + std::set boolean_op = { + verilog_expr::voperator::GTE, + verilog_expr::voperator::LTE, + verilog_expr::voperator::GT, + verilog_expr::voperator::LT, + verilog_expr::voperator::C_EQ, + verilog_expr::voperator::L_EQ, + verilog_expr::voperator::C_NEQ, + verilog_expr::voperator::L_NEQ, + verilog_expr::voperator::L_NEG, + verilog_expr::voperator::L_AND, + verilog_expr::voperator::L_OR + }; + + if(in->is_constant() || in->is_var()) + return false; + auto op = in->get_op(); + return (boolean_op.find(op) == boolean_op.end()); +} + + +// -------------------------------------------------------- +// TypeAnalysisUtility +// -------------------------------------------------------- + +// type inference rules // differences from TypedVerilogRefinementMap::ReplacingRtlIlaVar // 1. no var replacement (__ILA_I_, __ILA_SO_, __DOT__), array[idx] // 2. no special name handling @@ -678,155 +913,6 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr & inout) { inout->set_annotation(new_annotation); } // infer_type_op -RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in) { - - if(in->is_constant()) { - auto c = std::dynamic_pointer_cast(in)->get_constant(); - return RfMapVarType(std::get<1>(c)); - } else if (in->is_var()) { - auto n = std::dynamic_pointer_cast(in)->get_name(); - - auto pos_def_var = all_var_def_types.find(n.first); - - if(n.second) { // is a special name - // check special name first - if (pos_def_var != all_var_def_types.end()) - return RfMapVarType(pos_def_var->second.width); - - RfVarTypeOrig rtl_ila_vartype = typechecker(n.first); - if (!rtl_ila_vartype.type.is_unknown()) - return rtl_ila_vartype.type; - // then rtl ila name - } else { - // check rtl ila name first - // then special name - RfVarTypeOrig rtl_ila_vartype = typechecker(n.first); - if (!rtl_ila_vartype.type.is_unknown()) - return rtl_ila_vartype.type; - if (pos_def_var != all_var_def_types.end()) - return RfMapVarType(pos_def_var->second.width); - - } // if # ... # else not - return RfMapVarType(); // unknown type - } else { // has op - if(in->get_op() == verilog_expr::voperator::STAR || - in->get_op() == verilog_expr::voperator::PLUS || - in->get_op() == verilog_expr::voperator::MINUS || - in->get_op() == verilog_expr::voperator::DIV || - in->get_op() == verilog_expr::voperator::POW || - in->get_op() == verilog_expr::voperator::MOD || - in->get_op() == verilog_expr::voperator::B_NEG || - in->get_op() == verilog_expr::voperator::B_AND || - in->get_op() == verilog_expr::voperator::B_OR || - in->get_op() == verilog_expr::voperator::B_XOR || - in->get_op() == verilog_expr::voperator::B_NAND || - in->get_op() == verilog_expr::voperator::B_NOR - ) { - // the max of the args - unsigned nchild = in->get_child_cnt(); - unsigned maxw = 0; - for(size_t idx = 0; idx < nchild; idx ++) { - RfMapVarType t = TypeInferTravserRfExpr( in->child(idx) ); - if(t.is_bv()) - maxw = std::max(maxw, t.unified_width()); - } - return RfMapVarType(maxw); - } else if ( - in->get_op() == verilog_expr::voperator::ASL || - in->get_op() == verilog_expr::voperator::ASR || - in->get_op() == verilog_expr::voperator::LSL || - in->get_op() == verilog_expr::voperator::LSR || - in->get_op() == verilog_expr::voperator::AT - ) { // the left type - assert( in->get_child_cnt() == 2); - return TypeInferTravserRfExpr(in->child(0)); - } else if ( in->get_op() == verilog_expr::voperator::DELAY) { - // arg 1: width of first - // arg 2: width is 1 !!! - assert(in->get_child_cnt() == 1 || in->get_child_cnt() == 2); - if (in->get_child_cnt() == 2) - return RfMapVarType(1); - - // set return type to be the same as the first one - return TypeInferTravserRfExpr(in->child(0)); - } else if ( - in->get_op() == verilog_expr::voperator::GTE || - in->get_op() == verilog_expr::voperator::LTE || - in->get_op() == verilog_expr::voperator::GT || - in->get_op() == verilog_expr::voperator::LT || - in->get_op() == verilog_expr::voperator::C_EQ || - in->get_op() == verilog_expr::voperator::L_EQ || - in->get_op() == verilog_expr::voperator::C_NEQ || - in->get_op() == verilog_expr::voperator::L_NEQ || - in->get_op() == verilog_expr::voperator::L_NEG || - in->get_op() == verilog_expr::voperator::L_AND || - in->get_op() == verilog_expr::voperator::L_OR - ) { - return RfMapVarType(1); - } else if (in->get_op() == verilog_expr::voperator::INDEX) { - RfMapVarType child_type = TypeInferTravserRfExpr(in->child(0)); - if (child_type.is_array()) - return RfMapVarType(child_type.unified_width()); // data width - // TODO: check index within ? - if (child_type.is_bv()) - return RfMapVarType(1); - return RfMapVarType(); // UNKNOWN type - } else if ( - in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || - in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { - assert(in->get_child().size() == 3); - unsigned diff; - bool succ = _compute_const(in->child(2), diff /*ref*/); - // TODO: check index within ? - if (succ) - return RfMapVarType(diff); - return RfMapVarType(); - } else if (in->get_op() == verilog_expr::voperator::RANGE_INDEX) { - assert(in->get_child_cnt() == 3); - unsigned l,r; - - bool succ = _compute_const(in->child(1), l /*ref*/), - succ = succ && _compute_const(in->child(2), r /*ref*/); - if(!succ) - return RfMapVarType(); - // TODO: check width! - return RfMapVarType(std::max(l,r)-std::min(l,r) + 1); - } else if (in->get_op() == verilog_expr::voperator::STORE_OP) { - // TODO: check width! - // actually not implemented - return TypeInferTravserRfExpr(in->child(0)); - } else if (in->get_op() == verilog_expr::voperator::TERNARY) { - auto left = TypeInferTravserRfExpr(in->child(1)); - auto right = TypeInferTravserRfExpr(in->child(2)); - if(left.is_array() || right.is_array()) - return left; // TODO: check compatibility - return RfMapVarType(std::max(left.unified_width(), right.unified_width())); - } else if (in->get_op() == verilog_expr::voperator::FUNCTION_APP) { - return RfMapVarType(); - } else if(in->get_op() == verilog_expr::voperator::CONCAT) { - unsigned nchild = in->get_child_cnt(); - unsigned sumw = 0; - for(size_t idx = 0; idx < nchild; idx ++) { - RfMapVarType t = TypeInferTravserRfExpr( in->child(idx) ); - if(t.is_bv()) - sumw += t.unified_width(); - else - return RfMapVarType(); // cannot decide - } - return RfMapVarType(sumw); - } else if (in->get_op() == verilog_expr::voperator::REPEAT) { - assert( in->get_child_cnt() == 2 ); - unsigned ntimes; - if(!_compute_const(in->child(0), ntimes)) - return RfMapVarType(); - auto tp = TypeInferTravserRfExpr(in->child(1)); - return RfMapVarType(tp.unified_width()*ntimes); - } - ILA_ASSERT(false) << "BUG: Operator " << int(in->get_op()) << " is not handled"; - } // end of else has op - return RfMapVarType(); -} // TypeInferTravserRfExpr - } // namespace rfmap } // namespace ilang diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 79da8a875..dd816c333 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -141,7 +141,14 @@ bool JsonRfmapParseMem(ExternalMemPortMap & mem_rfmap , nlohmann::json & json_ob if (json_obj.contains("rdata")) succ = succ && JsonRfmapParseCond(mem_rfmap.rdata_map, json_obj["rdata"]); - return (succ && json_obj.contains("ren") && json_obj.contains("wen")); + mem_rfmap.rport_mapped = json_obj.contains("ren"); + mem_rfmap.wport_mapped = json_obj.contains("wen"); + if(mem_rfmap.rport_mapped) + succ = succ && json_obj.contains("raddr") && json_obj.contains("rdata"); + if(mem_rfmap.wport_mapped) + succ = succ && json_obj.contains("waddr") && json_obj.contains("wdata"); + + return (succ && (json_obj.contains("ren") || json_obj.contains("wen"))); } // JsonRfmapParseMem char inline to_space(char in) { return ( (in == '-' || in == '_') ? ' ' : in); } diff --git a/src/verilog-out/verilog_gen.cc b/src/verilog-out/verilog_gen.cc index e56b90c35..d08894462 100644 --- a/src/verilog-out/verilog_gen.cc +++ b/src/verilog-out/verilog_gen.cc @@ -1301,6 +1301,23 @@ void VerilogGenerator::ExportIla(const InstrLvlAbsPtr& ila_ptr_) { ExportFuncDefs(); } + +// get valid signal name in advace +std::string VerilogGenerator::GetValidSignalName(const InstrPtr& instr_ptr_) const { + + auto ila_ptr_ = instr_ptr_->host(); + return "__ILA_" + sanitizeName(ila_ptr_->name().str()) + "_valid__"; +} + +// get decode signal name in advace +std::string VerilogGenerator::GetDecodeSignalName(const InstrPtr& instr_ptr_) const { + + auto ila_ptr_ = instr_ptr_->host(); + return "__ILA_" + sanitizeName(ila_ptr_->name().str()) + + "_decode_of_" + sanitizeName(instr_ptr_->name().str()) + + "__"; +} + // here we will add all updates, those not touched will be update to itself // add inputs / states / functions // do remember to export its parents' state (hierarchically collect its parents) @@ -1341,7 +1358,7 @@ void VerilogGenerator::ExportTopLevelInstr(const InstrPtr& instr_ptr_) { ParseNonMemUpdateExpr(valid_ptr); vlg_name_t valid_sig_name = getVlgFromExpr(valid_ptr); if (validName == "") - validName = "__ILA_" + sanitizeName(ila_ptr_->name().str()) + "_valid__"; + validName = GetValidSignalName(instr_ptr_); add_wire(validName, 1); add_output(validName, 1); add_assign_stmt(validName, valid_sig_name); @@ -1354,9 +1371,7 @@ void VerilogGenerator::ExportTopLevelInstr(const InstrPtr& instr_ptr_) { } ParseNonMemUpdateExpr(decode_ptr); vlg_name_t decode_sig_name = getVlgFromExpr(decode_ptr); - auto decodeName = "__ILA_" + sanitizeName(ila_ptr_->name().str()) + - "_decode_of_" + sanitizeName(instr_ptr_->name().str()) + - "__"; + auto decodeName = GetDecodeSignalName(instr_ptr_); decodeNames.push_back(decodeName); add_wire(decodeName, 1); add_output(decodeName, 1); diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 8fc6f4ec6..a85f08661 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -170,9 +170,42 @@ std::string VlgSglTgtGen::TranslateMap(const rfmap::RfExpr & in, const std::stri return ReplExpr(eq_node); } +std::string VlgSglTgtGen::condition_map_to_str( + const std::vector> & cond_map, + const std::string & ila_state_name) +{ + std::vector all_mappings; + std::string prev_neg; // make sure it is a priority condition lists + for (const auto & cond_map_pair : cond_map) { + std::string cond_expr = ReplExpr(cond_map_pair.first); + std::string vmap_expr = TranslateMap(cond_map_pair.second, ila_state_name); + + all_mappings.push_back("~ (" + prev_neg + "(" + cond_expr + ") ) || (" + + vmap_expr + ")"); + prev_neg += "~(" + cond_expr + ")&&"; + } // end for each condition map item + ILA_ERROR_IF(all_mappings.empty()) << "Conditional map is empty!"; + auto map_str = "(" + Join(all_mappings, " )&&( ") + ")"; + return map_str; +} // end of condition_map_to_str + +std::string VlgSglTgtGen::non_mem_map_to_str( + const rfmap::SingleVarMap & single_map, + const std::string & ila_state_name) +{ + if(single_map.single_map != nullptr) { + return (TranslateMap(single_map.single_map, ila_state_name)); + } else { + auto map_str = condition_map_to_str( single_map.cond_map, ila_state_name); + return (map_str); + } // end map type +} // non_mem_map_to_str + void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, const rfmap::IlaVarMapping &vmap, const std::string & problem_name, bool true_for_assumpt_false_for_assert, const std::string & prefix, const std::string & suffix) { + // NOTE: prefix has ( ~ __START__ || ... + // and suffix has .. ) #define ADD_CONSTR(p1) do{ \ if(true_for_assumpt_false_for_assert) \ @@ -185,23 +218,8 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, if(!is_mem) { ILA_ERROR_IF(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) << "ila sv " << ila_state_name << " is not memory!"; - if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::SINGLE) { - ADD_CONSTR(TranslateMap(vmap.single_map.single_map, ila_state_name)); - } else if (vmap.type == rfmap::IlaVarMapping::StateVarMapType::CONDITIONAL) { - std::vector all_mappings; - std::string prev_neg; // make sure it is a priority condition lists - for (const auto & cond_map_pair : vmap.single_map.cond_map) { - std::string cond_expr = ReplExpr(cond_map_pair.first); - std::string vmap_expr = TranslateMap(cond_map_pair.second, ila_state_name); - - all_mappings.push_back("~ (" + prev_neg + "(" + cond_expr + ") ) || (" + - vmap_expr + ")"); - prev_neg += "~(" + cond_expr + ")&&"; - } // end for each condition map item - ILA_ERROR_IF(all_mappings.empty()) << "Conditional map is empty!"; - auto map_str = "(" + Join(all_mappings, " )&&( ") + ")"; - ADD_CONSTR(map_str); - } // end map type + auto map_str = non_mem_map_to_str(vmap.single_map, ila_state_name); + ADD_CONSTR(map_str); } else { if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { // TODO: (note: multiple ports!) @@ -209,17 +227,83 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, // ( ila.ren && rtl.renexpr && (ila.raddr == rtl.raddrexpr) |-> // (ila.rdata === rtl.rdataexpr) ) - // assert : IEND |-> - // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> - // (ila.wdata_d1 == rtl.wdataexpr) && (ila.waddr_d1 == rtl.waddrexpr) ) ) + if(true_for_assumpt_false_for_assert) { + // mem read assumption + const auto & read_ports = vlg_ila.ila_rports.at(ila_state_name); + unsigned rfmap_node_idx = 0; + + for(const auto & rport : read_ports) { + const auto & ila_ren = rport.second.ren; + const auto & ila_raddr = rport.second.raddr; + const auto & ila_rdata = rport.second.rdata; + + while(!(vmap.externmem_map.at(rfmap_node_idx).rport_mapped) + && rfmap_node_idx < vmap.externmem_map.size()) + ++ rfmap_node_idx; + + ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) + <<"#ila.read-port=" << read_ports.size() << " does not match #rfmap.read-port" + <<", and this is a mismatch for sname:" << ila_state_name; + + const auto & rfmap_rport = vmap.externmem_map.at(rfmap_node_idx); + + auto rtl_ren = non_mem_map_to_str(rfmap_rport.ren_map, ila_state_name); + auto rtl_raddr = non_mem_map_to_str(rfmap_rport.raddr_map, ila_state_name); + auto rtl_rdata = non_mem_map_to_str(rfmap_rport.rdata_map, ila_state_name); + + auto constr = "~(" + ila_ren + "&&(" + rtl_ren + ")&&(" + ila_raddr + "==(" + rtl_raddr +"))) || "; + constr += "(" + ila_rdata + "==(" + rtl_rdata+"))"; + ADD_CONSTR(constr); + + ++ rfmap_node_idx; + + } // for each read port - #error "connect according to the above" - } // same for jg/non-jg - else { + } else { + // assert : IEND |-> + // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> + // (ila.wdata_d1 == rtl.wdataexpr) && (ila.waddr_d1 == rtl.waddrexpr) ) ) + + // mem write assertion + // vlg_ila.ila_wports + const auto & write_ports = vlg_ila.ila_wports.at(ila_state_name); + unsigned rfmap_node_idx = 0; + + for(const auto & wport : write_ports) { + // the reason for _d1: see ConstructWrapper_get_ila_module_inst + // in single_target_connect.cc + const auto & ila_wen = wport.second.wen + "_d1"; + const auto & ila_waddr = wport.second.waddr + "_d1"; + const auto & ila_wdata = wport.second.wdata + "_d1"; + + while(!(vmap.externmem_map.at(rfmap_node_idx).wport_mapped) + && rfmap_node_idx < vmap.externmem_map.size()) + ++ rfmap_node_idx; + + ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) + <<"#ila.write-port=" << write_ports.size() << " does not match #rfmap.write-port" + <<", and this is a mismatch for sname:" << ila_state_name; + + const auto & rfmap_wport = vmap.externmem_map.at(rfmap_node_idx); + + auto rtl_wen = non_mem_map_to_str(rfmap_wport.wen_map, ila_state_name); + auto rtl_waddr = non_mem_map_to_str(rfmap_wport.waddr_map, ila_state_name); + auto rtl_wdata = non_mem_map_to_str(rfmap_wport.wdata_map, ila_state_name); + + auto constr = "("+ila_wen + "==(" + rtl_wen+")) &&( ~" + ila_wen + +"||(" + ila_waddr +"==("+rtl_waddr+") && " +ila_wdata +"==("+ rtl_wdata +")" +"))"; + ADD_CONSTR(constr); + + ++ rfmap_node_idx; + } // for each write port + } // end of if assume else assert + } // end of extern mem + else { // the case when internal mem bool is_jg = _backend == backend_selector::JASPERGOLD; bool is_pono = _backend == backend_selector::PONO; if(is_jg) { // same as non-mem var + if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::SINGLE) { ADD_CONSTR(TranslateMap(vmap.single_map.single_map, ila_state_name)); } else if (vmap.type == rfmap::IlaVarMapping::StateVarMapType::CONDITIONAL) { @@ -237,12 +321,63 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, auto map_str = "(" + Join(all_mappings, " )&&( ") + ")"; ADD_CONSTR(map_str); } // end map type - } else { - //TODO: to smt-lib2 - ILA_CHECK(is_pono) << "Only PONO/JG backend can handle array eq property"; - - #error "to smtlib2, need ReplacingRtlIlaVar first which will infer type" + } else { + //TODO: to smt-lib2 + ILA_CHECK(is_pono) << "Only PONO/JG backend can handle array eq property"; + + rfmap::RfExpr mem_map; + if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::SINGLE) + mem_map = vmap.single_map.single_map; + else { + std::vector all_mappings; + rfmap::RfExpr prev_neg; // make sure it is a priority condition lists + for (const auto & cond_map_pair : vmap.single_map.cond_map) { + rfmap::RfExpr cond = cond_map_pair.first; + if (prev_neg != nullptr) + cond = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, prev_neg, cond); + rfmap::RfExpr single_mem_map = refinement_map.IsLastLevelBooleanOp(cond_map_pair.second) ? + cond_map_pair.second : ( + verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, + cond_map_pair.second, + verilog_expr::VExprAst::MakeVar("ILA."+ila_state_name)) + ); + all_mappings.push_back( + verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_OR, + verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, cond), + single_mem_map)); + if (prev_neg == nullptr) + prev_neg = verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, cond); + else + prev_neg = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, prev_neg, + verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, cond)); + } // end of for each cond_map pair + ILA_CHECK(!all_mappings.empty()); + mem_map = all_mappings.at(0); + for (size_t idx = 1; idx < all_mappings.size(); ++ idx) + mem_map = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, + mem_map, all_mappings.at(idx)); + } // end of else (if condmap) + + rfmap::RfExpr start_or_end = true_for_assumpt_false_for_assert ? + verilog_expr::VExprAst::MakeSpecialName("decode") : + verilog_expr::VExprAst::MakeSpecialName("commit"); + + mem_map = /* ~start_or_end || (mem_map) */ + verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_OR, + verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, start_or_end), + mem_map); + + auto var_replaced_mem_map = refinement_map.ReplacingRtlIlaVar(mem_map, is_pono /*true*/); + // get var/type + // convert to smt-lib2 + std::unordered_map vars_in_map; + refinement_map.GetVars(var_replaced_mem_map, vars_in_map); + + if(true_for_assumpt_false_for_assert) + add_smt_assumption(vars_in_map, mem_map, problem_name); + else + add_smt_assertion(vars_in_map, mem_map, problem_name); } // end of is_jg / else } // end of is_extmem / else } // end for memory-case @@ -373,8 +508,8 @@ std::string VlgSglTgtGen::GetStateVarMapExpr(const std::string& ila_state_name, void VlgSglTgtGen::handle_start_condition(const std::vector & dc) { for (const auto & c : dc) { auto cond = ReplExpr(c); - cond = ReplaceAll(ReplaceAll(cond, "$decode", vlg_ila.decodeNames[0]), - "$valid", vlg_ila.validName); + //cond = ReplaceAll(ReplaceAll(cond, "$decode", vlg_ila.decodeNames[0]), + // "$valid", vlg_ila.validName); add_an_assumption("(~ __START__) || (" + cond +")", "start_condition"); } } // handle_start_condition diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index 103253c44..c06e7d20e 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -82,7 +82,9 @@ VlgSglTgtGen::VlgSglTgtGen( // [this](const std::string& n) -> bool { return TryFindIlaInput(n); }, // [this](const std::string& n) -> bool { return TryFindVlgState(n); }), // ref to refmaps - refinement_map(refinement, ??? ), + refinement_map(refinement, ??? /*type checker*/, + vlg_ila.GetDecodeSignalName(instr_ptr), + vlg_ila.GetValidSignalName(instr_ptr)), target_type(target_tp), // whether it is // invariant/instructions diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index da0091cc7..f91b04c08 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -15,6 +15,7 @@ #include #include #include +#include namespace ilang { @@ -24,12 +25,12 @@ void VlgSglTgtGen::add_wire_assign_assumption(const std::string& varname, //_problems.assumptions.push_back(varname + " = " + // convert_expr_to_cosa(expression)); vlg_wrapper.add_assign_stmt(varname, expression); - ILA_CHECK(_vtg_config.CosaDotReferenceNotify != - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_PANIC || + ILA_CHECK(_vtg_config.PonoDotReferenceNotify != + vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_PANIC || expression.find(".") == std::string::npos) << "expression:" << expression << " contains unfriendly dot."; - ILA_WARN_IF(_vtg_config.CosaDotReferenceNotify == - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_WARNING && + ILA_WARN_IF(_vtg_config.PonoDotReferenceNotify == + vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_WARNING && expression.find(".") != std::string::npos) << "expression:" << expression << " contains unfriendly dot."; } @@ -44,13 +45,13 @@ void VlgSglTgtGen::add_reg_cassign_assumption(const std::string& varname, // " ) | (" + varname + " = " + // convert_expr_to_cosa(expression) + "))"); - ILA_CHECK(_vtg_config.CosaDotReferenceNotify != - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_PANIC || + ILA_CHECK(_vtg_config.PonoDotReferenceNotify != + vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_PANIC || expression.find(".") == std::string::npos) << "expression:" << expression << " contains unfriendly dot."; - ILA_WARN_IF(_vtg_config.CosaDotReferenceNotify == - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_WARNING && + ILA_WARN_IF(_vtg_config.PonoDotReferenceNotify == + vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_WARNING && expression.find(".") != std::string::npos) << "expression:" << expression << " contains unfriendly dot."; @@ -75,20 +76,19 @@ void VlgSglTgtGen::add_an_assumption(const std::string& aspt, vlg_wrapper.add_output(assumption_wire_name, 1); // I find it is necessary to connect to the output - ILA_CHECK(_vtg_config.CosaDotReferenceNotify != - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_PANIC || + ILA_CHECK(_vtg_config.PonoDotReferenceNotify != + vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_PANIC || aspt.find(".") == std::string::npos) << "aspt:" << aspt << " contains unfriendly dot."; - ILA_WARN_IF(_vtg_config.CosaDotReferenceNotify == - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_WARNING && + ILA_WARN_IF(_vtg_config.PonoDotReferenceNotify == + vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_WARNING && aspt.find(".") != std::string::npos) << "aspt:" << aspt << " contains unfriendly dot."; vlg_wrapper.add_assign_stmt(assumption_wire_name, aspt); add_a_direct_assumption( - assumption_wire_name + - (_backend == backend_selector::COSA ? " = 1_1" : ""), + assumption_wire_name, dspt); } // add_an_assumption @@ -101,18 +101,57 @@ void VlgSglTgtGen::add_an_assertion(const std::string& asst, 1); // I find it is necessary to connect to the output vlg_wrapper.add_assign_stmt(assrt_wire_name, asst); add_a_direct_assertion( - assrt_wire_name + (_backend == backend_selector::COSA ? " = 1_1" : ""), + assrt_wire_name, dspt); - ILA_CHECK(_vtg_config.CosaDotReferenceNotify != - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_PANIC || + ILA_CHECK(_vtg_config.PonoDotReferenceNotify != + vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_PANIC || asst.find(".") == std::string::npos) << "asst:" << asst << " contains unfriendly dot."; - ILA_WARN_IF(_vtg_config.CosaDotReferenceNotify == - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_WARNING && + ILA_WARN_IF(_vtg_config.PonoDotReferenceNotify == + vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_WARNING && asst.find(".") != std::string::npos) << "asst:" << asst << " contains unfriendly dot."; //_problems.probitem[dspt].assertions.push_back(convert_expr_to_cosa(asst)); +} // add_an_assertion + + + +void VlgSglTgtGen::add_smt_assumption( + const std::unordered_map & vars, + const rfmap::RfExpr & body, + const std::string & dspt) +{ + std::string body_smt2 = + rfmap::RfExpr2Smt::to_smt2(body, rfmap::SmtType() /*Bool type*/ ); + std::vector arg; + for(const auto & n_expr_pair : vars) { + auto tp = refinement_map.GetType( n_expr_pair.second ); + auto smt_tp = rfmap::SmtType(tp.type, false); + const auto & n = n_expr_pair.first; + arg.push_back("("+n + " " + smt_tp.type_to_smt2() + ")"); + } + add_a_direct_smt_assumption( + "("+Join(arg, " ")+")", "Bool", body_smt2, dspt); +} + +// Add SMT assertion (using rfexpr) +void VlgSglTgtGen::add_smt_assertion( + const std::unordered_map & vars, + const rfmap::RfExpr & body, + const std::string & dspt) +{ + std::string body_smt2 = + rfmap::RfExpr2Smt::to_smt2(body, rfmap::SmtType() /*Bool type*/ ); + std::vector arg; + for(const auto & n_expr_pair : vars) { + auto tp = refinement_map.GetType( n_expr_pair.second ); + auto smt_tp = rfmap::SmtType(tp.type, false); + const auto & n = n_expr_pair.first; + arg.push_back("("+n + " " + smt_tp.type_to_smt2() + ")"); + } + add_a_direct_smt_assertion( + "("+Join(arg, " ")+")", "Bool", body_smt2, dspt); } }; // namespace ilang diff --git a/test/unit-data/vpipe/vmem/cond-rd.json b/test/unit-data/vpipe/vmem/cond-rd.json index aa5491a8c..4fecbea36 100644 --- a/test/unit-data/vpipe/vmem/cond-rd.json +++ b/test/unit-data/vpipe/vmem/cond-rd.json @@ -4,7 +4,7 @@ "instructions": [ { "instruction": "Rd", - "start condition":["m1.state == 0" , "$valid$", "$decode$" ], + "start condition":["m1.state == 0" , "$valid", "$decode" ], "ready bound": 2 } ] diff --git a/test/unit-data/vpipe/vmem/cond.json b/test/unit-data/vpipe/vmem/cond.json index 7bc670bb3..01feac63b 100644 --- a/test/unit-data/vpipe/vmem/cond.json +++ b/test/unit-data/vpipe/vmem/cond.json @@ -4,7 +4,7 @@ "instructions": [ { "instruction": "SWAP", - "start condition":["m1.state == 0" , "$valid$", "$decode$" ], + "start condition":["m1.state == 0" , "$valid", "$decode" ], "ready bound": 3 } ] From 01be7d435db6e863230ca9af87cbbc15f1e63d4d Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 20 Jul 2021 10:20:52 +0800 Subject: [PATCH 25/78] stage1 test --- include/ilang/vtarget-out/.gitignore | 2 + .../ilang/vtarget-out/inv-syn/inv_syn_cegar.h | 240 ---- .../vtarget-out/inv-syn/vtarget_gen_inv_abc.h | 179 --- .../vtarget-out/inv-syn/vtarget_gen_inv_chc.h | 174 --- .../inv-syn/vtarget_gen_inv_enhance.h | 187 --- include/ilang/vtarget-out/vtarget_gen.h | 50 +- include/ilang/vtarget-out/vtarget_gen_impl.h | 45 +- .../ilang/vtarget-out/vtarget_gen_jasper.h | 34 +- ...{vtarget_gen_cosa.h => vtarget_gen_pono.h} | 86 +- .../ilang/vtarget-out/vtarget_gen_relchc.h | 165 --- include/ilang/vtarget-out/vtarget_gen_yosys.h | 174 --- src/mcm/ast_helper.cc | 9 +- src/rfmap-in/rfmap_typecheck.cc | 11 +- src/rfmap-in/verilog_rfmap.cc | 18 +- src/vtarget-out/.gitignore | 2 +- src/vtarget-out/CMakeLists.txt | 4 +- src/vtarget-out/gen_util.cc | 167 +-- src/vtarget-out/inv-syn/CMakeLists.txt | 5 - src/vtarget-out/inv-syn/inv_syn_cegar.cc | 936 --------------- src/vtarget-out/inv-syn/rel_chc.cc | 610 ---------- .../inv-syn/vtarget_gen_inv_abc.cc | 575 --------- .../inv-syn/vtarget_gen_inv_chc.cc | 782 ------------- .../inv-syn/vtarget_gen_inv_enhance.cc | 680 ----------- src/vtarget-out/single_target.cc | 108 +- .../single_target_inv_syn_support.cc | 72 +- src/vtarget-out/single_target_misc.cc | 4 +- src/vtarget-out/vtarget_gen.cc | 15 +- src/vtarget-out/vtarget_gen_cosa.cc | 291 ----- src/vtarget-out/vtarget_gen_impl.cc | 222 +--- src/vtarget-out/vtarget_gen_jasper.cc | 69 +- src/vtarget-out/vtarget_gen_pono.cc | 295 +++++ src/vtarget-out/vtarget_gen_relchc.cc | 393 ------- src/vtarget-out/vtarget_gen_yosys.cc | 1030 ----------------- test/t_inv_extract.cc | 4 +- test/t_inv_obj.cc | 2 +- test/t_inv_syn.cc | 5 +- test/t_vtarget_gen.cc | 118 +- 37 files changed, 665 insertions(+), 7098 deletions(-) create mode 100644 include/ilang/vtarget-out/.gitignore delete mode 100644 include/ilang/vtarget-out/inv-syn/inv_syn_cegar.h delete mode 100644 include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_abc.h delete mode 100644 include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_chc.h delete mode 100644 include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_enhance.h rename include/ilang/vtarget-out/{vtarget_gen_cosa.h => vtarget_gen_pono.h} (62%) delete mode 100644 include/ilang/vtarget-out/vtarget_gen_relchc.h delete mode 100644 include/ilang/vtarget-out/vtarget_gen_yosys.h delete mode 100644 src/vtarget-out/inv-syn/inv_syn_cegar.cc delete mode 100644 src/vtarget-out/inv-syn/rel_chc.cc delete mode 100644 src/vtarget-out/inv-syn/vtarget_gen_inv_abc.cc delete mode 100644 src/vtarget-out/inv-syn/vtarget_gen_inv_chc.cc delete mode 100644 src/vtarget-out/inv-syn/vtarget_gen_inv_enhance.cc delete mode 100644 src/vtarget-out/vtarget_gen_cosa.cc create mode 100644 src/vtarget-out/vtarget_gen_pono.cc delete mode 100644 src/vtarget-out/vtarget_gen_relchc.cc delete mode 100644 src/vtarget-out/vtarget_gen_yosys.cc diff --git a/include/ilang/vtarget-out/.gitignore b/include/ilang/vtarget-out/.gitignore new file mode 100644 index 000000000..0b255b650 --- /dev/null +++ b/include/ilang/vtarget-out/.gitignore @@ -0,0 +1,2 @@ +deprecated/* + diff --git a/include/ilang/vtarget-out/inv-syn/inv_syn_cegar.h b/include/ilang/vtarget-out/inv-syn/inv_syn_cegar.h deleted file mode 100644 index bde891143..000000000 --- a/include/ilang/vtarget-out/inv-syn/inv_syn_cegar.h +++ /dev/null @@ -1,240 +0,0 @@ -/// \file The header for invariant synthesis --- using CEGAR loop -// ---Hongce Zhang - -#ifndef ILANG_VTARGET_OUT_INV_SYN_CEGAR_H__ -#define ILANG_VTARGET_OUT_INV_SYN_CEGAR_H__ - -#include -#ifdef INVSYN_INTERFACE - -#include -#include -#include - -#include -#include - -namespace ilang { - -/// \brief the implementation of the synthesizer class -class InvariantSynthesizerCegar { - -public: - // -------------------- TYPES ------------------ // - /// Type of the verification backend - using verify_backend_selector = VlgVerifTgtGenBase::backend_selector; - /// Type of configuration - using vtg_config_t = VlgVerifTgtGenBase::vtg_config_t; - /// Type of invariant synthesis backend - using synthesis_backend_selector = - VlgVerifTgtGenBase::synthesis_backend_selector; - /// Type of the cegar loop status - /// next to verify, wait_for_verify_result - /// next to synthesis, wait_for_synthesis_result - typedef enum { NEXT_V, V_RES, NEXT_S, S_RES, DONE, FAILED } cegar_status; - /// Type of advanced parameter - using advanced_parameters_t = VlgVerifTgtGenBase::advanced_parameters_t; - /// the type of invariant check result - enum _inv_check_res_t { INV_PROVED, INV_INVALID, INV_UNKNOWN }; - /// additional width info - typedef std::map additional_width_info_t; - -public: - // -------------------- CONSTRUCTOR ------------------ // - /// to create an inv-syn target - InvariantSynthesizerCegar( - const std::vector& implementation_include_path, - const std::vector& implementation_srcs, - const std::string& implementation_top_module, - const std::string& refinement_variable_mapping, - const std::string& refinement_conditions, const std::string& output_path, - const InstrLvlAbsPtr& ila_ptr, verify_backend_selector vbackend, - synthesis_backend_selector sbackend, - const vtg_config_t& vtg_config = vtg_config_t(), - const VerilogGenerator::VlgGenConfig& config = - VerilogGenerator::VlgGenConfig()); - /// no copy constructor, please. - InvariantSynthesizerCegar(const InvariantSynthesizerCegar&) = delete; - /// no assignment, please. - InvariantSynthesizerCegar& - operator=(const InvariantSynthesizerCegar&) = delete; - -public: - // -------------------- HELPERs ------------------ // - // to do things separately, you can provide the run function your self - // or even do it step by step - /// to generate targets using the current invariants - void GenerateVerificationTarget(); - /// to generate targets using the provided invariants - void GenerateVerificationTarget(const std::vector& invs); - /// to generate a target to validate the given and synthesize invariants - void GenerateInvariantVerificationTarget(); - /// to extract verification result - void ExtractVerificationResult(bool autodet = true, bool pass = true, - const std::string& res_file = "", - const std::string& mod_inst_name = ""); - - /// genenate a target to extract smt - void GenerateTargetAndExtractSmt(); - /// get the width of a certain state - unsigned QueryRtlStateWidth(const std::string& name) const; - - /// remove some states from cex - void CexGeneralizeRemoveStates(const std::vector&); - /// to generate synthesis target - void GenerateSynthesisTarget(); - /// to extract reachability test result - void ExtractSynthesisResult(bool autodet = true, bool reachable = true, - const std::string& res_file = ""); - /// to extract reachability test result, this will extract to candidate - /// invariant - void ExtractAbcSynthesisResultForEnhancement(InvariantInCnf& incremental_cnf, - bool autodet = true, - bool reachable = true); - - /// run Verification : returns eq true/false - bool virtual RunVerifAuto(const std::string& script_selection, - const std::string& pid_fname = "", - bool run_test = false, - unsigned timeout = 0); - /// run Synthesis : returns reachable/not - bool virtual RunSynAuto(bool run_test = false); - - /// Forcing to accept all the candidate invariants - void AcceptAllCandidateInvariant(); - /// Remove potentially failing candidate invariants (conservative approach - /// remove all candidates) - void PruneCandidateInvariant(); - /// Supply Verilog candidate invariants - void SupplyCandidateInvariant(const std::string& vlg); - /// Clear all the candidate invariants - void ClearAllCandidateInvariants(); - - // -------------------- GrainChc ------------------ // - void ChangeGrainSyntax(const std::vector& syn); - /// generate enhancement target and run it - /// return false, if grain fails - bool WordLevelEnhancement(const InvariantInCnf& incremental_cnf, - bool run_test = false); - /// get the current inv in cnf - const InvariantInCnf& GetCurrentCnfEnhance() const; - /// merge cnfs - void MergeCnf(const InvariantInCnf& incremental_cnf); - /// extra variable for enhancement, so not really a cnf - void ExtractInvariantVarForEnhance( - size_t inv_idx, InvariantInCnf& incremental_cnf, bool per_clause, - const std::set& vars_to_remove = {}); - - // -------------------- ACCESSOR ------------------ // - /// return back state - bool in_bad_state() const { return bad_state; } - /// check state - bool check_in_bad_state() const; - /// load the smt_design file - void LoadDesignSmtInfo(const std::string& fn); - /// Here we directly expose the runnable script names (They will never be used - /// as inputs) - const std::vector& GetRunnableTargetScriptName() const; - /// Here you can restore the design information - void LoadPrevStatisticsState(const std::string& fn); - /// Here you can get the design information - DesignStatistics GetDesignStatistics() const; - /// Here you can extract the invariants and export them if needed - const InvariantObject& GetInvariants() const; - /// remove a confirmed invariant - void RemoveInvariantsByIdx(size_t idx); - /// Here you can extract the invariants and export them if needed - const InvariantObject& GetCandidateInvariants() const; - /// load confirmed invariants from file - void LoadInvariantsFromFile(const std::string& fn); - /// load invariants as candidates from file - void LoadCandidateInvariantsFromFile(const std::string& fn); - -protected: - // -------------------- MEMBERS ------------------ // - /// the found invariants, in Verilog expression - InvariantObject inv_obj; - /// the found invariants, in CNF (only for ABC), will be merged to - InvariantInCnf inv_cnf; - /// the temporary invariants (that might not be inductive) - InvariantObject inv_candidate; - /// the pointer to a cegar object - std::unique_ptr cex_extract; - /// vlg-module instance name; - std::string vlg_mod_inst_name; - /// the status of the loop - cegar_status status; - /// the SMT-LIB2 information of the design - std::shared_ptr design_smt_info; - /// the supplementary information - additional_width_info_t additional_width_info; - /// is in back state? - bool bad_state; - /// the round id - unsigned round_id; - /// the runnable script name after each target gen - std::vector runnable_script_name; - /// verification result - bool verification_pass; - /// verification result -- the vcd full name/path - std::string vcd_file_name; - /// synthesis result - bool cex_reachable; - /// the synthesis result file - std::string synthesis_result_fn; - /// the invariant type - enum cur_inv_tp { NONE, GRAIN_CHC, CHC, CEGAR_ABC } current_inv_type; - - // -------------------------------------------------- - // for book-keeping purpose - // -------------------------------------------------- - /// path for verilog includes - std::vector implementation_incl_path; - /// path for verilog sources - std::vector implementation_srcs_path; - /// the top module name - std::string implementation_top_module_name; - /// path to the variable mapping file - std::string refinement_variable_mapping_path; - /// path to the conditions - std::string refinement_condition_path; - /// the output path (must exists) - std::string _output_path; - /// the pointer to ILA - InstrLvlAbsPtr _host; - /// the verification backend - verify_backend_selector v_backend; - /// the synthesis backend selection - synthesis_backend_selector s_backend; - /// the target generator configuration - vtg_config_t _vtg_config; - /// the verilog gnerator configuration - VerilogGenerator::VlgGenConfig _vlg_config; - - // -------------------------------------------------- - // for statistics purpose - // -------------------------------------------------- - /// time for equivalence checking - double eqcheck_time; - /// time for validation of invariants - double inv_validate_time; - /// time for z3 proving attempt - double inv_proof_attempt_time; - /// the synthesis time of invariants : chc/sygus-chc/sygus-dp - double inv_syn_time; - /// the enhance ment time - double inv_enhance_time; - /// the series of synthesis time - std::vector inv_syn_time_series; - -public: - /// total cands there are - long long total_grain_cand; - -}; // class InvariantSynthesizerCegar - -}; // namespace ilang - -#endif // INVSYN_INTERFACE - -#endif // ILANG_VTARGET_OUT_INV_SYN_CEGAR_H__ diff --git a/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_abc.h b/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_abc.h deleted file mode 100644 index 99f951e67..000000000 --- a/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_abc.h +++ /dev/null @@ -1,179 +0,0 @@ -/// \file Verilog Verification Target Generator -- generating Abc target -/// (design-only, same as the invariant target) -/// We use Abc to convert Verilog to smt-lib2, and then -/// it will be parsed and re-format by smt-io -/// and use that information, it will create horn clauses -/// This file should not be included, as it requires the impl. -// ---Hongce Zhang - -#ifndef VTARGET_GEN_INV_ABC_H__ -#define VTARGET_GEN_INV_ABC_H__ - -#include -#ifdef INVSYN_INTERFACE - -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -class VlgSglTgtGen_Abc; - -/// \brief a class to store (and generate) the problem for Abc -class Abc_problem { - friend class VlgSglTgtGen_Abc; - /// Type of assertions and assumptions - typedef std::vector prop_t; - /// Type of a problem --- we can handle multiple several problems (may not - /// needed) - typedef struct { - // the name in [??] - // std::string problem_name; - /// will be conjuncted and put in the question - prop_t exprs; - } problem_t; - /// set of problems - typedef std::map problemset_t; - -protected: - /// assumptions are not shared (unlike CoSA) - problemset_t assumptions; - /// problems are splitted into items - problemset_t assertions; - -}; // Abc_problem - -/// \brief a class to interface w. Abc -class VlgSglTgtGen_Abc : public VlgSglTgtGen { - -public: - /// using the target type - using target_type_t = VlgSglTgtGen::target_type_t; - /// a tuple to store all related info for modification - using info_t = VerilogModifier::info_t; - /// filename -> (lineno, varname, is_port_sig) vec - using fn_l_map_t = VerilogModifier::fn_l_map_t; - /// Type of advanced parameter - using advanced_parameters_t = VlgVerifTgtGenBase::advanced_parameters_t; - /// Type of Abc target - using _chc_target_t = VlgVerifTgtGenBase::_chc_target_t; - -public: - // --------------------- CONSTRUCTOR ---------------------------- // - /// - /// \param[in] output path (ila-verilog, wrapper-verilog, problem.txt, - /// run-verify-by-???, modify-impl, it there is ) \param[in] pointer to the - /// instruction \param[in] the default configuration for outputing verilog - /// \param[in] the variable map - /// \param[in] the conditions - /// \param[in] pointer to verify info class - /// \param[in] verilog module name - /// \param[in] ila module name, - /// \param[in] all implementation sources - /// \param[in] all include paths - /// \param[in] which backend to use, it needs this info to gen proper - /// properties - VlgSglTgtGen_Abc( - const std::string& output_path, // will be a sub directory of the - // output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const VerilogGenerator::VlgGenConfig& config, nlohmann::json& _rf_vmap, - nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo& _sup_info, - VerilogInfo* _vlg_info_ptr, const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& include_dirs, - const vtg_config_t& vtg_config, backend_selector vbackend, - synthesis_backend_selector sbackend, const target_type_t& target_tp, - advanced_parameters_t* adv_ptr, bool generate_proof, - _chc_target_t Abc_target, bool useGLA, bool useCORR, bool useAIGER); - - // --------------------- Destructor ---------------------------- // - /// do nothing - virtual ~VlgSglTgtGen_Abc(); - -protected: - /// Abc problem generate - Abc_problem _problems; - /// Abc problem file name - std::string blif_fname; - /// Abc problem file name (aiger file), if aiger_fname is not empty, it will - /// be do aiger - std::string aiger_fname; - /// Abc script 'run.sh' name - std::string abc_run_script_name; - /// the invariants on the design - std::vector vlg_mod_inv_vec; - /// the synthesis backend - synthesis_backend_selector s_backend; - /// whether to require a proof - bool generate_proof; - /// whether a cex is provided - bool has_cex; - /// what are the targets - _chc_target_t chc_target; - /// Use abc gla? - const bool useGla; - /// Use abc corr - const bool useCorr; - /// send abc aiger - const bool useAiger; - /// disallow GLA if use extra output as assumptions - bool disallowGla; - -protected: - /// Add a direct assumption -- needed by base class - virtual void add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) override; - /// Add a direct assertion -- needed by base class - virtual void add_a_direct_assertion(const std::string& asst, - const std::string& dspt) override; - - /// Pre export work : add assume and asssert to the top level - void virtual PreExportProcess() override; - /// export the script to run the verification - virtual void Export_script(const std::string& script_name) override; - /// export extra things: the Abc script, the smt template - virtual void Export_problem(const std::string& extra_name) override; - /// export the memory abstraction (implementation) - /// Yes, this is also implementation specific, (jasper may use a different - /// one) - virtual void Export_mem(const std::string& mem_name) override; - /// For jasper, this means do nothing, for Abc, you need to add (*keep*) - virtual void Export_modify_verilog() override; - -private: - /// generate the wrapper's smt first - void generate_blif(const std::string& blif_name, - const std::string& ys_script_name); - /// generate the wrapper's aig first - void generate_aiger(const std::string& blif_name, - const std::string& aiger_name, - const std::string& map_name, - const std::string& ys_script_name); - -public: - /// overwrite the Export - void virtual ExportAll(const std::string& wrapper_name, - const std::string& ila_vlg_name, - const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name) override; - - /// It is okay to instantiation - virtual void do_not_instantiate(void) override{}; - -}; // class VlgVerifTgtGenAbc - -}; // namespace ilang - -#endif // INVSYN_INTERFACE - -#endif // VTARGET_GEN_INV_ABC_H__ diff --git a/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_chc.h b/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_chc.h deleted file mode 100644 index 5d8df9320..000000000 --- a/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_chc.h +++ /dev/null @@ -1,174 +0,0 @@ -/// \file Verilog Verification Target Generator -- generating CHC target -/// (design-only, same as the invariant target) -/// We use chc to convert Verilog to smt-lib2, and then -/// it will be parsed and re-format by smt-io -/// and use that information, it will create horn clauses -/// This file should not be included, as it requires the impl. -// ---Hongce Zhang - -#ifndef VTARGET_GEN_INV_CHC_H__ -#define VTARGET_GEN_INV_CHC_H__ - -#include -#ifdef INVSYN_INTERFACE - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -class VlgSglTgtGen_Chc; - -/// \brief a class to store (and generate) the problem for Chc -class Chc_problem { - friend class VlgSglTgtGen_Chc; - /// Type of assertions and assumptions - typedef std::vector prop_t; - /// Type of a problem --- we can handle multiple several problems (may not - /// needed) - typedef struct { - // the name in [??] - // std::string problem_name; - /// will be conjuncted and put in the question - prop_t exprs; - } problem_t; - /// set of problems - typedef std::map problemset_t; - -protected: - /// assumptions are not shared (unlike CoSA) - problemset_t assumptions; - /// problems are splitted into items - problemset_t assertions; - -}; // Chc_problem - -/// \brief a class to interface w. Chc -class VlgSglTgtGen_Chc : public VlgSglTgtGen { - -public: - /// using the target type - using target_type_t = VlgSglTgtGen::target_type_t; - /// a tuple to store all related info for modification - using info_t = VerilogModifier::info_t; - /// filename -> (lineno, varname, is_port_sig) vec - using fn_l_map_t = VerilogModifier::fn_l_map_t; - /// Type of advanced parameter - using advanced_parameters_t = VlgVerifTgtGenBase::advanced_parameters_t; - /// Type of chc target - using _chc_target_t = VlgVerifTgtGenBase::_chc_target_t; - -public: - // --------------------- CONSTRUCTOR ---------------------------- // - /// - /// \param[in] output path (ila-verilog, wrapper-verilog, problem.txt, - /// run-verify-by-???, modify-impl, it there is ) \param[in] pointer to the - /// instruction \param[in] the default configuration for outputing verilog - /// \param[in] the variable map - /// \param[in] the conditions - /// \param[in] pointer to verify info class - /// \param[in] verilog module name - /// \param[in] ila module name, - /// \param[in] all implementation sources - /// \param[in] all include paths - /// \param[in] which backend to use, it needs this info to gen proper - /// properties - VlgSglTgtGen_Chc( - const std::string& output_path, // will be a sub directory of the - // output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const VerilogGenerator::VlgGenConfig& config, nlohmann::json& _rf_vmap, - nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo& _sup_info, - VerilogInfo* _vlg_info_ptr, const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& include_dirs, - const vtg_config_t& vtg_config, backend_selector vbackend, - synthesis_backend_selector sbackend, const target_type_t& target_tp, - advanced_parameters_t* adv_ptr, bool generate_proof, - _chc_target_t chc_target); - - // --------------------- Destructor ---------------------------- // - /// do nothing - virtual ~VlgSglTgtGen_Chc(); - -protected: - /// Chc problem generate - Chc_problem _problems; - /// Chc problem file name - std::string chc_prob_fname; - /// Chc script 'run.sh' name - std::string chc_run_script_name; - /// the invariants on the design - std::vector vlg_mod_inv_vec; - /// the synthesis backend - synthesis_backend_selector s_backend; - /// the smt info of the design - std::shared_ptr design_smt_info; - /// whether to require a proof - bool generate_proof; - /// whether a cex is provided - bool has_cex; - /// what are the targets - _chc_target_t chc_target; - -protected: - /// Add a direct assumption -- needed by base class - virtual void add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) override; - /// Add a direct assertion -- needed by base class - virtual void add_a_direct_assertion(const std::string& asst, - const std::string& dspt) override; - - /// Pre export work : add assume and asssert to the top level - void virtual PreExportProcess() override; - /// export the script to run the verification - virtual void Export_script(const std::string& script_name) override; - /// export extra things: the chc script, the smt template - virtual void Export_problem(const std::string& extra_name) override; - /// export the memory abstraction (implementation) - /// Yes, this is also implementation specific, (jasper may use a different - /// one) - virtual void Export_mem(const std::string& mem_name) override; - /// For jasper, this means do nothing, for chc, you need to add (*keep*) - virtual void Export_modify_verilog() override; - -private: - /// Convert the smt file to CHC -- datatype encoding - void convert_smt_to_chc_datatype(const std::string& smt_fname, - const std::string& chc_fname); - /// Convert the smt file to CHC -- bitvector encoding - void convert_smt_to_chc_bitvec(const std::string& smt_fname, - const std::string& chc_fname, - const std::string& wrapper_mod_name); - /// generate the wrapper's smt first - void design_only_gen_smt(const std::string& smt_name, - const std::string& ys_script_name); - -public: - /// overwrite the Export - void virtual ExportAll(const std::string& wrapper_name, - const std::string& ila_vlg_name, - const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name) override; - /// accessor of the design info - std::shared_ptr GetDesignSmtInfo() const; - /// It is okay to instantiation - virtual void do_not_instantiate(void) override{}; - -}; // class VlgVerifTgtGenChc - -}; // namespace ilang - -#endif // INVSYN_INTERFACE - -#endif // VTARGET_GEN_INV_CHC_H__ diff --git a/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_enhance.h b/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_enhance.h deleted file mode 100644 index 76c4c78f8..000000000 --- a/include/ilang/vtarget-out/inv-syn/vtarget_gen_inv_enhance.h +++ /dev/null @@ -1,187 +0,0 @@ -/// \file Verilog Verification Target Generator -- generating CHC target to -/// enhance invariant (design-only, same as the invariant target) We use yosys -/// to convert Verilog to smt-lib2, and then it will be parsed and re-format by -/// smt-io and use that information, it will create horn clauses This file -/// should not be included by the user code, as it requires the impl. - -/// This is for Grain only invariant enhancements/strengthening by syntax -// ---Hongce Zhang - -#ifndef VTARGET_GEN_INV_ENHANCE_H__ -#define VTARGET_GEN_INV_ENHANCE_H__ - -#include -#ifdef INVSYN_INTERFACE - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -class VlgSglTgtGen_Chc_wCNF; - -/// \brief a class to store (and generate) the problem for Chc -class Chc_enhance_problem { - friend class VlgSglTgtGen_Chc_wCNF; - /// Type of assertions and assumptions - typedef std::vector prop_t; - /// Type of a problem --- we can handle multiple several problems (may not - /// needed) - typedef struct { - // the name in [??] - // std::string problem_name; - /// will be conjuncted and put in the question - prop_t exprs; - } problem_t; - /// set of problems - typedef std::map problemset_t; - -protected: - /// assumptions are not shared (unlike CoSA) - problemset_t assumptions; - /// problems are splitted into items - problemset_t assertions; - -}; // Chc_enhance_problem - -/// \brief a class to interface w. Chc -class VlgSglTgtGen_Chc_wCNF : public VlgSglTgtGen { - -public: - /// using the target type - using target_type_t = VlgSglTgtGen::target_type_t; - /// a tuple to store all related info for modification - using info_t = VerilogModifier::info_t; - /// filename -> (lineno, varname, is_port_sig) vec - using fn_l_map_t = VerilogModifier::fn_l_map_t; - /// Type of advanced parameter - using advanced_parameters_t = VlgVerifTgtGenBase::advanced_parameters_t; - /// Type of chc target - using _chc_target_t = VlgVerifTgtGenBase::_chc_target_t; - -public: - // --------------------- CONSTRUCTOR ---------------------------- // - /// - /// \param[in] output path (ila-verilog, wrapper-verilog, problem.txt, - /// run-verify-by-???, modify-impl, it there is ) \param[in] pointer to the - /// instruction \param[in] the default configuration for outputing verilog - /// \param[in] the variable map - /// \param[in] the conditions - /// \param[in] pointer to verify info class - /// \param[in] verilog module name - /// \param[in] ila module name, - /// \param[in] all implementation sources - /// \param[in] all include paths - /// \param[in] which backend to use, it needs this info to gen proper - /// properties - VlgSglTgtGen_Chc_wCNF( - const std::string& output_path, // will be a sub directory of the - // output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const VerilogGenerator::VlgGenConfig& config, nlohmann::json& _rf_vmap, - nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo& _sup_info, - VerilogInfo* _vlg_info_ptr, const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& include_dirs, - const vtg_config_t& vtg_config, backend_selector vbackend, - synthesis_backend_selector sbackend, const target_type_t& target_tp, - advanced_parameters_t* adv_ptr, bool generate_proof, - _chc_target_t chc_target); - - // --------------------- Destructor ---------------------------- // - /// do nothing - virtual ~VlgSglTgtGen_Chc_wCNF(); - -protected: - /// Chc problem generate - Chc_enhance_problem _problems; - /// Chc problem file name - std::string chc_prob_fname; - /// Chc script 'run.sh' name - std::string chc_run_script_name; - /// the invariants on the design - std::vector vlg_mod_inv_vec; - /// the synthesis backend - synthesis_backend_selector s_backend; - /// the smt info of the design - std::shared_ptr design_smt_info; - /// whether to require a proof - bool generate_proof; - /// whether a cex is provided - bool has_cex; - /// what are the targets - _chc_target_t chc_target; - -protected: - /// Add a direct assumption -- needed by base class - virtual void add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) override; - /// Add a direct assertion -- needed by base class - virtual void add_a_direct_assertion(const std::string& asst, - const std::string& dspt) override; - - /// Pre export work : add assume and asssert to the top level - void virtual PreExportProcess() override; - /// export the script to run the verification - virtual void Export_script(const std::string& script_name) - override; // do nothing - should not be used - virtual void Export_script(const std::string& script_name, - const std::string& cnf_fn); - /// export extra things: the chc script, the smt template - virtual void Export_problem(const std::string& extra_name) override; - /// export the memory abstraction (implementation) - /// Yes, this is also implementation specific, (jasper may use a different - /// one) - virtual void Export_mem(const std::string& mem_name) override; - /// For jasper, this means do nothing, for chc, you need to add (*keep*) - virtual void Export_modify_verilog() override; - /// Export the cnf for Grain's reference - void Export_cnf(const InvariantInCnf& cnf, const std::string& cnf_fn) const; - /// Export the cnf for wky's Grain's reference - void Export_coci(const InvariantInCnf& cnf, const std::string& cnf_fn) const; - -private: - /// Convert the smt file to CHC -- datatype encoding - void convert_smt_to_chc_datatype(const std::string& smt_fname, - const std::string& chc_fname); - /// generate the wrapper's smt first - void design_only_gen_smt(const std::string& smt_name, - const std::string& ys_script_name); - -public: - /// do nothing - should not be used - void virtual ExportAll(const std::string& wrapper_name, - const std::string& ila_vlg_name, - const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name) override; - /// overwrite the Export, use this one: - void virtual ExportAll(const std::string& wrapper_name, - const std::string& ila_vlg_name, - const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name, - const std::string& cnf_name, - const InvariantInCnf& cnf); - /// accessor of the design info - std::shared_ptr GetDesignSmtInfo() const; - /// It is okay to instantiation - virtual void do_not_instantiate(void) override{}; - -}; // class VlgVerifTgtGenChc - -}; // namespace ilang - -#endif // INVSYN_INTERFACE - -#endif // VTARGET_GEN_INV_ENHANCE_H__ diff --git a/include/ilang/vtarget-out/vtarget_gen.h b/include/ilang/vtarget-out/vtarget_gen.h index 1e8057eef..9c9ccaf49 100644 --- a/include/ilang/vtarget-out/vtarget_gen.h +++ b/include/ilang/vtarget-out/vtarget_gen.h @@ -32,11 +32,11 @@ class VlgVerifTgtGenBase { NONE = 0, JASPERGOLD = 2, YOSYS = 128, // 10000000 - CHC = YOSYS + 8, // 10001000 - Z3PDR = CHC + 1, // 10001001 - ELD_CEGAR = CHC + 2, // 10001010 - GRAIN_SYGUS = CHC + 4, // 10001100 - ABCPDR = YOSYS + 16, // 10010000 + //CHC = YOSYS + 8, // 10001000 + //Z3PDR = CHC + 1, // 10001001 + //ELD_CEGAR = CHC + 2, // 10001010 + //GRAIN_SYGUS = CHC + 4, // 10001100 + //ABCPDR = YOSYS + 16, // 10010000 PONO = YOSYS + 32, // 10100000 RELCHC = YOSYS + 64 // 11000000 }; @@ -48,13 +48,13 @@ class VlgVerifTgtGenBase { } /// Type of invariant synthesis backend - enum class synthesis_backend_selector { - Z3 = int(backend_selector::Z3PDR) ^ int(backend_selector::YOSYS), - GRAIN = int(backend_selector::GRAIN_SYGUS) ^ int(backend_selector::YOSYS), - ABC = int(backend_selector::ABCPDR) ^ int(backend_selector::YOSYS), - ELDERICA = int(backend_selector::ELD_CEGAR) ^ int(backend_selector::YOSYS),// 0001010 - NOSYN = int(backend_selector::YOSYS) // 1000000 - } ; + /*enum class synthesis_backend_selector { + // Z3 = int(backend_selector::Z3PDR) ^ int(backend_selector::YOSYS), // 01001 + GRAIN = int(backend_selector::GRAIN_SYGUS) ^ int(backend_selector::YOSYS), // 01100 + ABC = int(backend_selector::ABCPDR) ^ int(backend_selector::YOSYS), // 10000 + ELDERICA = int(backend_selector::ELD_CEGAR) ^ int(backend_selector::YOSYS), // 01010 + NOSYN = int(backend_selector::YOSYS) // 1000000 + } ;*/ /// Type of the chc target enum class _chc_target_t { CEX, INVCANDIDATE, GENERAL_PROPERTY }; /// Verilog Target Generation Configuration @@ -96,11 +96,15 @@ class VlgVerifTgtGenBase { enum class PortDeclStyleT { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; /// Generate a jg script to help validate Pono? bool PonoGenJgTesterScript; + /// Pono VCD output + std::string PonoVcdOutputName; + /// Binary location of Pono + std::string PonoPath; /// For Pono backend: do we add (* keep *)? default true, however, it can be /// buggy, so you can disable it if you want bool PonoAddKeep; /// For Pono backend: what more options to add - std::string PonoOtherSolverOptions; + std::string PonoOtherOptions; /// whether to force dot reference check in the generation /// if you expect to use Pono on the it, yes, you need to /// use the default setting : NOTIFY_PANIC @@ -218,7 +222,7 @@ class VlgVerifTgtGenBase { // ----------- Options for Pono settings -------------- // ForceInstCheckReset(false), PortDeclStyle(PortDeclStyleT::AUTO), PonoGenJgTesterScript(false), PonoAddKeep(false), - PonoOtherSolverOptions(""), + PonoOtherOptions(""), PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), MaxBound(127), OnlyAssumeUpdatedVarsEq(false), @@ -291,8 +295,8 @@ class VerilogVerificationTargetGenerator { /// Type of the backend using backend_selector = VlgVerifTgtGenBase::backend_selector; /// Type of the synthesis backend - using synthesis_backend_selector = - VlgVerifTgtGenBase::synthesis_backend_selector; + //using synthesis_backend_selector = + // VlgVerifTgtGenBase::synthesis_backend_selector; /// Type of configuration using vtg_config_t = VlgVerifTgtGenBase::vtg_config_t; @@ -301,13 +305,17 @@ class VerilogVerificationTargetGenerator { /// /// \param[in] implementation's include path (if it uses `include) /// \param[in] verilog's path, currently we only handle situation where all in - /// the same folder \param[in] name of the top module of the implementation, - /// leave "" to allow auto analysis \param[in] where to get variable mapping + /// the same folder + /// \param[in] name of the top module of the implementation, + /// leave "" to allow auto analysis + /// \param[in] where to get variable mapping /// \param[in] where to get refinement relation /// \param[in] output path (ila-verilog, wrapper-verilog, problem.txt, - /// run-verify-by-???, modify-impl, it there is ) \param[in] pointer to the - /// ila \param[in] the backend selector \param[in] (optional) the default - /// configuration for outputing verilog + /// run-verify-by-???, modify-impl, it there is ) + /// \param[in] pointer to the ila + /// \param[in] the backend selector + /// \param[in] (optional) the default + /// configuration for outputing verilog VerilogVerificationTargetGenerator( const std::vector& implementation_include_path, const std::vector& implementation_srcs, diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 5ecedd6aa..7f6c18dca 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -42,8 +42,8 @@ class VlgSglTgtGen { /// Type of the verification backend using backend_selector = VlgVerifTgtGenBase::backend_selector; /// Type of the synthesis backend - using synthesis_backend_selector = - VlgVerifTgtGenBase::synthesis_backend_selector; + //using synthesis_backend_selector = + // VlgVerifTgtGenBase::synthesis_backend_selector; /// Type of configuration using vtg_config_t = VlgVerifTgtGenBase::vtg_config_t; /// Type of record of extra info of a signal @@ -102,13 +102,12 @@ class VlgSglTgtGen { /// Verilog module connection IntefaceDirectiveRecorder _idr; - /// The refinement map with type checked - rfmap::TypedVerilogRefinementMap refinement_map; - /// Analyzer for the implementation // we don't know the module name, before analyzing the rfmap. so we cannot // initialize in the beginning VerilogInfo* vlg_info_ptr; + /// The refinement map with type checked + rfmap::TypedVerilogRefinementMap refinement_map; /// target type target_type_t target_type; /// func apply counter @@ -144,8 +143,7 @@ class VlgSglTgtGen { const ExprPtr IlaGetInput(const std::string& sname) const; /// Get (a,d) width of a memory, if not existing, (0,0) std::pair - - GetMemInfo(const std::string& ila_mem_name) const; + GetMemInfo(const std::string& ila_mem_name) const; /// Test if a string represents an ila state name bool TryFindIlaState(const std::string& sname); /// Test if a string represents an ila input name @@ -154,6 +152,8 @@ class VlgSglTgtGen { bool TryFindVlgState(const std::string& sname); /// Try to find a ILA var according to a name ExprPtr TryFindIlaVarName(const std::string& sname); + /// return the type of a variable when its name is given + rfmap::RfVarTypeOrig VarTypeCheckForRfExprParsing(const std::string &); /// Check if ila name and vlg name are type compatible (not including special /// directives) @@ -197,6 +197,8 @@ class VlgSglTgtGen { void ConstructWrapper_add_cycle_count_moniter(); /// generate the `define TRUE 1 void ConstructWrapper_generate_header(); + /// add input equ assumptions + void ConstructWrapper_add_inputmap_assumptions(); /// add state equ assumptions void ConstructWrapper_add_varmap_assumptions(); /// add state equ assertions @@ -231,8 +233,7 @@ class VlgSglTgtGen { /// Add invariants as assumption/assertion when target is inv_syn_design_only void ConstructWrapper_add_inv_assumption_or_assertion_target_inv_syn_design_only(); - /// Connect the memory even we don't care a lot about them - void ConstructWrapper_inv_syn_connect_mem(); + /// Sometimes you need to add some signals that only appeared in Instruction /// target void ConstructWrapper_inv_syn_cond_signals(); @@ -272,9 +273,9 @@ class VlgSglTgtGen { void virtual ConstructWrapper(); /// PreExportWork (modification and etc.) void virtual PreExportProcess() = 0; - /// create the wrapper file + /// create the wrapper file: set top_file_name void virtual Export_wrapper(const std::string& wrapper_name); - /// export the ila verilog + /// export the ila verilog, may use top_file_name if backend needs yosys void virtual Export_ila_vlg(const std::string& ila_vlg_name); /// export the script to run the verification void virtual Export_script(const std::string& script_name) = 0; @@ -284,15 +285,14 @@ class VlgSglTgtGen { /// export the memory abstraction (implementation) /// Yes, this is also implementation specific, (jasper may use a different /// one) - void virtual Export_mem(const std::string& mem_name) = 0; + // void virtual Export_mem(const std::string& mem_name) = 0; /// For jasper, this means do nothing, for yosys, you need to add (*keep*) void virtual Export_modify_verilog() = 0; /// Take care of exporting all of a single target void virtual ExportAll(const std::string& wrapper_name, const std::string& ila_vlg_name, const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name); + const std::string& extra_name); protected: // helper function to be implemented by COSA/JASPER @@ -395,12 +395,9 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { VlgVerifTgtGen(const std::vector& implementation_include_path, const std::vector& implementation_srcs, const std::string& implementation_top_module, - const std::string& refinement_variable_mapping, - const std::string& refinement_conditions, + const rfmap::VerilogRefinementMap & refinement, const std::string& output_path, const InstrLvlAbsPtr& ila_ptr, backend_selector backend, const vtg_config_t& vtg_config, - const VerilogGenerator::VlgGenConfig& config = - VerilogGenerator::VlgGenConfig(), advanced_parameters_t* adv_ptr = NULL); /// no copy constructor, please @@ -421,18 +418,12 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { /// implementation top module name const std::string _vlg_impl_top_name; /// refinement relation - variable mapping path - const std::string _rf_var_map_name; - /// refinement relation - condition path - const std::string _rf_cond_name; + rfmap::VerilogRefinementMap _refinement; /// output path, output the ila-verilog, wrapper-verilog, problem.txt, /// run-verify-by-??? const std::string _output_path; /// The pointer to the instruction that is going to export const InstrLvlAbsPtr& _ila_ptr; - /// The name of verilog top module instance in the wrapper - std::string _vlg_mod_inst_name; - /// The name of ila-verilog top module instance in the wrapper - std::string _ila_mod_inst_name; /// A pointer to create verilog analyzer VerilogInfo* vlg_info_ptr; /// to store the backend @@ -455,9 +446,9 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { /// Return true if it is in bad state bool in_bad_state(void) const { return _bad_state; } /// get vlg-module instance name - std::string GetVlgModuleInstanceName() const { return _vlg_mod_inst_name; } + std::string GetVlgModuleInstanceName() const { return "RTL"; } -#ifdef INVSYN_INTERFACE +#if 0 /// generate invariant synthesis target void GenerateInvSynTargetsAbc(bool useGla, bool useCorr, bool useAiger); /// generate inv-syn target diff --git a/include/ilang/vtarget-out/vtarget_gen_jasper.h b/include/ilang/vtarget-out/vtarget_gen_jasper.h index 52da17b71..8de5be005 100644 --- a/include/ilang/vtarget-out/vtarget_gen_jasper.h +++ b/include/ilang/vtarget-out/vtarget_gen_jasper.h @@ -38,21 +38,13 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants const InstrLvlAbsPtr& ila_ptr, - const VerilogGenerator::VlgGenConfig& config, nlohmann::json& _rf_vmap, - nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo& _supplementary_info, - VerilogInfo* _vlg_info_ptr, const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, + const rfmap::VerilogRefinementMap & refinement, + VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& include_dirs, const vtg_config_t& vtg_config, backend_selector backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr); - /// if you have signals that are controled by assumptions to be equal as - /// the outer clock, you need to put them here, - /// because the assumptions do not work in the jaspergold reset step - /// (unlike COSA) - void add_addition_clock_info(const std::string& expr); - void add_addition_reset_info(const std::string& expr); protected: /// internal storage of problems @@ -61,17 +53,21 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { /// vector of pairs of std::vector> assertions; /// vector of clock signals that need to be taken care of - std::vector - additional_clock_expr; // we don't put the "clk" here, as by default it - // will be there - /// vector of clock signals that need to be taken care of - std::vector additional_reset_expr; + /// Name of the problem file std::string jg_script_name; - /// Name of the problem file - std::string abs_mem_name; protected: + /// Add SMT-lib2 assumption + virtual void add_a_direct_smt_assumption(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) override; + /// Add SMT-lib2 assertion + virtual void add_a_direct_smt_assertion(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) override; /// Add an assumption virtual void add_an_assumption(const std::string& aspt, const std::string& dspt) override; @@ -104,10 +100,6 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { /// export extra things (problem) virtual void Export_problem(const std::string& extra_name) override; // only for cosa - /// export the memory abstraction (implementation) - /// Yes, this is also implementation specific, (jasper may use a different - /// one) - virtual void Export_mem(const std::string& mem_name) override; /// For jasper, this means do nothing, for yosys, you need to add (*keep*) virtual void Export_modify_verilog() override; diff --git a/include/ilang/vtarget-out/vtarget_gen_cosa.h b/include/ilang/vtarget-out/vtarget_gen_pono.h similarity index 62% rename from include/ilang/vtarget-out/vtarget_gen_cosa.h rename to include/ilang/vtarget-out/vtarget_gen_pono.h index 1902d6b02..665e69a56 100644 --- a/include/ilang/vtarget-out/vtarget_gen_cosa.h +++ b/include/ilang/vtarget-out/vtarget_gen_pono.h @@ -1,9 +1,9 @@ -/// \file Verilog Verification Target Generator -- for CoSA +/// \file Verilog Verification Target Generator -- for Pono /// This file should not be included, as it requires the impl. // ---Hongce Zhang -#ifndef ILANG_VTARGET_OUT_VTARGET_GEN_COSA_H__ -#define ILANG_VTARGET_OUT_VTARGET_GEN_COSA_H__ +#ifndef ILANG_VTARGET_OUT_VTARGET_GEN_PONO_H__ +#define ILANG_VTARGET_OUT_VTARGET_GEN_PONO_H__ #include #include @@ -17,11 +17,11 @@ namespace ilang { -class VlgSglTgtGen_Cosa; +class VlgSglTgtGen_Pono; -/// \brief a class to store (and generate) the problem for cosa -class Cosa_problem { - friend class VlgSglTgtGen_Cosa; +/// \brief a class to store (and generate) the problem for pono +class Pono_problem { + friend class VlgSglTgtGen_Pono; /// Type of assertions and assumptions typedef std::vector prop_t; /// Type of a problem --- we can handle multiple several problems (may not @@ -30,21 +30,27 @@ class Cosa_problem { // the name in [??] // std::string problem_name; /// will be conjuncted and put in the question - prop_t assertions; + prop_t exprs; } problem_t; /// set of problems typedef std::map problemset_t; protected: - /// assumptions are shared - prop_t assumptions; + /// assumptions are not shared + problemset_t assumptions; /// problems are splitted into items - problemset_t probitem; + problemset_t assertions; + + /// SMT-LIB2 assumptions + prop_t smt_assumptions; + /// SMT-LIB2 assertions + prop_t smt_assertions; -}; // Cosa_problem +}; // Pono_problem -/// \brief a class to interface w. COSA -class VlgSglTgtGen_Cosa : public VlgSglTgtGen { +/// \brief a class to interface w. PONO +class VlgSglTgtGen_Pono : public VlgSglTgtGen { +public: /// using the target type using target_type_t = VlgSglTgtGen::target_type_t; /// a tuple to store all related info for modification @@ -58,10 +64,9 @@ class VlgSglTgtGen_Cosa : public VlgSglTgtGen { // --------------------- CONSTRUCTOR ---------------------------- // /// /// \param[in] output path (ila-verilog, wrapper-verilog, problem.txt, - /// run-verify-by-???, modify-impl, it there is ) \param[in] pointer to the - /// instruction \param[in] the default configuration for outputing verilog - /// \param[in] the variable map - /// \param[in] the conditions + /// run-verify-by-???, modify-impl, it there is ) + /// \param[in] pointer to the instruction + /// \param[in] the refinement map /// \param[in] pointer to verify info class /// \param[in] verilog module name /// \param[in] ila module name, @@ -69,26 +74,24 @@ class VlgSglTgtGen_Cosa : public VlgSglTgtGen { /// \param[in] all include paths /// \param[in] which backend to use, it needs this info to gen proper /// properties - VlgSglTgtGen_Cosa( + VlgSglTgtGen_Pono( const std::string& output_path, // will be a sub directory of the // output_path of its parent const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants const InstrLvlAbsPtr& ila_ptr, - const VerilogGenerator::VlgGenConfig& config, nlohmann::json& _rf_vmap, - nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo& _supplementary_info, - VerilogInfo* _vlg_info_ptr, const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, + const rfmap::VerilogRefinementMap & refinement, + VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& include_dirs, const vtg_config_t& vtg_config, backend_selector backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr); protected: - /// Cosa problem generate - Cosa_problem _problems; - /// Cosa problem file name - std::string cosa_prob_fname; + /// Pono problem generate + Pono_problem _problems; + /// Pono problem file name + std::string ys_script_name; protected: /// Add a direct assumption @@ -97,21 +100,26 @@ class VlgSglTgtGen_Cosa : public VlgSglTgtGen { /// Add a direct assertion virtual void add_a_direct_assertion(const std::string& asst, const std::string& dspt) override; + + /// Add SMT-lib2 assumption + virtual void add_a_direct_smt_assumption(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) override; + /// Add SMT-lib2 assertion + virtual void add_a_direct_smt_assertion(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) override; - /// Pre export work : nothing for cosa - void virtual PreExportProcess() override {} + /// Pre export work : nothing for pono + void virtual PreExportProcess() override; /// export the script to run the verification virtual void Export_script(const std::string& script_name) override; /// export extra things (problem) virtual void - Export_problem(const std::string& extra_name) override; // only for cosa - /// generate along-side a jg script that you can use in JasperGold - virtual void Export_jg_tester_script(const std::string& extra_name); - - /// export the memory abstraction (implementation) - /// Yes, this is also implementation specific, (jasper may use a different - /// one) - virtual void Export_mem(const std::string& mem_name) override; + Export_problem(const std::string& extra_name) override; // only for pono + /// For jasper, this means do nothing, for yosys, you need to add (*keep*) virtual void Export_modify_verilog() override; @@ -119,8 +127,8 @@ class VlgSglTgtGen_Cosa : public VlgSglTgtGen { /// It is okay to instantiation virtual void do_not_instantiate(void) override{}; -}; // class VlgVerifTgtGenCosa +}; // class VlgVerifTgtGenPono }; // namespace ilang -#endif // ILANG_VTARGET_OUT_VTARGET_GEN_COSA_H__ +#endif // ILANG_VTARGET_OUT_VTARGET_GEN_PONO_H__ diff --git a/include/ilang/vtarget-out/vtarget_gen_relchc.h b/include/ilang/vtarget-out/vtarget_gen_relchc.h deleted file mode 100644 index 377dd77e3..000000000 --- a/include/ilang/vtarget-out/vtarget_gen_relchc.h +++ /dev/null @@ -1,165 +0,0 @@ -/// \file Verilog Verification Target Generator -- for Relchc -/// We use yosys to convert Verilog to smt-lib2, and then -/// it will be converted to horn clause -/// This file should not be included, as it requires the impl. -/// Internally, we use the -// ---Hongce Zhang - -#ifndef VTARGET_GEN_RELCHC_H__ -#define VTARGET_GEN_RELCHC_H__ - -#include - -#include -#include -#include -#include -#include -#include - -namespace ilang { - -class VlgSglTgtGen_Relchc; - -/// \brief a class to store (and generate) the problem for Relchc (Z3) -class Relchc_problem { - friend class VlgSglTgtGen_Relchc; - /// Type of assertions and assumptions - typedef std::vector prop_t; - /// Type of a problem --- we can handle multiple several problems (may not - /// needed) - typedef struct { - // the name in [??] - // std::string problem_name; - /// will be conjuncted and put in the question - prop_t exprs; - } problem_t; - /// set of problems - typedef std::map problemset_t; - -protected: - /// assumptions are not shared (unlike CoSA) - problemset_t assumptions; - /// problems are splitted into items - problemset_t assertions; - -}; // Relchc_problem - - -/// \brief a class to interface w. Relchc Z3 -class VlgSglTgtGen_Relchc : public VlgSglTgtGen { - /// using the target type - using target_type_t = VlgSglTgtGen::target_type_t; - /// a tuple to store all related info for modification - using info_t = VerilogModifier::info_t; - /// filename -> (lineno, varname, is_port_sig) vec - using fn_l_map_t = VerilogModifier::fn_l_map_t; - /// Type of advanced parameter - using advanced_parameters_t = VlgVerifTgtGenBase::advanced_parameters_t; - -public: - // --------------------- CONSTRUCTOR ---------------------------- // - /// - /// \param[in] output path (ila-verilog, wrapper-verilog, problem.txt, - /// run-verify-by-???, modify-impl, it there is ) \param[in] pointer to the - /// instruction \param[in] the default configuration for outputing verilog - /// \param[in] the variable map - /// \param[in] the conditions - /// \param[in] pointer to verify info class - /// \param[in] verilog module name - /// \param[in] ila module name, - /// \param[in] all implementation sources - /// \param[in] all include paths - /// \param[in] which backend to use, it needs this info to gen proper - /// properties - VlgSglTgtGen_Relchc( - const std::string& output_path, // will be a sub directory of the - // output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const VerilogGenerator::VlgGenConfig& config, nlohmann::json& _rf_vmap, - nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo & _sup_info, VerilogInfo* _vlg_info_ptr, - const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& include_dirs, - const vtg_config_t& vtg_config, backend_selector backend, - const target_type_t& target_tp, - advanced_parameters_t * adv_ptr); - - /// Destructor: do nothing , most importantly it is virtual - virtual ~VlgSglTgtGen_Relchc() {} - -protected: - /// Relchc problem generate - Relchc_problem _problems; - /// Relchc problem file name - std::string relchc_prob_fname; - /// Relchc script 'run.sh' name - std::string relchc_run_script_name; - /// the invariants on the design - std::vector vlg_mod_inv_vec; - -protected: - /// Add a direct assumption -- needed by base class - virtual void add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) override; - /// Add a direct assertion -- needed by base class - virtual void add_a_direct_assertion(const std::string& asst, - const std::string& dspt) override; - - /// Pre export work : add assume and asssert to the top level - void virtual PreExportProcess() override; - /// export the script to run the verification - virtual void Export_script(const std::string& script_name) override; - /// export extra things: the relchc script, the smt template - virtual void - Export_problem(const std::string& extra_name) override; - /// export the memory abstraction (implementation) - /// Yes, this is also implementation specific, (jasper may use a different - /// one) - virtual void Export_mem(const std::string& mem_name) override; - /// For jasper, this means do nothing, for relchc, you need to add (*keep*) - virtual void Export_modify_verilog() override; - -private: - // Here begins the specific functions - // single_inv_problem() : gensmt.ys - // dual_inv_problem() : gensmt.ys - // single_inv_script() : same run.sh - // dual_inv_script() - // single_inv_tpl() : - // dual_inv_tpl() : - - /// generate the Relchc script for dual invariant - void dual_inv_problem(const std::string& ys_script_name); - - /// generate the template file - void dual_inv_tpl(const std::string & tpl_name, const std::string & smt_info); - - /// generate the wrapper's smt first - std::string dual_inv_gen_smt( - const std::string & smt_name, - const std::string & ys_script_name); - - -public: - - /// Deprecation of the one without smt info - void virtual ExportAll(const std::string& wrapper_name, - const std::string& ila_vlg_name, - const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name) override; - - - /// It is okay to instantiation - virtual void do_not_instantiate(void) override { }; - -}; // class VlgVerifTgtGenRelchc - - -}; // namespace ilang - -#endif // VTARGET_GEN_RELCHC_H__ diff --git a/include/ilang/vtarget-out/vtarget_gen_yosys.h b/include/ilang/vtarget-out/vtarget_gen_yosys.h deleted file mode 100644 index ff1f1183a..000000000 --- a/include/ilang/vtarget-out/vtarget_gen_yosys.h +++ /dev/null @@ -1,174 +0,0 @@ -/// \file Verilog Verification Target Generator -- generating CHC target -/// (design-only, same as the invariant target) -/// We use chc to convert Verilog to smt-lib2, and then -/// it will be parsed and re-format by smt-io -/// and use that information, it will create horn clauses -/// This file should not be included, as it requires the impl. -// ---Hongce Zhang - -#ifndef VTARGET_GEN_YOSYS_H__ -#define VTARGET_GEN_YOSYS_H__ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -class VlgSglTgtGen_Yosys; - -/// \brief a class to store (and generate) the problem for Yosys -class Yosys_problem { - friend class VlgSglTgtGen_Yosys; - /// Type of assertions and assumptions - typedef std::vector prop_t; - /// Type of a problem --- we can handle multiple several problems (may not - /// needed) - typedef struct { - // the name in [??] - // std::string problem_name; - /// will be conjuncted and put in the question - prop_t exprs; - } problem_t; - /// set of problems - typedef std::map problemset_t; - -protected: - /// assumptions are not shared (unlike CoSA) - problemset_t assumptions; - /// problems are splitted into items - problemset_t assertions; - -}; // Yosys_problem - -/// \brief a class to interface w. Yosys -class VlgSglTgtGen_Yosys : public VlgSglTgtGen { - -public: - /// using the target type - using target_type_t = VlgSglTgtGen::target_type_t; - /// a tuple to store all related info for modification - using info_t = VerilogModifier::info_t; - /// filename -> (lineno, varname, is_port_sig) vec - using fn_l_map_t = VerilogModifier::fn_l_map_t; - /// Type of advanced parameter - using advanced_parameters_t = VlgVerifTgtGenBase::advanced_parameters_t; - /// Type of yosys target - using _chc_target_t = VlgVerifTgtGenBase::_chc_target_t; - -public: - // --------------------- CONSTRUCTOR ---------------------------- // - /// - /// \param[in] output path (ila-verilog, wrapper-verilog, problem.txt, - /// run-verify-by-???, modify-impl, it there is ) \param[in] pointer to the - /// instruction \param[in] the default configuration for outputing verilog - /// \param[in] the variable map - /// \param[in] the conditions - /// \param[in] pointer to verify info class - /// \param[in] verilog module name - /// \param[in] ila module name, - /// \param[in] all implementation sources - /// \param[in] all include paths - /// \param[in] which backend to use, it needs this info to gen proper - /// properties - VlgSglTgtGen_Yosys( - const std::string& output_path, // will be a sub directory of the - // output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const VerilogGenerator::VlgGenConfig& config, nlohmann::json& _rf_vmap, - nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo& _sup_info, - VerilogInfo* _vlg_info_ptr, const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& include_dirs, - const vtg_config_t& vtg_config, backend_selector vbackend, - const target_type_t& target_tp, advanced_parameters_t* adv_ptr, - _chc_target_t chc_target); - - // --------------------- Destructor ---------------------------- // - /// do nothing - virtual ~VlgSglTgtGen_Yosys(); - -protected: - /// Yosys problem generate - Yosys_problem _problems; - /// Yosys problem file name - std::string prob_fname; - /// Yosys script 'run.sh' name - std::string run_script_name; - /// the synthesis backend - synthesis_backend_selector s_backend; - /// the smt info of the design - std::shared_ptr design_smt_info; - /// whether to require a proof - bool generate_proof; - /// what are the targets - _chc_target_t chc_target; - -protected: - /// Add a direct assumption -- needed by base class - virtual void add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) override; - /// Add a direct assertion -- needed by base class - virtual void add_a_direct_assertion(const std::string& asst, - const std::string& dspt) override; - - /// Pre export work : add assume and asssert to the top level - void virtual PreExportProcess() override; - /// export the script to run the verification - virtual void Export_script(const std::string& script_name) override; - /// export extra things: the chc script, the smt template - virtual void Export_problem(const std::string& extra_name) override; - /// export the memory abstraction (implementation) - /// Yes, this is also implementation specific, (jasper may use a different - /// one) - virtual void Export_mem(const std::string& mem_name) override; - /// For jasper, this means do nothing, for chc, you need to add (*keep*) - virtual void Export_modify_verilog() override; - -private: - /// Convert the smt file to CHC -- datatype encoding - void convert_smt_to_chc_datatype(const std::string& smt_fname, - const std::string& chc_fname); - /// Convert the smt file to CHC -- bitvector encoding - void convert_smt_to_chc_bitvec(const std::string& smt_fname, - const std::string& chc_fname, - const std::string& wrapper_mod_name); - /// generate the wrapper's smt first - void design_only_gen_smt(const std::string& smt_name, - const std::string& ys_script_name); - /// generate the wrapper's btor - void design_only_gen_btor(const std::string& btor_name, - const std::string& ys_script_name); - /// generate the aiger file - void generate_aiger(const std::string& blif_name, - const std::string& aiger_name, - const std::string& map_name, - const std::string& ys_script_name); - -public: - /// overwrite the Export - void virtual ExportAll(const std::string& wrapper_name, - const std::string& ila_vlg_name, - const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name) override; - /// accessor of the design info - std::shared_ptr GetDesignSmtInfo() const; - /// It is okay to instantiation - virtual void do_not_instantiate(void) override{}; - -}; // class VlgVerifTgtGenYosys - -}; // namespace ilang - -#endif // VTARGET_GEN_YOSYS_H__ diff --git a/src/mcm/ast_helper.cc b/src/mcm/ast_helper.cc index ea98f6801..0ed1c1bae 100644 --- a/src/mcm/ast_helper.cc +++ b/src/mcm/ast_helper.cc @@ -8,6 +8,7 @@ #include #include #include +#include namespace ilang { @@ -170,6 +171,10 @@ FunctionApplicationFinder::GetReferredFunc() const { } +bool isSpecialUnknownFunction(const ExprOpAppFunc::FuncPtr & func) { + return StrStartsWith(func->name().str(), "__unknown__"); +} + bool getIteUnknownCondVal(const ExprPtr & e, ExprPtr & c, ExprPtr & v) { if (!e->is_op()) @@ -183,7 +188,7 @@ bool getIteUnknownCondVal(const ExprPtr & e, ExprPtr & c, ExprPtr & v) { if ( (arg1 && arg1->op_name() == "APP") ) { std::shared_ptr apply_op_arg1 = std::dynamic_pointer_cast(arg1); - if ( StateMappingDirectiveRecorder::isSpecialUnknownFunction(apply_op_arg1->func())) { + if ( isSpecialUnknownFunction(apply_op_arg1->func())) { c = eop->arg(0); v = eop->arg(2); return true; @@ -196,7 +201,7 @@ bool getIteUnknownCondVal(const ExprPtr & e, ExprPtr & c, ExprPtr & v) { if ( (arg2 && arg2->op_name() == "APP") ) { std::shared_ptr apply_op_arg2 = std::dynamic_pointer_cast(arg2); - if ( StateMappingDirectiveRecorder::isSpecialUnknownFunction(apply_op_arg2->func())) { + if ( isSpecialUnknownFunction(apply_op_arg2->func())) { c = eop->arg(0); v = eop->arg(1); return true; diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index f611b2c91..cdf748b7b 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -23,7 +23,8 @@ TypedVerilogRefinementMap::TypedVerilogRefinementMap( var_typecheck_t type_checker, const std::string & ila_inst_decode_signal_name, const std::string & ila_valid_signal_name - ) : VerilogRefinementMap(refinement), counter(0), TypeAnalysisUtility(type_checker) { + ) : VerilogRefinementMap(refinement), TypeAnalysisUtility(type_checker), + counter(0) { initialize(ila_inst_decode_signal_name,ila_valid_signal_name); } @@ -34,7 +35,7 @@ TypedVerilogRefinementMap::TypedVerilogRefinementMap( const std::string & ila_inst_decode_signal_name, const std::string & ila_valid_signal_name ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), - counter(0), TypeAnalysisUtility(type_checker) { + TypeAnalysisUtility(type_checker), counter(0) { initialize(ila_inst_decode_signal_name,ila_valid_signal_name); } // TypedVerilogRefinementMap::TypedVerilogRefinementMap @@ -470,7 +471,7 @@ bool _compute_const(const RfExpr & in, unsigned & out) { return false; auto bws = cst_ast_ptr->get_constant(); auto base = std::get<0>(bws); - auto width = std::get<1>(bws); + // auto width = std::get<1>(bws); out = StrToLong(std::get<2>(bws), base); return true; } @@ -618,7 +619,7 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in assert(in->get_child_cnt() == 3); unsigned l,r; - bool succ = _compute_const(in->child(1), l /*ref*/), + bool succ = _compute_const(in->child(1), l /*ref*/); succ = succ && _compute_const(in->child(2), r /*ref*/); if(!succ) return RfMapVarType(); @@ -860,7 +861,7 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr & inout) { assert(inout->get_child_cnt() == 3); unsigned l,r; - bool succ = _compute_const(inout->child(1), l /*ref*/), + bool succ = _compute_const(inout->child(1), l /*ref*/); succ = succ && _compute_const(inout->child(2), r /*ref*/); ILA_ASSERT(succ); diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index dd816c333..7f47ba6d1 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -48,7 +48,7 @@ static size_t find_comments(const std::string& line) { } // load_json and remove the comment, if succeed return true -bool load_json(const std::string& fname, nlohmann::json& j) { +static bool load_json(const std::string& fname, nlohmann::json& j) { std::ifstream fin(fname); if (!fin.is_open()) { @@ -68,6 +68,7 @@ bool load_json(const std::string& fname, nlohmann::json& j) { contents += "\n"; } j = nlohmann::json::parse(contents); + return true; } // load_json @@ -91,7 +92,7 @@ RfExpr VerilogRefinementMap::ParseRfExprFromString(const std::string & in) { RfExpr ParseRfMapExpr(const std::string & in) { // TODO - auto ret = VerilogRefinementMap::ParseRfExprFromString(in) + auto ret = VerilogRefinementMap::ParseRfExprFromString(in); if (ret == nullptr) ParseRfExprErrFlag = true; return ret; @@ -297,7 +298,7 @@ unsigned gcd(unsigned a, unsigned b) { // least common multiplier unsigned lcm(const std::vector & in) { unsigned ans = in.at(0); - for(int i = 1; i < in.size(); ++i) { + for(size_t i = 1; i < in.size(); ++i) { ans = ((in.at(i)*ans)/gcd(in.at(i),ans)); } return ans; @@ -1062,8 +1063,6 @@ bool VerilogRefinementMap::SelfCheckField() const { for (const auto & n_st : phase_tracker) { for (const auto & var_def : n_st.second.event_alias ) { - all_var_def_types.emplace(var_def.first) - ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); var_def_names.insert(var_def.first); } @@ -1074,13 +1073,13 @@ bool VerilogRefinementMap::SelfCheckField() const { } for (const auto & n_st : value_recorder) { ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); - ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); - monitor_names.insert(n_st.first); + ERRIF( IN(n_st.first, var_def_names) , "Monitor name " + n_st.first + " has been used" ); + var_def_names.insert(n_st.first); } for (const auto & n_st : customized_monitor) { ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); - ERRIF( IN(n_st.first, monitor_names) , "Monitor name " + n_st.first + " has been used" ); - monitor_names.insert(n_st.first); + ERRIF( IN(n_st.first, var_def_names) , "Monitor name " + n_st.first + " has been used" ); + var_def_names.insert(n_st.first); for (const auto & var_def : n_st.second.var_defs ) { ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); @@ -1088,6 +1087,7 @@ bool VerilogRefinementMap::SelfCheckField() const { } } } + return true; // no need to check for inst_cond } // bool VerilogRefinementMap::SelfCheck() const diff --git a/src/vtarget-out/.gitignore b/src/vtarget-out/.gitignore index dcd1b5ed4..d8f4c5a86 100644 --- a/src/vtarget-out/.gitignore +++ b/src/vtarget-out/.gitignore @@ -1,2 +1,2 @@ NOTE.txt - +deprecated/* diff --git a/src/vtarget-out/CMakeLists.txt b/src/vtarget-out/CMakeLists.txt index 867b8bff9..6ad93c1f9 100644 --- a/src/vtarget-out/CMakeLists.txt +++ b/src/vtarget-out/CMakeLists.txt @@ -14,10 +14,8 @@ target_sources(${ILANG_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/single_target_misc.cc ${CMAKE_CURRENT_SOURCE_DIR}/single_target_cond.cc ${CMAKE_CURRENT_SOURCE_DIR}/single_target_inv_syn_support.cc - ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_cosa.cc + ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_pono.cc ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_jasper.cc - ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_yosys.cc - ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_relchc.cc ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen.cc ${CMAKE_CURRENT_SOURCE_DIR}/vlg_mod.cc ${CMAKE_CURRENT_SOURCE_DIR}/design_stat.cc diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index a85f08661..adccfed75 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -155,6 +155,54 @@ unsigned VlgSglTgtGen::get_width(const ExprPtr& n) { } +rfmap::RfVarTypeOrig VlgSglTgtGen::VarTypeCheckForRfExprParsing(const std::string & vname) { + + if(StrStartsWith(vname,"ILA.")) { + rfmap::RfVarTypeOrig ret; + if(TryFindIlaInput(vname)) { + const ExprPtr ila_input_ptr = IlaGetInput(vname.substr(4)); + ret.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::ILAI; + + ret.type = rfmap::RfMapVarType( + ila_input_ptr->is_bool() ? + 1 : ila_input_ptr->sort()->bit_width()); + return ret; + } else if(TryFindIlaState(vname)) { + const ExprPtr ila_sv_ptr = IlaGetState(vname.substr(4)); + ret.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::ILAS; + if(ila_sv_ptr->is_bool()) + ret.type = rfmap::RfMapVarType(1); + else if (ila_sv_ptr->is_bv()) + ret.type = rfmap::RfMapVarType(ila_sv_ptr->sort()->bit_width()); + else { + ILA_ASSERT(ila_sv_ptr->is_mem()); + ret.type = rfmap::RfMapVarType(ila_sv_ptr->sort()->addr_width(), + ila_sv_ptr->sort()->data_width()); + } + return ret; + } + ILA_ERROR << "Cannot find ila var: " << vname; + return ret; + } // else if + if (StrStartsWith(vname,"RTL.")) { + ILA_ERROR_IF(!TryFindVlgState(vname)) << "Cannot find rtl var: " << vname; + auto sig_info = vlg_info_ptr->get_signal(vname); + auto aw = sig_info.get_addr_width(); + auto dw = sig_info.get_width(); + + rfmap::RfVarTypeOrig ret; + ret.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::RTLV; + if(aw == 0) // not an array + ret.type = rfmap::RfMapVarType(dw); + else + ret.type = rfmap::RfMapVarType(aw,dw); + return ret; + } + + //if(!StrStartsWith(vname,"ILA.") && !StrStartsWith(vname,"RTL.")) + return rfmap::RfVarTypeOrig(); // unknown +} // VarTypeCheckForRfExprParsing + std::string VlgSglTgtGen::ReplExpr(const rfmap::RfExpr & in) { bool replace_dot = _backend != VlgSglTgtGen::backend_selector::JASPERGOLD; @@ -385,125 +433,6 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, #undef ADD_CONSTR } // end of Gen_varmap_assumpt_assert -// ila-state -> ref (json) -// return a verilog verilog, that should be asserted to be true for this purpose -std::string VlgSglTgtGen::GetStateVarMapExpr(const std::string& ila_state_name, - nlohmann::json& m, - bool is_assert) { - if (m.is_null()) - return VLG_TRUE; - if (m.is_string()) { - std::string rfm = m.get(); - if (_sdr.isSpecialStateDir(rfm)) { - // currently we only support **MEM** as state directive - if (!_sdr.isSpecialStateDirMem(rfm)) { - ILA_ERROR << "Unsupported state directive:" << rfm; - return VLG_TRUE; - } - ILA_DLOG("VlgSglTgtGen.GetStateVarMapExpr") - << "map mem:" << ila_state_name; - - bool external = _vlg_cfg.extMem; - if (IN(ila_state_name, supplementary_info.memory_export)) - external = supplementary_info.memory_export.at(ila_state_name); - - ILA_ERROR_IF(!external) - << "Should not use MEM directive since this memory is internal:" - << ila_state_name; - // may be we need to log them here - if (is_assert == false) { - _idr.SetMemName(rfm, ila_state_name, _vtg_config.MemAbsReadAbstraction); - return VLG_TRUE; // no need for assumptions on memory - } - // handle memory: map vlg_ila.ila_wports && vlg_ila.ila_rports with - // _idr.abs_mems - - auto ila_state = TryFindIlaVarName(ila_state_name); - if (!ila_state) { - ILA_ERROR << ila_state_name << " does not exist in ILA."; - return VLG_TRUE; - } - if (!ila_state->sort()->is_mem()) { - ILA_ERROR << ila_state_name << " is not memory, not compatible w. " - << rfm; - return VLG_TRUE; - } - // if expand memory, it will not reach this point - // but will on the per_state_map branch - auto mem_eq_assert = _idr.ConnectMemory( - rfm, ila_state_name, vlg_ila.ila_rports[ila_state_name], - vlg_ila.ila_wports[ila_state_name], ila_state->sort()->addr_width(), - ila_state->sort()->data_width(), _vtg_config.MemAbsReadAbstraction); - // wire will be added by the absmem - return mem_eq_assert; - } else { - // return the mapping variable - return PerStateMap(ila_state_name, rfm); - } - } /* else */ - if (m.is_array()) { // array of string or array of object/array - std::vector all_mappings; - std::string prev_neg; // make sure it is a priority condition lists - - for (auto& num_item_pair : m.items()) { - auto& item = num_item_pair.value(); - if (item.is_string()) { - auto mapping = ReplExpr(item.get()); - all_mappings.push_back(mapping); - } else if (item.is_array() || - item.is_object()) { // it should only by size of 2 - std::string cond(VLG_TRUE), vmap(VLG_TRUE); - for (const auto& i : (item).items()) { - if (i.key() == "0" || i.key() == "cond") { - if (i.value().is_null()) - continue; - else if (i.value().is_string()) { - cond = ReplExpr(i.value().get()); // set the condtion - continue; - } else { - ILA_ERROR - << "Expecting the first element/`cond` to be a string/null"; - continue; - } - } - if (i.key() == "1" || i.key() == "map") { - if (i.value().is_null()) - continue; - else if (i.value().is_string()) { - vmap = PerStateMap(ila_state_name, i.value().get()); - continue; // set the mapping - } else { - ILA_ERROR - << "Expecting the second element/`map` to be a string/null"; - continue; - } - } - ILA_ERROR << "mapping for statename:" << ila_state_name - << " contains unsupported construct."; - break; - } - // cond ==> vmap i.e. ~cond || vmap - all_mappings.push_back("~ (" + prev_neg + "(" + cond + ") ) || (" + - vmap + ")"); - prev_neg += "~(" + cond + ")&&"; - } else { - ILA_ERROR << "Unable to handle this piece of JSON input:" << item; - return VLG_TRUE; - } - } // for (item in m) - - if (all_mappings.size() == 0) { - ILA_ERROR << "Variable mapping for " << ila_state_name << " is empty!"; - return VLG_TRUE; - } - - return "(" + Join(all_mappings, " )&&( ") + ")"; - } // if it is an array - - // fall-through case - ILA_ERROR << "Unable to handle this piece of JSON input:" << m; - return VLG_TRUE; -} // GetStateVarMapExpr void VlgSglTgtGen::handle_start_condition(const std::vector & dc) { for (const auto & c : dc) { diff --git a/src/vtarget-out/inv-syn/CMakeLists.txt b/src/vtarget-out/inv-syn/CMakeLists.txt index 7afb999ae..55f6b41ca 100644 --- a/src/vtarget-out/inv-syn/CMakeLists.txt +++ b/src/vtarget-out/inv-syn/CMakeLists.txt @@ -5,15 +5,10 @@ target_sources(${ILANG_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cex_extract.cc - ${CMAKE_CURRENT_SOURCE_DIR}/rel_chc.cc ${CMAKE_CURRENT_SOURCE_DIR}/inv_obj.cc ${CMAKE_CURRENT_SOURCE_DIR}/inv_cnf.cc ${CMAKE_CURRENT_SOURCE_DIR}/inv_abc_parse.cc - ${CMAKE_CURRENT_SOURCE_DIR}/inv_syn_cegar.cc ${CMAKE_CURRENT_SOURCE_DIR}/grain_inv_parse.cc - ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_inv_chc.cc - ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_inv_abc.cc - ${CMAKE_CURRENT_SOURCE_DIR}/vtarget_gen_inv_enhance.cc ) diff --git a/src/vtarget-out/inv-syn/inv_syn_cegar.cc b/src/vtarget-out/inv-syn/inv_syn_cegar.cc deleted file mode 100644 index 10387a241..000000000 --- a/src/vtarget-out/inv-syn/inv_syn_cegar.cc +++ /dev/null @@ -1,936 +0,0 @@ -/// \file Source for invariant synthesis --- using CEGAR loop -// Hongce Zhang - -#include -#ifdef INVSYN_INTERFACE - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace ilang { - -static std::string select_script_to_run(const std::vector& scripts, - const std::string& sel) { - ILA_CHECK(!sel.empty()) << "no selection is provided in RunVerifAuto"; - std::vector sels; - for (auto&& sc : scripts) - if (S_IN(sel, sc)) - sels.push_back(sc); - ILA_CHECK(!sels.empty()) << "Auto run: no selection!"; - if (sels.size() > 1) { - ILA_ERROR << "Multi scripts selected!"; - for (auto&& sc : sels) - ILA_ERROR << sc; - ILA_CHECK(false); - } - return sels[0]; -} - -// problem: you cannot create and keep the objs -// so you need to keep the infos -InvariantSynthesizerCegar::InvariantSynthesizerCegar( - const std::vector& implementation_include_path, - const std::vector& implementation_srcs, - const std::string& implementation_top_module, - const std::string& refinement_variable_mapping, - const std::string& refinement_conditions, const std::string& output_path, - const InstrLvlAbsPtr& ila_ptr, verify_backend_selector vbackend, - synthesis_backend_selector sbackend, const vtg_config_t& vtg_config, - const VerilogGenerator::VlgGenConfig& config) - : status(cegar_status::NEXT_V), bad_state(false), round_id(0), - // book-keeping - implementation_incl_path(implementation_include_path), - implementation_srcs_path(implementation_srcs), - implementation_top_module_name(implementation_top_module), - refinement_variable_mapping_path(refinement_variable_mapping), - refinement_condition_path(refinement_conditions), - _output_path(output_path), _host(ila_ptr), v_backend(vbackend), - s_backend(sbackend), _vtg_config(vtg_config), _vlg_config(config), - // ------------ statistics bookkeeping --------------- // - eqcheck_time(0), inv_validate_time(0), inv_proof_attempt_time(0), - inv_syn_time(0), inv_enhance_time(0), total_grain_cand(0) { - // detect some wrong settings here - if (vbackend != verify_backend_selector::COSA) { - ILA_ERROR << "Implementation bug: currently only support COSA."; - bad_state = true; - return; - } - // BUG: should also consider Yosys single inv? - - // we need to have the vcd generated - _vtg_config.CosaGenTraceVcd = true; - // for other backend, enable similar options - - current_inv_type = cur_inv_tp::NONE; - -} // end of constructor - -bool InvariantSynthesizerCegar::check_in_bad_state() const { - ILA_ERROR_IF(bad_state) << "In bad state, cannot proceed."; - return bad_state; -} - -// -------------------------------- VERIFICATION TARGETS -// ------------------------------------------- // - -/// to generate a target to validate the given and synthesize invariants and -/// guessed ones -void InvariantSynthesizerCegar::GenerateInvariantVerificationTarget() { - if (check_in_bad_state()) - return; - - // to send in the invariants - advanced_parameters_t adv_param; - adv_param._inv_obj_ptr = &inv_obj; - adv_param._candidate_inv_ptr = &inv_candidate; - - auto inv_gen_vtg_config = _vtg_config; - inv_gen_vtg_config.target_select = inv_gen_vtg_config.INV; - // no overwite - // inv_gen_vtg_config.ValidateSynthesizedInvariant = - // vtg_config_t::_validate_synthesized_inv::ALL; // overwrite - - VlgVerifTgtGen vg(implementation_incl_path, // include - implementation_srcs_path, // sources - implementation_top_module_name, // top_module_name - refinement_variable_mapping_path, // variable mapping - refinement_condition_path, // conditions - _output_path, // output path - _host, // ILA - v_backend, // verification backend setting - inv_gen_vtg_config, // target configuration - _vlg_config, // verilog generator configuration - &adv_param // advanced parameter - ); - - vg.GenerateTargets(); -} - -// the reason we need to do this is that we need to know -// in the verilog design, which is (true)reg, which is not (true)reg -void InvariantSynthesizerCegar::GenerateTargetAndExtractSmt() { - // generate a target -- based on selection - if (check_in_bad_state()) - return; - - // to send in the invariants - advanced_parameters_t adv_param; - adv_param._inv_obj_ptr = NULL; - adv_param._candidate_inv_ptr = NULL; - - VlgVerifTgtGen vg( - implementation_incl_path, // include - implementation_srcs_path, // sources - implementation_top_module_name, // top_module_name - refinement_variable_mapping_path, // variable mapping - refinement_condition_path, // conditions - _output_path, // output path - _host, // ILA - verify_backend_selector::YOSYS, // verification backend setting - _vtg_config, // target configuration - _vlg_config, // verilog generator configuration - &adv_param // advanced parameter - ); - - // design_smt_info = vg.GenerateSmtTargets(); -} - -unsigned -InvariantSynthesizerCegar::QueryRtlStateWidth(const std::string& name) const { - if (design_smt_info == nullptr) - return 0; - const auto& sts = design_smt_info->get_var_idx(); - auto pos = sts.find(name); - if (pos == sts.end()) - return 0; - return pos->second->_type.GetBoolBvWidth(); -} - -// to do things separately, you can provide the run function yourself -// or even do it step by step -/// to generate targets using the current invariants -void InvariantSynthesizerCegar::GenerateVerificationTarget() { - // generate a target -- based on selection - if (check_in_bad_state()) - return; - ILA_WARN_IF(status != cegar_status::NEXT_V) - << "CEGAR-loop: repeated verification step."; - - // to send in the invariants - advanced_parameters_t adv_param; - adv_param._inv_obj_ptr = &inv_obj; - adv_param._candidate_inv_ptr = &inv_candidate; - - VlgVerifTgtGen vg(implementation_incl_path, // include - implementation_srcs_path, // sources - implementation_top_module_name, // top_module_name - refinement_variable_mapping_path, // variable mapping - refinement_condition_path, // conditions - _output_path, // output path - _host, // ILA - v_backend, // verification backend setting - _vtg_config, // target configuration - _vlg_config, // verilog generator configuration - &adv_param // advanced parameter - ); - - vg.GenerateTargets(); - - vlg_mod_inst_name = vg.GetVlgModuleInstanceName(); - inv_obj.set_dut_inst_name(vlg_mod_inst_name); - inv_candidate.set_dut_inst_name(vlg_mod_inst_name); - - runnable_script_name = vg.GetRunnableScriptName(); - if (additional_width_info.empty()) - additional_width_info = vg.GetSupplementaryInfo().width_info; - - status = cegar_status::V_RES; -} - -/// to generate targets using the provided invariants -void InvariantSynthesizerCegar::GenerateVerificationTarget( - const std::vector& invs) { - for (auto&& inv : invs) - inv_obj.AddInvariantFromVerilogExpr(std::to_string(round_id), inv); - GenerateVerificationTarget(); -} // to generate targets using the provided invariants - -// -------------------------------- CHC SYNTHESIS TARGETS -// ------------------------------------------- // - -/// to generate synthesis target -void InvariantSynthesizerCegar::GenerateSynthesisTarget() { - // generate a target -- based on selection - if (check_in_bad_state()) - return; - ILA_WARN_IF(status != cegar_status::NEXT_S) - << "CEGAR-loop: not expecting synthesis step."; - - // to send in the invariants - advanced_parameters_t adv_param; - adv_param._inv_obj_ptr = &inv_obj; - adv_param._candidate_inv_ptr = NULL; - adv_param._cex_obj_ptr = cex_extract.get(); - - VlgVerifTgtGen vg( - implementation_incl_path, // include - implementation_srcs_path, // sources - implementation_top_module_name, // top_module_name - refinement_variable_mapping_path, // variable mapping - refinement_condition_path, // conditions - _output_path, // output path - _host, // ILA - verify_backend_selector::YOSYS, // verification backend setting - _vtg_config, // target configuration - _vlg_config, // verilog generator configuration - &adv_param // advanced parameter - ); - - if (s_backend == synthesis_backend_selector::ABC) { - vg.GenerateInvSynTargetsAbc(_vtg_config.AbcUseGla, _vtg_config.AbcUseCorr, - _vtg_config.AbcUseAiger); - current_inv_type = cur_inv_tp::CEGAR_ABC; - } else { - design_smt_info = vg.GenerateInvSynTargets(s_backend); // general chc - current_inv_type = s_backend == synthesis_backend_selector::GRAIN - ? cur_inv_tp::GRAIN_CHC - : cur_inv_tp::CHC; - } - - runnable_script_name = vg.GetRunnableScriptName(); - - status = cegar_status::S_RES; - -} // GenerateSynthesisTarget - -static int inline retrieveColonEol(const std::string& msg, - const std::string& label) { - size_t pos_1, endl_1; - pos_1 = msg.find(label); - endl_1 = msg.find('\n', pos_1); - return StrToInt(msg.substr(pos_1 + label.length(), endl_1)); -} - -const InvariantInCnf& InvariantSynthesizerCegar::GetCurrentCnfEnhance() const { - return inv_cnf; -} -/// merge cnfs -void InvariantSynthesizerCegar::MergeCnf( - const InvariantInCnf& incremental_cnf) { - inv_cnf.InsertClauseIncremental(incremental_cnf); -} - -/// extra variable for enhancement, so not really a cnf -void InvariantSynthesizerCegar::ExtractInvariantVarForEnhance( - size_t inv_idx, InvariantInCnf& incremental_cnf, bool per_clause, - const std::set& vars_to_remove) { - ILA_CHECK(inv_idx < inv_obj.NumInvariant()); - const auto& inv_vlg = inv_obj.GetVlgConstraints().at(inv_idx); - VarExtractor vext( - [](const std::string& s) -> bool { return false; }, // not ila input - [](const std::string& s) -> bool { return false; }, // not ila state - [](const std::string& scalbln) -> bool { - return true; - } // but verilog state - ); - vext.ParseToExtract(inv_vlg, true); // force verilog state - - InvariantInCnf::clause cl; - std::set v_in_this_cl; - vext.ForEachTokenReplace( - [&cl, &incremental_cnf, &v_in_this_cl, per_clause, - &vars_to_remove](const VarExtractor::token& t) -> std::string { - if (per_clause && t.second.find("&&") != t.second.npos) { - incremental_cnf.InsertClause(cl); - cl.clear(); - v_in_this_cl.clear(); - } - if (t.first != VarExtractor::token_type::VLG_S) - return t.second; - const auto& vname = t.second; - auto pos = vname.rfind('['); - std::string vn = vname; - if (pos != vname.npos) - vn = vname.substr(0, pos); - if (!IN(vn, v_in_this_cl) && !(IN(vn, vars_to_remove))) { - cl.push_back(std::make_tuple(false, vn, 0U)); - v_in_this_cl.insert(vn); - } - return t.second; - }); - incremental_cnf.InsertClause(cl); -} - -bool InvariantSynthesizerCegar::WordLevelEnhancement( - const InvariantInCnf& incremental_cnf, bool under_test) { - if (check_in_bad_state()) - return false; - // to send in the invariants - advanced_parameters_t adv_param; - adv_param._inv_obj_ptr = &inv_obj; - adv_param._candidate_inv_ptr = NULL; - adv_param._cex_obj_ptr = cex_extract.get(); - // TODO: - // generate grain (enhance) target - // run the script - // extract the result - std::vector runnable_scripts; - { // generate grain target - VlgVerifTgtGen vg( - implementation_incl_path, // include - implementation_srcs_path, // sources - implementation_top_module_name, // top_module_name - refinement_variable_mapping_path, // variable mapping - refinement_condition_path, // conditions - _output_path, // output path - _host, // ILA - verify_backend_selector::YOSYS, // verification backend setting - _vtg_config, // target configuration - _vlg_config, // verilog generator configuration - &adv_param // advanced parameter - ); - - design_smt_info = vg.GenerateInvSynEnhanceTargets(incremental_cnf); - runnable_scripts = vg.GetRunnableScriptName(); - } // generate grain target - - // merge the cnfs - // incremental_cnf.Clear(); - - ILA_CHECK(runnable_scripts.size() == 1) - << "BUG: GenerateInvSynEnhanceTargets should create only 1 target " - "script "; - auto synthesis_result_fn = - os_portable_append_dir(_output_path, "__enhance_result.txt"); - auto redirect_fn = os_portable_append_dir("../", "__enhance_result.txt"); - - auto cwd = os_portable_getcwd(); - auto new_wd = os_portable_path_from_path(runnable_scripts[0]); - ILA_ERROR_IF(!os_portable_chdir(new_wd)) - << "WordLevelEnhancement: cannot change dir to:" << new_wd; - ILA_INFO << "Executing script:" << runnable_scripts[0]; - execute_result res; - - if (under_test) { - res.subexit_normal = true; - res.seconds = 0; - res.ret = 0; - res.failure = res.NONE; - res.timeout = false; - } else - res = os_portable_execute_shell( - {"bash", os_portable_file_name_from_path(runnable_scripts[0])}, - redirect_fn, redirect_t::BOTH); - - ILA_ERROR_IF(res.failure != execute_result::NONE) - << "Running synthesis script " << runnable_scripts[0] - << " results in error."; - ILA_CHECK(os_portable_chdir(cwd)); - - inv_enhance_time += res.seconds; - // inv_syn_time_series.push_back(res.seconds); - - bool freq_enhance_okay = false; - { // run grain - std::stringstream sbuf; - std::ifstream fin(synthesis_result_fn); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read the synthesis result file:" - << synthesis_result_fn; - freq_enhance_okay = false; - } else { - sbuf << fin.rdbuf(); - freq_enhance_okay = - S_IN("proved", sbuf.str()) || S_IN("proven", sbuf.str()); - if (S_IN("unknown", sbuf.str())) - freq_enhance_okay = false; - if (freq_enhance_okay) { - ILA_INFO << "Enhance Info: Lemma/Gen/Spec = " - << retrieveColonEol(sbuf.str(), "learned lemmas:") << " " - << retrieveColonEol(sbuf.str(), "TotalGen:") << " " - << retrieveColonEol(sbuf.str(), "TotalSpec:") << " " - << retrieveColonEol(sbuf.str(), "TotalCand:"); - total_grain_cand += retrieveColonEol(sbuf.str(), "TotalCand:"); - } - } - } // end of grain chc result - // else reachable - if (!freq_enhance_okay) - return false; - - if (design_smt_info == nullptr) { - ILA_ERROR << "BUG: Design SMT-LIB2 info is not available. "; - return false; - } - inv_obj.AddInvariantFromGrainResultFile( - *(design_smt_info.get()), "", - os_portable_append_dir(_output_path, "grain.result"), true, true); - - // you also need to merge CNF - status = cegar_status::NEXT_V; - return true; -} - -// -------------------------------- EXTRACTIONS -// ------------------------------------------- // - -/// to extract result -void InvariantSynthesizerCegar::ExtractVerificationResult( - bool autodet, bool pass, const std::string& vcd_file, - const std::string& mod_inst_name) { - if (check_in_bad_state()) - return; - - std::string res_file = vcd_file; - if (autodet) { - res_file = vcd_file_name; - pass = verification_pass; - } - ILA_WARN_IF(status != cegar_status::V_RES) - << "CEGAR-loop: repeated verification step."; - - vlg_mod_inst_name = - vlg_mod_inst_name.empty() ? mod_inst_name : vlg_mod_inst_name; - if (vlg_mod_inst_name.empty()) { - ILA_ERROR << "Instance name in vcd is unknown and not specified"; - bad_state = true; - return; - } - - if (pass) { - ILA_INFO << "No counterexample has been found. CEGAR loop finishes."; - status = cegar_status::DONE; - return; - } - - // we still need to create a verilog info analyzer - VerilogAnalyzer va(implementation_incl_path, implementation_srcs_path, - vlg_mod_inst_name, implementation_top_module_name); - - auto is_reg = [&](const std::string& n) -> bool { - if (!VerilogAnalyzerBase::is_reg(va.check_hierarchical_name_type(n))) - return false; - if (design_smt_info) // if available we will use it - return design_smt_info->is_state_name(n); - return true; // if not available - }; - - // not passing - cex_extract = std::unique_ptr(new CexExtractor( - res_file, vlg_mod_inst_name, is_reg, !_vtg_config.CosaFullTrace)); - // advance to synthesis stage - status = cegar_status::NEXT_S; -} // extract result - -/// a helper function (only locally available) -/// to extract vcd file name from the output -std::string extract_vcd_name_from_cex(const std::string& fn) { - std::ifstream fin(fn); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read from:" << fn; - return ""; - } - std::string line; - while (std::getline(fin, line)) { - if (S_IN("*** TRACES ***", line)) - break; - } - if (fin.eof()) { - ILA_ERROR << "Cannot extract vcd filename, incorrect format, expecting *** " - "TRACES ***"; - return ""; - } - std::string fname; - fin >> fname; - fin >> fname; // the first is garbage; - ILA_ERROR_IF(!S_IN(".vcd", fname)) - << "Expecting vcd file name, get " << fname; - return fname; -} // extract_vcd_name_from_cex - -void InvariantSynthesizerCegar::CexGeneralizeRemoveStates( - const std::vector& n) { - cex_extract->DropStates(n); -} - -void InvariantSynthesizerCegar::ExtractAbcSynthesisResultForEnhancement( - InvariantInCnf& incremental_cnf, bool autodet, bool reachable) { - - if (check_in_bad_state()) - return; - - if (autodet) { - reachable = cex_reachable; - } - - ILA_WARN_IF(status != cegar_status::S_RES) - << "CEGAR-loop: expecting synthesis result."; - - if (reachable) { - ILA_ERROR << "Verification failed with true counterexample!"; - status = cegar_status::FAILED; - return; - } - ILA_CHECK(current_inv_type == cur_inv_tp::CEGAR_ABC) - << "Can only work with CEGAR ABC!"; - // the incremental CNF here - ILA_CHECK(inv_candidate.AddInvariantFromAbcResultFile( - _vtg_config.AbcUseAiger - ? os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), - "__aiger_prepare.blif") - : os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), - "wrapper.blif"), - os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), "ffmap.info"), - true, true, - _vtg_config.AbcUseGla - ? os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), - "glamap.info") - : "", - _vtg_config.AbcUseAiger, - _vtg_config.AbcUseAiger - ? os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), - "wrapper.aig.map") - : "", - incremental_cnf, inv_cnf) // incrementally add cnf - ) - << "Extracting of invariant failed!"; - - current_inv_type = cur_inv_tp::NONE; // we have extracted, reset this marker -} // ExtractAbcSynthesisResultForEnhancement - -void InvariantSynthesizerCegar::ExtractSynthesisResult( - bool autodet, bool reachable, const std::string& given_smt_chc_result_txt) { - - if (check_in_bad_state()) - return; - - std::string res_file = given_smt_chc_result_txt; - if (autodet) { - reachable = cex_reachable; - res_file = synthesis_result_fn; - } - - ILA_WARN_IF(status != cegar_status::S_RES) - << "CEGAR-loop: expecting synthesis result."; - - if (reachable) { - ILA_ERROR << "Verification failed with true counterexample!"; - status = cegar_status::FAILED; - return; - } - - if (current_inv_type == cur_inv_tp::CHC) { - if (design_smt_info == nullptr) { - ILA_ERROR << "Design SMT-LIB2 info is not available. " - << "You need to run `GenerateSynthesisTarget` or Parse a " - "design smt first first."; - return; - } - ILA_CHECK(inv_obj.AddInvariantFromChcResultFile - (*(design_smt_info.get()), "", - res_file, - _vtg_config.YosysSmtFlattenDatatype, - _vtg_config.YosysSmtFlattenHierarchy)); - } else if (current_inv_type == cur_inv_tp::GRAIN_CHC) { - if (design_smt_info == nullptr) { - ILA_ERROR << "Design SMT-LIB2 info is not available. " - << "You need to run `GenerateSynthesisTarget` or Parse a " - "design smt first first."; - return; - } - inv_obj.AddInvariantFromGrainResultFile( - *(design_smt_info.get()), "", - os_portable_append_dir(_output_path, "grain.result"), true, true); - } else if (current_inv_type == cur_inv_tp::CEGAR_ABC) { - ILA_CHECK(inv_obj.AddInvariantFromAbcResultFile( - _vtg_config.AbcUseAiger - ? os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), - "__aiger_prepare.blif") - : os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), - "wrapper.blif"), - os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), "ffmap.info"), - true, true, - _vtg_config.AbcUseGla - ? os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), - "glamap.info") - : "", - _vtg_config.AbcUseAiger, - _vtg_config.AbcUseAiger - ? os_portable_append_dir( - os_portable_path_from_path(runnable_script_name[0]), - "wrapper.aig.map") - : "", - inv_cnf, InvariantInCnf())) - << "Extracting of invariant failed!"; - } else - ILA_ERROR << "Inv type unknown:" << current_inv_type; - - std::cout << "Confirmed synthesized invariants:" << std::endl; - for (auto&& v : inv_obj.GetVlgConstraints()) - std::cout << v << std::endl; - - status = cegar_status::NEXT_V; - current_inv_type = cur_inv_tp::NONE; // we have extracted, reset this marker - -} // ExtractSynthesisResult - -// -------------------------------- AUTO RUNS -// ------------------------------------------- // - -/// a helper function (only locally available) -/// to detect tool error (e.g., verilog parsing error) -bool static has_verify_tool_error_cosa(const std::string& fn) { - std::ifstream fin(fn); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read from:" << fn; - return true; - } - - std::string line; - while (std::getline(fin, line)) { - if (S_IN("See yosys-err.log for more info.", line)) - return true; - } - return false; -} // has_verify_tool_error_cosa - -/// a helper function (only locally available) -/// to detect tool error (e.g., verilog parsing error) -bool static has_verify_tool_unknown_cosa(const std::string& fn) { - std::ifstream fin(fn); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read from:" << fn; - return true; - } - - std::string line; - while (std::getline(fin, line)) { - if (S_IN("UNKNOWN != TRUE <<<---------| ERROR", line)) - return true; - } - return false; -} // has_verify_tool_error_cosa -/// run Verification -bool InvariantSynthesizerCegar::RunVerifAuto( - const std::string& script_selection, const std::string& pid_fname, - bool under_test, unsigned timeout) { - auto script_sel = - select_script_to_run(runnable_script_name, script_selection); - if (check_in_bad_state()) - return true; - // Not implemented - auto result_fn = - os_portable_append_dir(_output_path, "__verification_result.txt"); - auto redirect_fn = os_portable_append_dir("..", "__verification_result.txt"); - auto cwd = os_portable_getcwd(); - auto new_wd = os_portable_path_from_path(script_sel); - ILA_ERROR_IF(!os_portable_chdir(new_wd)) - << "RunVerifAuto: cannot change dir to:" << new_wd; - ILA_INFO << "Executing verify script:" << script_sel; - - execute_result res; - if (under_test) { - res.subexit_normal = true; - res.seconds = 0; - res.ret = 0; - res.failure = res.NONE; - res.timeout = false; - } else { - res = os_portable_execute_shell( - {"bash", os_portable_file_name_from_path(script_sel)}, redirect_fn, - redirect_t::BOTH, timeout, pid_fname); - } - - ILA_ERROR_IF(res.failure != execute_result::NONE) - << "Running verification script " << script_sel << " results in error."; - ILA_CHECK(os_portable_chdir(cwd)); - // the last line contains the result - // above it you should have *** TRACES *** - // the vcd file resides within the new dir - ILA_ERROR_IF(has_verify_tool_error_cosa(result_fn)) - << "----------- Verification tool reported error! Please check the log " - "output!"; - ILA_ERROR_IF(has_verify_tool_unknown_cosa(result_fn)) - << "UNKNOWN Verif result"; - - eqcheck_time += res.seconds; - - auto lastLine = os_portable_read_last_line(result_fn); - ILA_ERROR_IF(lastLine.empty()) << "Unable to extract verification result."; - if (S_IN("Verifications with unexpected result", lastLine)) { - ILA_INFO << "Counterexample found."; - - vcd_file_name = extract_vcd_name_from_cex(result_fn); - vcd_file_name = os_portable_append_dir(new_wd, vcd_file_name); - - verification_pass = false; - return false; - } - verification_pass = true; - status = cegar_status::DONE; - ILA_INFO << "No counterexample has been found. CEGAR loop finishes."; - return true; -} - -/// run Synthesis -bool InvariantSynthesizerCegar::RunSynAuto(bool under_test) { - if (check_in_bad_state()) - return true; - - ILA_CHECK(runnable_script_name.size() == 1) - << "Please run GenerateInvSynTargets function first"; - synthesis_result_fn = - os_portable_append_dir(_output_path, "__synthesis_result.txt"); - auto redirect_fn = os_portable_append_dir("..", "__synthesis_result.txt"); - - auto cwd = os_portable_getcwd(); - auto new_wd = os_portable_path_from_path(runnable_script_name[0]); - ILA_ERROR_IF(!os_portable_chdir(new_wd)) - << "RunSynAuto: cannot change dir to:" << new_wd; - ILA_INFO << "Executing synthesis script:" << runnable_script_name[0]; - - execute_result res; - if (under_test) { - res.subexit_normal = true; - res.seconds = 0; - res.ret = 0; - res.failure = res.NONE; - res.timeout = false; - } else { - res = os_portable_execute_shell( - {"bash", os_portable_file_name_from_path(runnable_script_name[0])}, - redirect_fn, redirect_t::BOTH); - } - - ILA_ERROR_IF(res.failure != execute_result::NONE) - << "Running synthesis script " << runnable_script_name[0] - << " results in error."; - ILA_CHECK(os_portable_chdir(cwd)); - - inv_syn_time += res.seconds; - inv_syn_time_series.push_back(res.seconds); - - if (current_inv_type == CEGAR_ABC) { - std::stringstream sbuf; - std::ifstream fin(synthesis_result_fn); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read the synthesis result file:" - << synthesis_result_fn; - status = cegar_status::FAILED; - bad_state = true; - return true; // reachable - } - sbuf << fin.rdbuf(); - cex_reachable = !(S_IN("Property proved.", sbuf.str()) && - S_IN("Invariant contains ", sbuf.str())); - } else if (current_inv_type == GRAIN_CHC) { - std::stringstream sbuf; - std::ifstream fin(synthesis_result_fn); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read the synthesis result file:" - << synthesis_result_fn; - status = cegar_status::FAILED; - bad_state = true; - return true; // reachable - } - sbuf << fin.rdbuf(); - cex_reachable = !(S_IN("proved", sbuf.str())); - if (S_IN("unknown", sbuf.str())) - cex_reachable = true; - // count cands - total_grain_cand += retrieveColonEol(sbuf.str(), "TotalCand:"); - } else { - std::string line; - { // read the result - std::ifstream fin(synthesis_result_fn); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read the synthesis result file:" - << synthesis_result_fn; - status = cegar_status::FAILED; - bad_state = true; - return true; // reachable - } - std::getline(fin, line); - } // finish file reading - cex_reachable = true; - if (S_IN("unsat", line)) - cex_reachable = false; // not reachable - } - // else reachable - return cex_reachable; -} - -// -------------------------------- MISCS -// ------------------------------------------- // - -void InvariantSynthesizerCegar::LoadDesignSmtInfo(const std::string& fn) { - std::ifstream fin(fn); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read from : " << fn; - return; - } - std::stringstream sbuf; - sbuf << fin.rdbuf(); - design_smt_info = std::make_shared(sbuf.str()); -} - -const std::vector& -InvariantSynthesizerCegar::GetRunnableTargetScriptName() const { - return runnable_script_name; -} - -void InvariantSynthesizerCegar::LoadPrevStatisticsState(const std::string& fn) { - DesignStatistics local_info; - local_info.LoadFromFile(fn); - if (eqcheck_time != 0 || inv_proof_attempt_time != 0 || inv_syn_time != 0 || - inv_validate_time != 0 || inv_enhance_time != 0 || - !inv_syn_time_series.empty()) { - ILA_ERROR << "Not loading the statistics state from initial time!"; - } - eqcheck_time += local_info.TimeOfEqCheck; - inv_proof_attempt_time += local_info.TimeOfInvProof; - inv_syn_time += local_info.TimeOfInvSyn; - inv_enhance_time += local_info.TimeOfInvSynEnhance; - inv_validate_time += local_info.TimeOfInvValidate; - inv_syn_time_series.insert(inv_syn_time_series.end(), - local_info.TimeOfInvSynSeries.begin(), - local_info.TimeOfInvSynSeries.end()); -} - -DesignStatistics InvariantSynthesizerCegar::GetDesignStatistics() const { - DesignStatistics ret; - - ret.TimeOfEqCheck = eqcheck_time; - ret.TimeOfInvProof = inv_proof_attempt_time; - ret.TimeOfInvSyn = inv_syn_time; - ret.TimeOfInvSynEnhance = inv_enhance_time; - ret.TimeOfInvValidate = inv_validate_time; - ret.TimeOfInvSynSeries = inv_syn_time_series; - - if (design_smt_info == nullptr) { - ILA_ERROR << "Design information not available!"; - return ret; - } - - ILA_ERROR_IF(vlg_mod_inst_name.empty()) - << "vlg_mod_inst_name is empty, will not distinguish in/out module state"; - - for (auto&& st : design_smt_info->get_module_flatten_dt("wrapper")) { - - if (StrStartsWith(st.verilog_name, vlg_mod_inst_name + ".")) { - ret.NumOfDesignStateBits += st._type.GetBoolBvWidth(); - ret.NumOfDesignStateVars++; - } else { - ret.NumOfExtraStateBits += st._type.GetBoolBvWidth(); - ret.NumOfExtraStateVars++; - } - } - return ret; -} - -const InvariantObject& InvariantSynthesizerCegar::GetInvariants() const { - return inv_obj; -} - -void InvariantSynthesizerCegar::RemoveInvariantsByIdx(size_t idx) { - inv_obj.RemoveInvByIdx(idx); -} - -/// Here you can extract the invariants and export them if needed -const InvariantObject& -InvariantSynthesizerCegar::GetCandidateInvariants() const { - return inv_candidate; -} - -void InvariantSynthesizerCegar::ClearAllCandidateInvariants() { - inv_candidate.ClearAllInvariants(); -} - -void InvariantSynthesizerCegar::LoadInvariantsFromFile(const std::string& fn) { - inv_obj.ImportFromFile(fn); -} -void InvariantSynthesizerCegar::LoadCandidateInvariantsFromFile( - const std::string& fn) { - inv_candidate.ImportFromFile(fn); -} - -void InvariantSynthesizerCegar::AcceptAllCandidateInvariant() { - if (inv_candidate.NumInvariant() != 0) { - inv_obj.InsertFromAnotherInvObj(inv_candidate); - inv_candidate.ClearAllInvariants(); - } else - ILA_INFO << "All candidate invariants have been accepted."; -} - -/// Supply Verilog candidate invariants -void InvariantSynthesizerCegar::SupplyCandidateInvariant( - const std::string& vlg_expr) { - ILA_WARN << "Verilog invariant cannot be pruned"; - inv_candidate.AddInvariantFromVerilogExpr("", vlg_expr); -} - -// -------------------- GrainChc ------------------ // -void InvariantSynthesizerCegar::ChangeGrainSyntax( - const std::vector& syn) { - _vtg_config.GrainOptions = syn; -} - -}; // namespace ilang - -#endif // INVSYN_INTERFACE diff --git a/src/vtarget-out/inv-syn/rel_chc.cc b/src/vtarget-out/inv-syn/rel_chc.cc deleted file mode 100644 index 2c5e519a1..000000000 --- a/src/vtarget-out/inv-syn/rel_chc.cc +++ /dev/null @@ -1,610 +0,0 @@ -/// \file Source of initial constraint synthesis utility -// --- Hongce Zhang - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -// o.w. we need to find two ind-inv -static std::string dual_ind_inv_reset_start_tmpl = R"***( -;---------------------------------------- -; Dual Inductive Invariant Synthesis -; Generated from ILAng -;---------------------------------------- - -; wrapper smt -%wrapperSmt% - -; customized bv2bool -(define-fun zbv2bool ((bv1b (_ BitVec 1))) Bool (= bv1b #b1)) - -; additional mapping control -; |__AMC__design| is actually the invariants -; -(define-fun |__AMC__design| ((|__Sv__| |%d%_s|)) Bool %amcFunc_design%) -(define-fun |__AMC__wrapper| ((|__Sw__| |%w%_s|)) Bool %amcFunc_wrapper%) - -; includes the start_condition, issue_decode, issue_valid -(define-fun |__ASPT__| ((|__Sw__| |%w%_s|)) Bool %ASPT%) - -; includes the variable_map_assert -(define-fun |__ASST__| ((|__Sw__| |%w%_s|)) Bool %ASST%) - -(declare-rel INV1 (|%d%_s|)) ; inv1 is on design -(declare-rel INV2 (|%w%_s|)) ; inv2 is on wrapper -(declare-rel fail ()) - -%BIn% - -(declare-var |__SvI__| |%d%_s|) ; design -(declare-var |__Sv__| |%d%_s|) ; design -(declare-var |__Sv'__| |%d%_s|) ; design - -; (declare-var |__Swst__| |%w%_s|) ; wrapper : starting -- __START__ signal is true -(declare-var |__Sw__| |%w%_s|) ; wrapper : generic state -(declare-var |__Sw'__| |%w%_s|) ; wrapper : new state -;(declare-var |__Svst__| |%d%_s|) ; design : starting -- __START__ signal is true here - - -; init => inv1 -(rule (=> - (and - %rstseq% - ; (not (|%d%_n rst| |__SvI__|)) ; why not removed? - (|%d%_h| |__SvI__|) - (|__AMC__design| |__SvI__|) - ) (INV1 |__SvI__|))) - -; inv1 /\ T => inv1 -(rule (=> - (and - (INV1 |__Sv__|) - (|%d%_t| |__Sv__| |__Sv'__|) - (|%d%_h| |__Sv__|) - (|%d%_h| |__Sv'__|) - (|__AMC__design| |__Sv__|) - (|__AMC__design| |__Sv'__|)) - (INV1 |__Sv'__|))) - - -; init /\ inv1 => inv2 -(rule (=> - (and - (not (|%w%_n rst| |__Sw__|)) ; why not removed? - (|%w%_h| |__Sw__|) - (|%w%_i| |__Sw__|) - (|__AMC__wrapper| |__Sw__|) - (|__ASPT__| |__Sw__|) - (INV1 (|%w%_h %subi%| |__Sw__|)) - ) - (INV2 |__Sw__|) - ) -) - -; inv2 /\ T => inv2 -(rule - (=> - (and - (INV2 |__Sw__|) - (|%w%_t| |__Sw__| |__Sw'__|) - (|__AMC__wrapper| |__Sw__|) - (|__AMC__wrapper| |__Sw'__|) - (not (|%w%_n rst| |__Sw__|)) ; why not removed? - (not (|%w%_n rst| |__Sw'__|)) ; why not removed? - (|%w%_h| |__Sw__|) - (|%w%_h| |__Sw'__|) - ) - (INV2 |__Sw'__|) - ) -) - - -; inv2 /\ ~ assert => fail -(rule - (=> - (and - (INV2 |__Sw__|) - (|__AMC__wrapper| |__Sw__|) - (|%w%_h| |__Sw__|) - (not (|__ASST__| |__Sw__|)) - ) - fail) -) - -(query fail :print-certificate true) - -)***"; - - -// o.w. we need to find two ind-inv -static std::string dual_ind_inv_tmpl = R"***( -;---------------------------------------- -; Dual Inductive Invariant Synthesis -; Generated from ILAng -;---------------------------------------- - -; wrapper smt -%wrapperSmt% - -; customized bv2bool -(define-fun zbv2bool ((bv1b (_ BitVec 1))) Bool (= bv1b #b1)) - -; additional mapping control -; |__AMC__design| is actually the invariants -; -(define-fun |__AMC__design| ((|__Sv__| |%d%_s|)) Bool %amcFunc_design%) -(define-fun |__AMC__wrapper| ((|__Sw__| |%w%_s|)) Bool %amcFunc_wrapper%) - -; includes the start_condition, issue_decode, issue_valid -(define-fun |__ASPT__| ((|__Sw__| |%w%_s|)) Bool %ASPT%) - -; includes the variable_map_assert -(define-fun |__ASST__| ((|__Sw__| |%w%_s|)) Bool %ASST%) - -(declare-rel INV1 (|%d%_s|)) ; inv1 is on design -(declare-rel INV2 (|%w%_s|)) ; inv2 is on wrapper -(declare-rel fail ()) - -%BIn% -(declare-var |__SvI__| |%d%_s|) ; design -(declare-var |__Sv__| |%d%_s|) ; design -(declare-var |__Sv'__| |%d%_s|) ; design - -(declare-var |__SwI__| |%w%_s|) ; wrapper : init state -(declare-var |__Swst__| |%w%_s|) ; wrapper : starting -- __START__ signal is true -(declare-var |__Sw__| |%w%_s|) ; wrapper : generic state -(declare-var |__Sw'__| |%w%_s|) ; wrapper : new state -;(declare-var |__Svst__| |%d%_s|) ; design : starting -- __START__ signal is true here - - -; init => inv1 -(rule (=> - (and - %rstseq% - ;(not (|%d%_n rst| |__SvI__|)) ; why not removed? - (|%d%_h| |__SvI__|) - (|__AMC__design| |__SvI__|) - ) (INV1 |__SvI__|))) - -; inv1 /\ T => inv1 -(rule (=> - (and - (INV1 |__Sv__|) - (|%d%_t| |__Sv__| |__Sv'__|) - (|%d%_h| |__Sv__|) - (|%d%_h| |__Sv'__|) - (|__AMC__design| |__Sv__|) - (|__AMC__design| |__Sv'__|)) - (INV1 |__Sv'__|))) - - -; init /\ inv1 => inv2 -(rule (=> - (and - (|%w%_i| |__SwI__|) - (not (|%w%_n rst| |__SwI__|)) ; why not removed? - (not (|%w%_n rst| |__Swst__|)) ; why not removed? - (|%w%_h| |__SwI__|) - (|%w%_h| |__Swst__|) - (|__AMC__wrapper| |__SwI__|) - (|%w%_t| |__SwI__| |__Swst__|) - (|__AMC__wrapper| |__Swst__|) - (|__ASPT__| |__Swst__|) - (INV1 (|%w%_h %subi%| |__Swst__|)) - ) - (INV2 |__Swst__|) - ) -) - -; inv2 /\ T => inv2 -(rule - (=> - (and - (INV2 |__Sw__|) - (|%w%_t| |__Sw__| |__Sw'__|) - (|__AMC__wrapper| |__Sw__|) - (|__AMC__wrapper| |__Sw'__|) - (not (|%w%_n rst| |__Sw__|)) ; why not removed? - (not (|%w%_n rst| |__Sw'__|)) ; why not removed? - (|%w%_h| |__Sw__|) - (|%w%_h| |__Sw'__|) - ) - (INV2 |__Sw'__|) - ) -) - - -; inv2 /\ ~ assert => fail -(rule - (=> - (and - (INV2 |__Sw__|) - (|__AMC__wrapper| |__Sw__|) - (|%w%_h| |__Sw__|) - (not (|__ASST__| |__Sw__|)) - ) - fail) -) - -(query fail :print-certificate true) - -)***"; - -// a local helper function to produce a list of and -std::string static JoinListWithAnd(const std::vector & l) { - if (l.size() == 0) - return "true"; - else if(l.size() == 1) - return l[0]; - return "(and " + Join(l, " ")+")"; -} - -size_t static skipArgs(const std::string & stmt, size_t start) { - // need to fit - auto pos = start; - ILA_ASSERT(stmt.at(pos) == '(') << "Expecting '('"; - unsigned level = 0; - do { - if (stmt.at(pos) == '(') - level ++; - else if (stmt.at(pos) == ')') - level --; - pos ++; - } while(level != 0); - return pos; -} - -// a local helper function to return the type of a smt (define-fun ) stmt -bool static is_returntype_bool(const std::string & stmt) { - std::string beginning("(define-fun |"); - ILA_ASSERT (stmt.find(beginning) == 0) << "Not a `(define-fun |` stmt"; - auto pos = beginning.length()+1; - auto end_func_name_pos = stmt.find('|',pos); - auto start_arg_list = stmt.find('(', end_func_name_pos); - auto end_arg_list = skipArgs(stmt, start_arg_list); - auto Bool_pos = stmt.find("Bool", end_arg_list); - auto Bitvec_pos = stmt.find("(_ BitVec", end_arg_list); - if (Bool_pos < Bitvec_pos) - return true; - return false; -} - - -// extract -bool static extractSigDefFromLine( - const std::string & mod_name, - const std::string & line, - std::set & s, - std::vector> & v) { - // list of (name, is bool?) - bool found_match_state = false; - std::string search_target_wire_num = "(define-fun |" + mod_name + "#"; - std::string search_target_n = "(define-fun |" + mod_name + "_n "; - // bool returnBool; - if (line.find(search_target_wire_num) == 0) { // begins with it - auto mark = line.find("; \\"); - if (mark != line.npos) { - auto signame = line.substr(mark+strlen("; \\")); - // it should not contain EOL - //signame = ReplaceAll(ReplaceAll(signame, "\n",""),"\r",""); - if( IN(signame, s ) ) { - s.erase(signame); // remove it from the set - - auto num_start = line.substr(search_target_wire_num.size()); - auto end = num_start.find('|'); - auto num = num_start.substr(0,end); - auto smt_expr = "|" + mod_name + "#" + num + "|"; - - v.push_back(std::make_pair(smt_expr,is_returntype_bool(line))); // |mod#n| - - found_match_state = true; - } - } // found "; \\" - } // end of exists signal definition type 1 - else if (line.find(search_target_n) == 0) { // begins with it - auto len = search_target_n.size(); - auto mark = line.find('|',len); - auto signame = line.substr(len, mark-len); - - if( IN(signame, s) ) { - s.erase(signame); // remove it from the set - - auto smt_expr = "|" + mod_name + "_n " + signame + "|"; - - v.push_back(std::make_pair(smt_expr,is_returntype_bool(line))); // |mod_n signal| - found_match_state = true; - } - } - - return found_match_state; -} - - /// generate the Yosys script for dual invariant - void VlgSglTgtGen_Relchc::dual_inv_problem(const std::string& ys_script_name) { - // this is the yosys script for ? what? - return; // do nothing - } - - -// ------------------------------------------- -// Summary of the assertions/assumptions we need to handle -// -// assert: variable_map_assert -// invariant_assert -- should no be here -// -// assmpt: noreset (AMC) -// funcmap (AMC) -// absmem (AMC) -// additional_mapping_control_assume (AMC) -// invariant_assume (AMC_design) -// issue_decode (START -- ASPT) -// issue_valid (START -- ASPT) -// start_condition (START -- ASPT) -// -// (AMC means should always be true) -// -// ------------------------------------------- - - /// generate the template file - void VlgSglTgtGen_Relchc::dual_inv_tpl(const std::string & tpl_name, const std::string & all_smt) { - // get a local copy of the stringstream - std::stringstream smt_stream; - smt_stream << all_smt; - // std::string all_smt = smt_info.full_smt.str(); - // the Verilog top module - auto vlg_top_module_name = vlg_info_ptr->get_top_module_name(); - - // define amc(d/w)/asst/aspt funcs - std::string amc_design; - std::string amc_wrapper; - std::string asst; - std::string aspt; - { // Construct the above four - std::set wn_amc_design_item; // wn stands for wire name - std::set wn_amc_wrapper_item; - std::set wn_asst_item; // assertions - std::set wn_aspt_item; // assumptions - - { // find the verilog signal name - for (auto&& pbname_prob_pair : _problems.assertions) { - const auto & dspt = pbname_prob_pair.first; - const auto & exprs = pbname_prob_pair.second; - - if (dspt == "invariant_assert") { - ILA_ASSERT(false) << "Unanticipated dspt: " << dspt; - } - else if(dspt == "variable_map_assert") { - // - for (const auto & expr : exprs.exprs) { - ILA_ASSERT( expr.find("=") == expr.npos ) - << "Bug: should be pure name." - << "but get: " << expr; - - wn_asst_item.insert(expr); - } - } - else - ILA_ASSERT(false) << "Unknown dspt:" << dspt; - - - } // end of parsing asserts - - for (auto && pbname_prob_pair : _problems.assumptions) { - const auto & dspt = pbname_prob_pair.first; - const auto & exprs = pbname_prob_pair.second; - for (const auto &expr : exprs.exprs) { - ILA_ASSERT( expr.find("=") == expr.npos ) // no "=" - << "Bug: should be pure name." - << " but get: " << expr - << " dspt: " << dspt; - - if(dspt == "invariant_assume") - wn_amc_design_item.insert(expr); - else if( - dspt == "noreset" || - dspt == "funcmap" || - dspt == "absmem" || - dspt == "additional_mapping_control_assume" || - dspt == "func_arg" || - dspt == "func_result" || - dspt == "post_value_holder" || - dspt == "rfassumptions" - ) - wn_amc_wrapper_item.insert(expr); - else if( - dspt == "issue_decode" || - dspt == "issue_valid" || - dspt == "start_condition" || - dspt == "variable_map_assume" || - dspt == "variable_map_assume_" - ) - wn_aspt_item.insert(expr); - else - ILA_ASSERT(false) << "Unknown dspt : " << dspt; - } // for expr - } // for assumptions - - } // gen wire name - - std::vector> amc_design_item; // no wn here : in the submodule - std::vector> amc_wrapper_item; // in the top module - std::vector> asst_item; // assertions - std::vector> aspt_item; // assumptions - { // find number name --- smt name - // algo : go line by line, check in "wn_" or not, if so, add ow ignored - enum {BEFORE, SUBMODULE, TOPMODULE} state = BEFORE; - for (std::string line; std::getline(smt_stream, line);) { - if ( state == BEFORE && - line.find("; yosys-smt2-module ") == 0) { // starts with it - // new module - auto modname = line.substr(strlen("; yosys-smt2-module ")); - if (modname == vlg_top_module_name) - state = SUBMODULE; // go to next state - } // find vlg module - else if (state == SUBMODULE) { - if ( extractSigDefFromLine( - vlg_top_module_name, line, wn_amc_design_item, - amc_design_item) ) { /* do nothing */ } - else if(line.find("; yosys-smt2-module ") == 0) { - auto modname = line.substr(strlen("; yosys-smt2-module ")); - if (modname == top_mod_name) - state = TOPMODULE; // go to next state - } // end of go to next module - // else do nothing - } // deal with submodule (verilog top) -- continue to the wrapper - else if (state == TOPMODULE) { - if ( extractSigDefFromLine( top_mod_name, line, - wn_amc_wrapper_item, amc_wrapper_item ) ) { /* do nothing */ } - else if ( extractSigDefFromLine( top_mod_name, line, - wn_asst_item, asst_item ) ) { /* do nothing */ } - else if ( extractSigDefFromLine( top_mod_name, line, - wn_aspt_item, aspt_item ) ) { /* do nothing */ } - else { /* do nothing */ } - } - } // end of for readline - ILA_ASSERT (state == TOPMODULE) - << "BUG: Error in parsing smt-lib2 file! " - << "Not reaching the top module."; - // sanity check -- if all sigs are found - - ILA_ASSERT ( - wn_amc_design_item.empty() && - wn_amc_wrapper_item.empty() && - wn_asst_item.empty() && - wn_aspt_item.empty() - ) << "Missing signals in SMT parsing, HC gen will be incorrect"; - } // find number name --- smt name - - { // construct expressions - // (signame |%d%_s|) or (signame |%w%_s|), use " " to join and add "(and" ")" - std::vector items; - items.clear(); - for (auto && name_bool_pair: amc_design_item) { - if (name_bool_pair.second) - items.push_back("("+name_bool_pair.first+" |__Sv__|)"); - else - items.push_back("(zbv2bool ("+name_bool_pair.first+" |__Sv__|))"); - } - amc_design = JoinListWithAnd(items); - - - items.clear(); - for (auto && name_bool_pair: amc_wrapper_item) { - if (name_bool_pair.second) - items.push_back("("+name_bool_pair.first+" |__Sw__|)"); - else - items.push_back("(zbv2bool ("+name_bool_pair.first+" |__Sw__|))"); - } - amc_wrapper = JoinListWithAnd(items); - - items.clear(); - for (auto && name_bool_pair: aspt_item) { - if (name_bool_pair.second) - items.push_back("("+name_bool_pair.first+" |__Sw__|)"); - else - items.push_back("(zbv2bool ("+name_bool_pair.first+" |__Sw__|))"); - } - aspt = JoinListWithAnd(items); - - items.clear(); - for (auto && name_bool_pair: asst_item) { - if (name_bool_pair.second) - items.push_back("("+name_bool_pair.first+" |__Sw__|)"); - else - items.push_back("(zbv2bool ("+name_bool_pair.first+" |__Sw__|))"); - } - asst = JoinListWithAnd(items); - - /* - for_each(aspt_item.begin(), aspt_item.end(), - [](std::string & s) -> void {s = "("+s+" |__Sw__|)";} ); - aspt = JoinListWithAnd(aspt_item); - - for_each(asst_item.begin(), asst_item.end(), - [](std::string & s) -> void {s = "("+s+" |__Sw__|)";} ); - asst = JoinListWithAnd(asst_item);*/ - - } // construct expressions - } // Construct exprs done - - // %BIn% - // %rstseq% - std::string BIn; - std::string rstseq; - { // set BIn and rstseq - unsigned rstcycles = supplementary_info.cosa_yosys_reset_config.reset_cycles; - std::string rst_sig = "rst"; - bool rst_neg = false; - - // decide reset signal - if(IN("interface mapping", rf_vmap) || IN("interface-mapping", rf_vmap)) { - nlohmann::json & ifmap = IN("interface mapping", rf_vmap) ? rf_vmap["interface mapping"] : rf_vmap["interface-mapping"]; - ILA_CHECK(ifmap.is_object()); - for (auto&& item : ifmap.items()) { - if (item.value() == "**RESET**") { - rst_sig = item.key(); - rst_neg = false; - } else if (item.value() == "**NRESET**") { - rst_sig = item.key(); - rst_neg = true; - } - } - } // finish deciding reset signal - - - for (unsigned idx = 0; idx < rstcycles; ++ idx) { - std::string st_name = "|__SvBI" + std::to_string(idx) +"__|"; - std::string next_st_name = idx < rstcycles -1 ? - "|__SvBI" + std::to_string(idx+1) +"__|" : - "|__SvI__|"; - BIn += "(declare-var " + st_name + " |%d%_s|)\n"; - - if (rst_neg) - rstseq += "(not (|%d%_n "+ rst_sig +"| " + st_name + "))\n"; - else - rstseq += "(|%d%_n "+ rst_sig +"| " + st_name + ")\n"; - rstseq += "(|%d%_t| " + st_name + " " + next_st_name + ")\n"; - rstseq += "(|%d%_h| " + st_name + ")\n"; - } - } // end of setting BIn and rstseq - - - std::string ret_tpl_smt; - ret_tpl_smt = dual_ind_inv_reset_start_tmpl; - - - { // replacing the init sequence - ret_tpl_smt = ReplaceAll(ReplaceAll(ret_tpl_smt, "%BIn%", BIn), "%rstseq%", rstseq); - } - - { // now create the template - // 1. func sub - ret_tpl_smt = ReplaceAll(ret_tpl_smt, "%wrapperSmt%", all_smt); - ret_tpl_smt = ReplaceAll(ret_tpl_smt, "%amcFunc_design%", amc_design); - ret_tpl_smt = ReplaceAll(ret_tpl_smt, "%amcFunc_wrapper%", amc_wrapper); - ret_tpl_smt = ReplaceAll(ret_tpl_smt, "%ASST%", asst); - ret_tpl_smt = ReplaceAll(ret_tpl_smt, "%ASPT%", aspt); - // 2. name sub - ret_tpl_smt = ReplaceAll(ret_tpl_smt, "%subi%", _vlg_mod_inst_name); - ret_tpl_smt = ReplaceAll(ret_tpl_smt, "%d%", vlg_top_module_name); - ret_tpl_smt = ReplaceAll(ret_tpl_smt, "%w%", top_mod_name); - } - - { // output the tpl - std::ofstream tpl_fout(tpl_name); - tpl_fout << ret_tpl_smt; - } // finish output - - } // dual_inv_tpl - - - -}; // namespace ilang diff --git a/src/vtarget-out/inv-syn/vtarget_gen_inv_abc.cc b/src/vtarget-out/inv-syn/vtarget_gen_inv_abc.cc deleted file mode 100644 index ecb07b8f0..000000000 --- a/src/vtarget-out/inv-syn/vtarget_gen_inv_abc.cc +++ /dev/null @@ -1,575 +0,0 @@ -/// \file Source of generating Yosys accepted problem, vlg, mem, script -/// the inv-syn related HC generation is located in inv_syn.cc -// --- Hongce Zhang - -#include -#ifdef INVSYN_INTERFACE - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -#define VLG_TRUE "`true" -#define VLG_FALSE "`false" - -// initialize templates -static std::string abcGenerateSmtScript_wo_Array = R"***( -read_verilog -formal %topfile% -prep -top %module% -flatten -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -miter -assert %module% -%setundef -undriven -init -expose% -memory -nordff -techmap; opt -fast -write_blif %blifname% -)***"; - -// flatten before sim to avoid sim's none unique issue -// yosys template -static std::string abcGenerateAigerWInit_wo_Array = R"***( -read_verilog -formal %topfile% -prep -top %module% -flatten -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -miter -assert %module% -%setundef -undriven -init -expose% -memory -nordff -opt_clean -techmap -abc -fast -g AND -write_aiger -zinit -map %mapname% %aigname% -write_blif %blifname% -)***"; - -static std::string abcAigCmdNoGLA = R"***( - &read %aigname% - &put - fold - pdr - {inv_min} - inv_print -v -)***"; - -static std::string abcAigCmdGLA = R"***( - &read %aigname% - &gla -T 500 -F 200 -v - &gla_derive - &put - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - {scorr} - dc2 -v - dc2 -v - dc2 -v - dc2 -v - {lcorr} - dc2 -v - dc2 -v - dc2 -v - dc2 -v - pdr - {inv_min} - inv_print -v -)***"; - -static std::string abcCmdNoGLA = R"***( - read_blif %blifname% - strash - pdr - {inv_min} - inv_print -v -)***"; - -static std::string abcCmdGLA = R"***( - read_blif %blifname% - &get -n - &gla -T 500 -F 200 -v - &gla_derive - &put - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - {scorr} - dc2 -v - dc2 -v - dc2 -v - dc2 -v - {lcorr} - dc2 -v - dc2 -v - dc2 -v - dc2 -v - pdr - {inv_min} - inv_print -v -)***"; - -VlgSglTgtGen_Abc::~VlgSglTgtGen_Abc() {} - -VlgSglTgtGen_Abc::VlgSglTgtGen_Abc( - const std::string& - output_path, // will be a sub directory of the output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, const VerilogGenerator::VlgGenConfig& config, - nlohmann::json& _rf_vmap, nlohmann::json& _rf_cond, - VlgTgtSupplementaryInfo& _sup_info, VerilogInfo* _vlg_info_ptr, - const std::string& vlg_mod_inst_name, const std::string& ila_mod_inst_name, - const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector vbackend, - synthesis_backend_selector sbackend, const target_type_t& target_tp, - advanced_parameters_t* adv_ptr, bool GenerateProof, _chc_target_t chctarget, - bool useGLA, bool useCORR, bool useAIGER) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, config, _rf_vmap, _rf_cond, - _sup_info, _vlg_info_ptr, vlg_mod_inst_name, - ila_mod_inst_name, wrapper_name, implementation_srcs, - implementation_include_path, vtg_config, vbackend, target_tp, - adv_ptr), - s_backend(sbackend), generate_proof(GenerateProof), - has_cex(adv_ptr && adv_ptr->_cex_obj_ptr), chc_target(chctarget), - useGla(useGLA), useCorr(useCORR), useAiger(useAIGER), disallowGla(false) { - - ILA_CHECK(vbackend == backend_selector::YOSYS) - << "Only support using yosys for chc target"; - - ILA_CHECK(chctarget == _chc_target_t::CEX) << "Target must be cex"; - ILA_CHECK(target_tp == target_type_t::INV_SYN_DESIGN_ONLY) - << "for cex chc, target type must be INV_SYN_DESIGN_ONLY: " << target_tp; - ILA_CHECK(has_cex) << "for cex chc, cex must be provided!"; - - ILA_CHECK(sbackend == synthesis_backend_selector::ABC) - << "Unknown synthesis backend:" << sbackend; - - ILA_CHECK(_vtg_config.YosysSmtFlattenHierarchy) - << "For ABC, hierarchy must be flattened!"; -} - -/// Add an assumption -void VlgSglTgtGen_Abc::add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) { - _problems.assumptions[dspt].exprs.push_back(aspt); -} -/// Add an assertion -void VlgSglTgtGen_Abc::add_a_direct_assertion(const std::string& asst, - const std::string& dspt) { - _problems.assertions[dspt].exprs.push_back(asst); -} - -void VlgSglTgtGen_Abc::PreExportProcess() { - - std::string all_assert_wire_content; - std::string all_assume_wire_content; - - ILA_CHECK(target_type == target_type_t::INV_SYN_DESIGN_ONLY); - ILA_ERROR_IF(_problems.assertions.size() != 1) << "BUG in cex extract"; - - // you need to add assumptions as well - for (auto&& pbname_prob_pair : _problems.assumptions) { - const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - ILA_DLOG("VlgSglTgtGen_Abc.PreExportProcess") - << "Adding assumption:" << prbname; - - for (auto&& p : prob.exprs) { - if (all_assume_wire_content.empty()) - all_assume_wire_content = "(" + p + ")"; - else - all_assume_wire_content += "&& (" + p + ")"; - } // for prob.exprs - } // for _problems.assumption - - bool first = true; - // this is to check given invariants - for (auto&& pbname_prob_pair : _problems.assertions) { - // const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - - // ILA_CHECK(prbname == "cex_nonreachable_assert") - // << "BUG: assertion can only be cex reachability queries."; - // sanity check, should only be invariant's related asserts - - for (auto&& p : prob.exprs) { - // there should be only one expression (for cex target) - // ILA_CHECK(all_assert_wire_content.empty()); - if (first) - all_assert_wire_content = p; - else - all_assert_wire_content += " && " + p; - - first = false; - } // for expr - } // for problem - // add assert wire (though no use : make sure will not optimized away) - ILA_CHECK(!all_assert_wire_content.empty()) << "no property to check!"; - - vlg_wrapper.add_wire("__all_assert_wire__", 1, true); - vlg_wrapper.add_output("__all_assert_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); - - std::string precond; - disallowGla = false; - if (!all_assume_wire_content.empty()) { - ILA_CHECK( - !(_vtg_config.AbcUseAiger == false && - _vtg_config.AbcAssumptionStyle == _vtg_config.AigMiterExtraOutput)) - << "If you don't use aiger, and has assumptions, there is no way to " - "pass the extra output. (Will have an additional latch, but " - "currently we cannot interprete.)"; - if (_vtg_config.AbcAssumptionStyle == _vtg_config.AigMiterExtraOutput) { - disallowGla = true; - vlg_wrapper.add_wire("__all_assume_wire__", 1, true); - vlg_wrapper.add_output("__all_assume_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assume_wire__", - all_assume_wire_content); - vlg_wrapper.add_stmt("assume property (__all_assume_wire__);\n"); - } else { - vlg_wrapper.add_reg("__all_assumed_reg__", 1); - vlg_wrapper.add_stmt("always @(posedge clk) begin"); - vlg_wrapper.add_stmt("if (rst) __all_assumed_reg__ <= 0;"); - vlg_wrapper.add_stmt( - "else if (!__all_assume_wire__) __all_assumed_reg__ <= 1; end"); - - vlg_wrapper.add_wire("__all_assume_wire__", 1, true); - vlg_wrapper.add_output("__all_assume_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assume_wire__", - all_assume_wire_content); - precond = "!( __all_assume_wire__ && !__all_assumed_reg__) || "; - } - } // handle assumptions - - vlg_wrapper.add_stmt("assert property (" + precond + - " __all_assert_wire__ ); // the only assertion \n"); -} // PreExportProcess - -/// export the script to run the verification : -/// like "yosys gemsmt.ys" -void VlgSglTgtGen_Abc::Export_script(const std::string& script_name) { - abc_run_script_name = script_name; - /// TODO: BUG: modify this : use z3/freqHorn - - auto fname = os_portable_append_dir(_output_path, script_name); - std::ofstream fout(fname); - if (!fout.is_open()) { - ILA_ERROR << "Error writing to file:" << fname; - return; - } - fout << "#!/bin/bash" << std::endl; - // fout << "trap \"trap - SIGTERM && kill -- -$$\" SIGINT SIGTERM"< lineno - // open, read, count and write - // if it is a port name, we will ask user to specify its upper level - // signal name - VerilogModifier vlg_mod(vlg_info_ptr, - static_cast( - _vtg_config.PortDeclStyle), - _vtg_config.PonoAddKeep, - supplementary_info.width_info); - - for (auto&& refered_vlg_item : _all_referred_vlg_names) { - auto idx = refered_vlg_item.first.find("["); - auto removed_range_name = refered_vlg_item.first.substr(0, idx); - vlg_mod.RecordKeepSignalName(removed_range_name); - // auto sig = // no use, this is too late, vlg_wrapper already exported - vlg_mod.RecordConnectSigName(removed_range_name, - refered_vlg_item.second.range); - // vlg_wrapper.add_output(sig.first, sig.second); - } - vlg_mod.FinishRecording(); - - // auto tmp_fn = os_portable_append_dir(_output_path, tmp_design_file); - auto tmp_fn = os_portable_append_dir(_output_path, top_file_name); - // now let's do the job - for (auto&& fn : vlg_design_files) { - std::ifstream fin(fn); - std::ofstream fout(tmp_fn, std::ios_base::app); // append to a temp file - if (!fin.is_open()) { - ILA_ERROR << "Cannot read file:" << fn; - continue; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot open file for write:" << tmp_fn; - continue; - } - vlg_mod.ReadModifyWrite(fn, fin, fout); - } // for (auto && fn : vlg_design_files) - - // handles the includes - // .. (copy all the verilog file in the folder), this has to be os independent - if (vlg_include_files_path.size() != 0) { - // copy the files and specify the -I commandline to the run.sh - for (auto&& include_path : vlg_include_files_path) - os_portable_copy_dir(include_path, _output_path); - } - -} // Export_modify_verilog - -/// export the memory abstraction (implementation) -/// Yes, this is also implementation specific, (jasper may use a different one) -void VlgSglTgtGen_Abc::Export_mem(const std::string& mem_name) { - // we will ignore the mem_name - - auto outfn = os_portable_append_dir(_output_path, top_file_name); - std::ofstream fout(outfn, std::ios_base::app); // append - - VlgAbsMem::OutputMemFile(fout, - _vtg_config.VerificationSettingAvoidIssueStage); -} - -static void correct_blif_remove_non_init(const std::string& fn, - const std::string& fo) { - std::ifstream fin(fn); - std::ofstream fout(fo); - if (!fin.is_open()) { - ILA_ERROR << "Unable to read " << fn; - return; - } - if (!fout.is_open()) { - ILA_ERROR << "Unable to write " << fo; - return; - } - std::string line; - while (std::getline(fin, line)) { - if (StrStartsWith(line, ".latch ")) { - auto st_def = SplitSpaceTabEnter(line); - if (st_def.back() == "2") { - st_def.back() = "0"; - ILA_WARN << "Force state to be 0: " << st_def.at(2); - line = Join(st_def, " "); - } - } - // always write back - fout << line << "\n"; - } -} // correct_blif_remove_non_init - -// export the chc file -void VlgSglTgtGen_Abc::Export_problem(const std::string& extra_name) { - // used by export script! - - if (!useAiger) { - blif_fname = extra_name; - - // first generate a temporary smt - // and extract from it the necessary info - // "yosys --> blif " - generate_blif(os_portable_append_dir(_output_path, "__blif_prepare.blif"), - os_portable_append_dir(_output_path, "__gen_blif_script.ys")); - - correct_blif_remove_non_init( - os_portable_append_dir(_output_path, "__blif_prepare.blif"), - os_portable_append_dir(_output_path, blif_fname)); - } else { - aiger_fname = extra_name; - - generate_aiger( - os_portable_append_dir(_output_path, "__aiger_prepare.blif"), - os_portable_append_dir(_output_path, aiger_fname), - os_portable_append_dir(_output_path, aiger_fname + ".map"), - os_portable_append_dir(_output_path, "__gen_blif_script.ys")); - } -} // Export_problem - -void VlgSglTgtGen_Abc::ExportAll(const std::string& wrapper_name, // wrapper.v - const std::string& ila_vlg_name, // no use - const std::string& script_name, // the run.sh - const std::string& extra_name, // the chc - const std::string& mem_name) { // no use - - PreExportProcess(); - - if (os_portable_mkdir(_output_path) == false) - ILA_WARN << "Cannot create output directory:" << _output_path; - - // you don't need to worry about the path and names - Export_wrapper(wrapper_name); - // design only - // if (target_type == target_type_t::INSTRUCTIONS) - // Export_ila_vlg(ila_vlg_name); // this has to be after Export_wrapper - - // for Jasper, this will be put to multiple files - // for CoSA & Yosys, this will be put after the wrapper file (wrapper.v) - Export_modify_verilog(); // this must be after Export_wrapper - Export_mem(mem_name); - - // you need to create the map function -- - Export_problem(extra_name); // the gensmt.ys - - Export_script(script_name); -} - -/// generate the wrapper's smt first -void VlgSglTgtGen_Abc::generate_blif(const std::string& blif_name, - const std::string& ys_script_name) { - - auto ys_output_full_name = - os_portable_append_dir(_output_path, "__yosys_exec_result.txt"); - { // export to ys_script_name - std::ofstream ys_script_fout(ys_script_name); - - ys_script_fout << ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll(abcGenerateSmtScript_wo_Array, "%topfile%", - os_portable_append_dir(_output_path, - top_file_name)), - "%module%", top_mod_name), - "%blifname%", blif_name), - "%setundef -undriven -init -expose%", - _vtg_config.YosysUndrivenNetAsInput - ? "setundef -undriven -init -expose" - : ""), - "%rstlen%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%cycle%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)); - } // finish writing - - std::string yosys = "yosys"; - - if (!_vtg_config.YosysPath.empty()) - yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); - - // execute it - std::vector cmd; - cmd.push_back(yosys); - cmd.push_back("-s"); - cmd.push_back(ys_script_name); - auto res = os_portable_execute_shell(cmd, ys_output_full_name); - ILA_ERROR_IF(res.failure != res.NONE) << "Executing Yosys failed!"; - ILA_ERROR_IF(res.failure == res.NONE && res.ret != 0) - << "Yosys returns error code:" << res.ret; -} // design_only_gen_smt - -/// generate the wrapper's smt first -void VlgSglTgtGen_Abc::generate_aiger(const std::string& blif_name, - const std::string& aiger_name, - const std::string& map_name, - const std::string& ys_script_name) { - - auto ys_output_full_name = - os_portable_append_dir(_output_path, "__yosys_exec_result.txt"); - { // export to ys_script_name - std::ofstream ys_script_fout(ys_script_name); - - ys_script_fout << ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll(abcGenerateAigerWInit_wo_Array, - "%topfile%", - os_portable_append_dir( - _output_path, top_file_name)), - "%module%", top_mod_name), - "%blifname%", blif_name), - "%aigname%", aiger_name), - "%mapname%", map_name), - "%setundef -undriven -init -expose%", - _vtg_config.YosysUndrivenNetAsInput - ? "setundef -undriven -init -expose" - : ""), - "%rstlen%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%cycle%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)); - } // finish writing - - std::string yosys = "yosys"; - - if (!_vtg_config.YosysPath.empty()) - yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); - - // execute it - std::vector cmd; - cmd.push_back(yosys); - cmd.push_back("-s"); - cmd.push_back(ys_script_name); - auto res = os_portable_execute_shell(cmd, ys_output_full_name); - ILA_ERROR_IF(res.failure != res.NONE) << "Executing Yosys failed!"; - ILA_ERROR_IF(res.failure == res.NONE && res.ret != 0) - << "Yosys returns error code:" << res.ret; -} // generate_aiger - -}; // namespace ilang - -#endif // INVSYN_INTERFACE diff --git a/src/vtarget-out/inv-syn/vtarget_gen_inv_chc.cc b/src/vtarget-out/inv-syn/vtarget_gen_inv_chc.cc deleted file mode 100644 index a56eeefe8..000000000 --- a/src/vtarget-out/inv-syn/vtarget_gen_inv_chc.cc +++ /dev/null @@ -1,782 +0,0 @@ -/// \file Source of generating Yosys accepted problem, vlg, mem, script -/// the inv-syn related HC generation is located in inv_syn.cc -// --- Hongce Zhang - -#include -#ifdef INVSYN_INTERFACE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -#define VLG_TRUE "`true" -#define VLG_FALSE "`false" - -// hierarchy --> opt may not be useful -// mux undef may be useful? - -// initialize templates -static std::string chcGenerateSmtScript_wo_Array = R"***( -hierarchy -check -proc -opt -opt_expr -mux_undef -opt -opt -%flatten% -%setundef -undriven -init -expose% -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -memory -nordff -proc -opt;; -)***"; - -// should not be used -static std::string chcGenerateSmtScript_w_Array = R"***( -hierarchy -check -proc -opt -opt_expr -mux_undef -opt -opt -%flatten% -%setundef -undriven -init -expose% -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -memory_dff -wr_only -memory_collect; -memory_unpack -splitnets -driver -opt;; -memory_collect; -pmuxtree -proc -opt;; -)***"; - -static std::string inv_syn_tmpl_datatypes = R"***( -;---------------------------------------- -; Single Inductive Invariant Synthesis -; Generated from ILAng -;---------------------------------------- -%(set-option :fp.engine spacer)% - -%% - -(declare-rel INV (|%1%_s|)) -(declare-rel fail ()) - -(declare-var |__S__| |%1%_s|) -(declare-var |__S'__| |%1%_s|) - -; -------------------------------- -; note if you want it a bit faster -; if can try removing wrapper-u in rule 1 -; or remove the assume previous invariants -; -------------------------------- - -; init => inv -(rule (=> - (and - (|%1%_i| |__S__|) - (|%1%_u| |__S__|) - (|%1%_h| |__S__|) - ) - (INV |__S__|))) - -; inv /\ T => inv -(rule (=> (and - (INV |__S__|) - (|%1%_u| |__S__|) - (|%1%_u| |__S'__|) - (|%1%_h| |__S__|) - (|%1%_h| |__S'__|) - (|%1%_t| |__S__| |__S'__|)) - (INV |__S'__|))) - -; inv /\ ~p => \bot -(rule (=> (and - (INV |__S__|) - (|%1%_u| |__S__|) - (|%1%_h| |__S__|) - (not (|%1%_a| |__S__|))) - fail)) - -; (query fail :print-certificate true) - -)***"; - -static std::string inv_syn_tmpl_wo_datatypes = R"***( -;---------------------------------------- -; Single Inductive Invariant Synthesis -; Generated from ILAng -;---------------------------------------- -%(set-option :fp.engine spacer)% - -%% - -(declare-rel INV %WrapperDataType%) -(declare-rel fail ()) - - -%State% -%StatePrime% -;(declare-var |__S__state| Type) -;(declare-var |__S'__state| Type) - -; same for flattened - -; init => inv -(rule (=> - (and - (|%WrapperName%_i| %Ss%) - (|%WrapperName%_u| %Ss%) - (|%WrapperName%_h| %Ss%) - ) - (INV %Ss%))) - -; inv /\ T => inv -(rule (=> (and - (INV %Ss%) - (|%WrapperName%_u| %Ss%) - (|%WrapperName%_u| %Sps%) - (|%WrapperName%_h| %Ss%) - (|%WrapperName%_h| %Sps%) - (|%WrapperName%_t| %Ss% %Sps%)) - (INV %Sps%))) - -; inv /\ ~p => \bot -(rule (=> (and - (INV %Ss%) - (|%WrapperName%_u| %Ss%) - (|%WrapperName%_h| %Ss%) - (not (|%WrapperName%_a| %Ss%))) - fail)) - -; (query fail :print-certificate true) - -)***"; - -static std::string RewriteDatatypeChc(const std::string& tmpl, - const std::vector& dt, - const std::string& wrapper_mod_name); - -VlgSglTgtGen_Chc::~VlgSglTgtGen_Chc() {} - -VlgSglTgtGen_Chc::VlgSglTgtGen_Chc( - const std::string& - output_path, // will be a sub directory of the output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, const VerilogGenerator::VlgGenConfig& config, - nlohmann::json& _rf_vmap, nlohmann::json& _rf_cond, - VlgTgtSupplementaryInfo& _sup_info, VerilogInfo* _vlg_info_ptr, - const std::string& vlg_mod_inst_name, const std::string& ila_mod_inst_name, - const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector vbackend, - synthesis_backend_selector sbackend, const target_type_t& target_tp, - advanced_parameters_t* adv_ptr, bool GenerateProof, _chc_target_t chctarget) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, config, _rf_vmap, _rf_cond, - _sup_info, _vlg_info_ptr, vlg_mod_inst_name, - ila_mod_inst_name, wrapper_name, implementation_srcs, - implementation_include_path, vtg_config, vbackend, target_tp, - adv_ptr), - s_backend(sbackend), generate_proof(GenerateProof), - has_cex(adv_ptr && adv_ptr->_cex_obj_ptr), chc_target(chctarget) { - - ILA_CHECK(vbackend == backend_selector::YOSYS) - << "Only support using yosys for chc target"; - - ILA_CHECK(chctarget == _chc_target_t::CEX) - << "Bug: VlgSglTgtGen_Chc should only be used for CEX"; - - ILA_CHECK(target_tp == target_type_t::INV_SYN_DESIGN_ONLY) - << "for cex chc, target type must be INV_SYN_DESIGN_ONLY: " << target_tp; - ILA_CHECK(has_cex) << "for cex chc, cex must be provided!"; - ILA_CHECK(_vtg_config.YosysSmtStateSort == _vtg_config.Datatypes) - << "invariant synthesis only supports datatypes state encoding."; - - ILA_CHECK(sbackend == synthesis_backend_selector::GRAIN or - sbackend == synthesis_backend_selector::Z3) - << "Unknown synthesis backend:" << sbackend; - - if (sbackend == synthesis_backend_selector::GRAIN) - ILA_CHECK(vtg_config.YosysSmtFlattenDatatype) - << "For Grain, datatype must be flattened!"; - - ILA_CHECK(_vtg_config.YosysSmtFlattenHierarchy) - << "Currently implementation only supports extract invariants from " - "flattened hierarchy."; -} - -/// Add an assumption -void VlgSglTgtGen_Chc::add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) { - _problems.assumptions[dspt].exprs.push_back(aspt); -} -/// Add an assertion -void VlgSglTgtGen_Chc::add_a_direct_assertion(const std::string& asst, - const std::string& dspt) { - _problems.assertions[dspt].exprs.push_back(asst); -} - -void VlgSglTgtGen_Chc::PreExportProcess() { - - std::string all_assert_wire_content; - std::string all_assume_wire_content; - - ILA_CHECK(target_type == target_type_t::INV_SYN_DESIGN_ONLY); - ILA_ERROR_IF(_problems.assertions.size() != 1) << "BUG in cex extract"; - - // you need to add assumptions as well - for (auto&& pbname_prob_pair : _problems.assumptions) { - const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - ILA_DLOG("VlgSglTgtGen_Chc.PreExportProcess") - << "Adding assumption:" << prbname; - - for (auto&& p : prob.exprs) { - vlg_wrapper.add_stmt("assume property (" + p + "); //" + prbname + "\n"); - if (all_assume_wire_content.empty()) - all_assume_wire_content = "(" + p + ")"; - else - all_assume_wire_content += "&& (" + p + ")"; - } // for prob.exprs - } // for _problems.assumption - - bool first = true; - // this is to check given invariants - for (auto&& pbname_prob_pair : _problems.assertions) { - const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - - // ILA_CHECK(prbname == "cex_nonreachable_assert") - // << "BUG: assertion can only be cex reachability queries."; - // sanity check, should only be invariant's related asserts - - for (auto&& p : prob.exprs) { - vlg_wrapper.add_stmt("assert property (" + p + "); //" + prbname + "\n"); - // there should be only one expression (for cex target) - // ILA_CHECK(all_assert_wire_content.empty()); - if (first) - all_assert_wire_content = p; - else - all_assert_wire_content += " && " + p; - - first = false; - } // for expr - } // for problem - // add assert wire (though no use : make sure will not optimized away) - ILA_CHECK(!all_assert_wire_content.empty()) << "no property to check!"; - - vlg_wrapper.add_wire("__all_assert_wire__", 1, true); - vlg_wrapper.add_output("__all_assert_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); - - if (!all_assume_wire_content.empty()) { - vlg_wrapper.add_wire("__all_assume_wire__", 1, true); - vlg_wrapper.add_output("__all_assume_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assume_wire__", all_assume_wire_content); - } -} // PreExportProcess - -/// export the script to run the verification : -/// like "yosys gemsmt.ys" -void VlgSglTgtGen_Chc::Export_script(const std::string& script_name) { - chc_run_script_name = script_name; - /// TODO: BUG: modify this : use z3/freqHorn - - auto fname = os_portable_append_dir(_output_path, script_name); - std::ofstream fout(fname); - if (!fout.is_open()) { - ILA_ERROR << "Error writing to file:" << fname; - return; - } - fout << "#!/bin/bash" << std::endl; - // fout << "trap \"trap - SIGTERM && kill -- -$$\" SIGINT SIGTERM"< lineno - // open, read, count and write - // if it is a port name, we will ask user to specify its upper level - // signal name - VerilogModifier vlg_mod(vlg_info_ptr, - static_cast( - _vtg_config.PortDeclStyle), - _vtg_config.PonoAddKeep, - supplementary_info.width_info); - - for (auto&& refered_vlg_item : _all_referred_vlg_names) { - auto idx = refered_vlg_item.first.find("["); - auto removed_range_name = refered_vlg_item.first.substr(0, idx); - vlg_mod.RecordKeepSignalName(removed_range_name); - // auto sig = // no use, this is too late, vlg_wrapper already exported - vlg_mod.RecordConnectSigName(removed_range_name, - refered_vlg_item.second.range); - // vlg_wrapper.add_output(sig.first, sig.second); - } - vlg_mod.FinishRecording(); - - // auto tmp_fn = os_portable_append_dir(_output_path, tmp_design_file); - auto tmp_fn = os_portable_append_dir(_output_path, top_file_name); - // now let's do the job - for (auto&& fn : vlg_design_files) { - std::ifstream fin(fn); - std::ofstream fout(tmp_fn, std::ios_base::app); // append to a temp file - if (!fin.is_open()) { - ILA_ERROR << "Cannot read file:" << fn; - continue; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot open file for write:" << tmp_fn; - continue; - } - vlg_mod.ReadModifyWrite(fn, fin, fout); - } // for (auto && fn : vlg_design_files) - - // handles the includes - // .. (copy all the verilog file in the folder), this has to be os independent - if (vlg_include_files_path.size() != 0) { - // copy the files and specify the -I commandline to the run.sh - for (auto&& include_path : vlg_include_files_path) - os_portable_copy_dir(include_path, _output_path); - } - -} // Export_modify_verilog - -/// export the memory abstraction (implementation) -/// Yes, this is also implementation specific, (jasper may use a different one) -void VlgSglTgtGen_Chc::Export_mem(const std::string& mem_name) { - // we will ignore the mem_name - - auto outfn = os_portable_append_dir(_output_path, top_file_name); - std::ofstream fout(outfn, std::ios_base::app); // append - - VlgAbsMem::OutputMemFile(fout, - _vtg_config.VerificationSettingAvoidIssueStage); -} - -// export the chc file -void VlgSglTgtGen_Chc::Export_problem(const std::string& extra_name) { - // used by export script! - chc_prob_fname = extra_name; - - // first generate a temporary smt - // and extract from it the necessary info - - // first generate a temporary smt - // and extract from it the necessary info - // this is the CHC-style thing - design_only_gen_smt( - os_portable_append_dir(_output_path, "__design_smt.smt2"), - os_portable_append_dir(_output_path, "__gen_smt_script.ys")); - // if (_vtg_config.YosysSmtStateSort == _vtg_config.DataSort) - convert_smt_to_chc_datatype( - os_portable_append_dir(_output_path, "__design_smt.smt2"), - os_portable_append_dir(_output_path, - s_backend == synthesis_backend_selector::GRAIN - ? "grain_prep.txt" - : extra_name)); - - // for grain : convert wrapper# --> w wrapper_ --> w - if (s_backend == synthesis_backend_selector::GRAIN) { - std::ifstream fin(os_portable_append_dir(_output_path, "grain_prep.txt")); - std::ofstream fout(os_portable_append_dir(_output_path, extra_name)); - if (!fin.is_open()) { - ILA_ERROR << "Cannot read from : " - << os_portable_append_dir(_output_path, "grain_prep.txt"); - return; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot write to : " - << os_portable_append_dir(_output_path, extra_name); - return; - } - std::string line; - while (std::getline(fin, line)) { - fout << ReplaceAll(ReplaceAll(line, "wrapper#", "w"), "wrapper_", "w_") - << "\n"; - } - } - -} // Export_problem - -std::shared_ptr -VlgSglTgtGen_Chc::GetDesignSmtInfo() const { - return design_smt_info; -} - -void VlgSglTgtGen_Chc::ExportAll(const std::string& wrapper_name, // wrapper.v - const std::string& ila_vlg_name, // no use - const std::string& script_name, // the run.sh - const std::string& extra_name, // the chc - const std::string& mem_name) { // no use - - PreExportProcess(); - - if (os_portable_mkdir(_output_path) == false) - ILA_WARN << "Cannot create output directory:" << _output_path; - - // you don't need to worry about the path and names - Export_wrapper(wrapper_name); - // design only - // if (target_type == target_type_t::INSTRUCTIONS) - // Export_ila_vlg(ila_vlg_name); // this has to be after Export_wrapper - - // for Jasper, this will be put to multiple files - // for CoSA & Yosys, this will be put after the wrapper file (wrapper.v) - Export_modify_verilog(); // this must be after Export_wrapper - Export_mem(mem_name); - - // you need to create the map function -- - Export_problem(extra_name); // the gensmt.ys - - Export_script(script_name); -} - -/// generate the wrapper's smt first -void VlgSglTgtGen_Chc::design_only_gen_smt(const std::string& smt_name, - const std::string& ys_script_name) { - - auto ys_output_full_name = - os_portable_append_dir(_output_path, "__yosys_exec_result.txt"); - { // export to ys_script_name - std::ofstream ys_script_fout(ys_script_name); - - std::string write_smt2_options = - " -mem -bv "; // future work : -stbv, or nothing - // if (_vtg_config.YosysSmtStateSort == _vtg_config.DataSort) - write_smt2_options += "-stdt "; - // else if (_vtg_config.YosysSmtStateSort == _vtg_config.BitVec) - // write_smt2_options += "-stbv "; - // else - // ILA_CHECK(false) << "Unsupported smt state sort encoding:" << - // _vtg_config.YosysSmtStateSort; - - ys_script_fout << "read_verilog -sv " - << os_portable_append_dir(_output_path, top_file_name) - << std::endl; - ys_script_fout << "prep -top " << top_mod_name << std::endl; - - auto chcGenSmtTemplate = _vtg_config.ChcWordBlastArray - ? chcGenerateSmtScript_wo_Array - : chcGenerateSmtScript_w_Array; - - ys_script_fout << ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll(ReplaceAll(chcGenSmtTemplate, "%flatten%", - _vtg_config.YosysSmtFlattenHierarchy - ? "flatten;" - : ""), - "%setundef -undriven -init -expose%", - _vtg_config.YosysUndrivenNetAsInput - ? "setundef -undriven -init -expose" - : ""), - "%rstlen%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%cycle%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%module%", top_mod_name); - - ys_script_fout << "write_smt2" << write_smt2_options << smt_name; - } // finish writing - - std::string yosys = "yosys"; - - if (!_vtg_config.YosysPath.empty()) - yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); - - // execute it - std::vector cmd; - cmd.push_back(yosys); - cmd.push_back("-s"); - cmd.push_back(ys_script_name); - auto res = os_portable_execute_shell(cmd, ys_output_full_name); - ILA_ERROR_IF(res.failure != res.NONE) << "Executing Yosys failed!"; - ILA_ERROR_IF(res.failure == res.NONE && res.ret != 0) - << "Yosys returns error code:" << res.ret; -} // design_only_gen_smt - -// currently we don't support prepresenting state using a bit vector -#if 0 -void VlgSglTgtGen_Chc::convert_smt_to_chc_bitvec( - const std::string & smt_fname, const std::string & chc_fname, - const std::string & wrapper_mod_name) { - - std::stringstream ibuf; - { // read file - std::ifstream smt_fin( smt_fname ); - if(! smt_fin.is_open()) { - ILA_ERROR << "Cannot read from " << smt_fname; - return; - } - ibuf << smt_fin.rdbuf(); - } // end read file - - std::string smt_converted; - smt_converted = ibuf.str(); - - std::string chc; - - chc = ReplaceAll(inv_syn_tmpl_datatypes, - "%(set-option :fp.engine spacer)%" , - s_backend == synthesis_backend_selector::GRAIN ? "" : "(set-option :fp.engine spacer)"); - chc = ReplaceAll(chc, "(|%1%_h| |__BI__|)", _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__BI__|)"); - chc = ReplaceAll(chc, "(|%1%_h| |__I__|)" , _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__I__|)"); - chc = ReplaceAll(chc, "(|%1%_h| |__S__|)" , _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__S__|)"); - chc = ReplaceAll(chc, "(|%1%_h| |__S'__|)", _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__S'__|)"); - chc = ReplaceAll(chc,"%1%", wrapper_mod_name); - chc = ReplaceAll(chc, "%%", smt_converted ); - - { // (query fail :print-certificate true) - if (generate_proof) - chc += "\n(query fail :print-certificate true)\n"; - else - chc += "\n(query fail)\n"; - } - - { // write file - std::ofstream chc_fout(chc_fname); - if (! chc_fout.is_open()) { - ILA_ERROR << "Error writing to : "<< chc_fname; - return; - } - chc_fout << chc; - } // end write file -} -#endif - -void VlgSglTgtGen_Chc::convert_smt_to_chc_datatype( - const std::string& smt_fname, const std::string& chc_fname) { - - std::stringstream ibuf; - { // read file - std::ifstream smt_fin(smt_fname); - if (!smt_fin.is_open()) { - ILA_ERROR << "Cannot read from " << smt_fname; - return; - } - ibuf << smt_fin.rdbuf(); - } // end read file - - std::string smt_converted; - design_smt_info = std::make_shared(ibuf.str()); - if (_vtg_config.YosysSmtFlattenDatatype) { - design_smt_info->BreakDatatypes(); - // smt_rewriter.AddNoChangeStateUpdateFunction(); - smt_converted = design_smt_info->Export(); - } else { - smt_converted = ibuf.str(); - } - - std::string wrapper_mod_name = - design_smt_info->get_module_def_orders().back(); - // construct the template - - std::string chc; - if (_vtg_config.YosysSmtFlattenDatatype) { - const auto& datatype_top_mod = - design_smt_info->get_module_flatten_dt(wrapper_mod_name); - auto tmpl = ReplaceAll(inv_syn_tmpl_wo_datatypes, - "%(set-option :fp.engine spacer)%", - s_backend == synthesis_backend_selector::GRAIN - ? "" - : "(set-option :fp.engine spacer)"); - - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_u| %Ss%)", - _vtg_config.ChcAssumptionsReset ? "(|%WrapperName%_u| %Ss%)" : ""); - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_u| %Sps%)", - _vtg_config.ChcAssumptionNextState ? "(|%WrapperName%_u| %Sps%)" : ""); - tmpl = ReplaceAll(tmpl, "(|%WrapperName%_u| %Ss%)", - _vtg_config.ChcAssumptionEnd ? "(|%WrapperName%_u| %Ss%)" - : ""); - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_h| %Ss%)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%WrapperName%_h| %Ss%)"); - tmpl = ReplaceAll(tmpl, "(|%WrapperName%_h| %Sps%)", - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : "(|%WrapperName%_h| %Sps%)"); - tmpl = ReplaceAll(tmpl, "(and", - !_vtg_config.ChcAssumptionsReset && - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : "(and"); - tmpl = ReplaceAll(tmpl, ")", - !_vtg_config.ChcAssumptionsReset && - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : ")"); - - chc = RewriteDatatypeChc(tmpl, datatype_top_mod, wrapper_mod_name); - - chc = ReplaceAll(chc, "%%", smt_converted); - - } else { - chc = ReplaceAll(inv_syn_tmpl_datatypes, "%(set-option :fp.engine spacer)%", - s_backend == synthesis_backend_selector::GRAIN - ? "" - : "(set-option :fp.engine spacer)"); - - chc = - ReplaceAll(chc, "(|%1%_u| |__S__|)", - _vtg_config.ChcAssumptionsReset ? "(|%1%_u| |__S__|)" : ""); - chc = ReplaceAll(chc, "(|%1%_u| |__S'__|)", - _vtg_config.ChcAssumptionNextState ? "(|%1%_u| |__S'__|)" - : ""); - chc = ReplaceAll(chc, "(|%1%_u| |__S__|)", - _vtg_config.ChcAssumptionEnd ? "(|%1%_u| |__S__|)" : ""); - chc = ReplaceAll( - chc, "(|%1%_h| |__S__|)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__S__|)"); - chc = ReplaceAll( - chc, "(|%1%_h| |__S'__|)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__S'__|)"); - chc = ReplaceAll(chc, "(and", - !_vtg_config.ChcAssumptionsReset && - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : "(and"); - chc = ReplaceAll(chc, ")", - !_vtg_config.ChcAssumptionsReset && - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : ")"); - chc = ReplaceAll(chc, "%1%", wrapper_mod_name); - chc = ReplaceAll(chc, "%%", smt_converted); - } // end of ~_vtg_config.YosysSmtFlattenDatatype -- no convert - - { // (query fail :print-certificate true) - if (generate_proof) - chc += "\n(query fail :print-certificate true)\n"; - else - chc += "\n(query fail)\n"; - } - - { // write file - std::ofstream chc_fout(chc_fname); - if (!chc_fout.is_open()) { - ILA_ERROR << "Error writing to : " << chc_fname; - return; - } - chc_fout << chc; - } // end write file - -} // convert_smt_to_chc_datatype - -// %WrapperName% -// %WrapperDataType% -// %BeforeInitVar% -// %InitVar% -// %State% -// %StatePrime% -// %BIs% %Is% %Ss% %Sps% -static std::string RewriteDatatypeChc(const std::string& tmpl, - const std::vector& dt, - const std::string& wrapper_mod_name) { - - std::string chc = tmpl; - - std::vector inv_tps; - smt::YosysSmtParser::convert_datatype_to_type_vec(dt, inv_tps); - auto WrapperDataType = smt::var_type::toString(inv_tps); - - // %State% - // %StatePrime% - // declare-var s ... - std::string State; - std::string StatePrime; - // %Ss% %Sps% - std::string Ss; - std::string Sps; - bool first = true; - - std::set name_set; // avoid repetition - for (auto&& st : dt) { - auto st_name = st.verilog_name.back() == '.' || st.verilog_name.empty() - ? st.internal_name - : st.verilog_name; - st_name = ReplaceAll(st_name, "|", ""); // remove its || - // check no repetition is very important! - ILA_CHECK(!IN(st_name, name_set)) << "Bug: name repetition!"; - ILA_CHECK(!st._type.is_datatype()); - name_set.insert(st_name); - auto type_string = st._type.toString(); - State += "(declare-var |S_" + st_name + "| " + type_string + ")\n"; - StatePrime += "(declare-var |S'_" + st_name + "| " + type_string + ")\n"; - - if (!first) { - Ss += " "; - Sps += " "; - } - first = false; - Ss += "|S_" + st_name + "|"; - Sps += "|S'_" + st_name + "|"; - } - // Replacement - chc = ReplaceAll(chc, "%WrapperName%", wrapper_mod_name); - chc = ReplaceAll(chc, "%WrapperDataType%", WrapperDataType); - chc = ReplaceAll(chc, "%State%", State); - chc = ReplaceAll(chc, "%StatePrime%", StatePrime); - chc = ReplaceAll(chc, "%Ss%", Ss); - chc = ReplaceAll(chc, "%Sps%", Sps); - - return chc; -} // RewriteDatatypeChc - -}; // namespace ilang - -#endif // INVSYN_INTERFACE \ No newline at end of file diff --git a/src/vtarget-out/inv-syn/vtarget_gen_inv_enhance.cc b/src/vtarget-out/inv-syn/vtarget_gen_inv_enhance.cc deleted file mode 100644 index 247a7d250..000000000 --- a/src/vtarget-out/inv-syn/vtarget_gen_inv_enhance.cc +++ /dev/null @@ -1,680 +0,0 @@ -/// \file Verilog Verification Target Generator -- generating CHC target to -/// enhance invariant (design-only, same as the invariant target) We use yosys -/// to convert Verilog to smt-lib2, and then it will be parsed and re-format by -/// smt-io and use that information, it will create horn clauses This file -/// should not be included by the user code, as it requires the impl. - -/// This is for Grain only invariant enhancements/strengthening by syntax -// ---Hongce Zhang - -/// the monolithic CHC generation is located in inv_syn.cc - -#include -#ifdef INVSYN_INTERFACE - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -#define VLG_TRUE "`true" -#define VLG_FALSE "`false" - -// initialize templates -std::string chcEnhanceGenerateSmtScript_wo_Array = R"***( -hierarchy -check -proc -opt -opt_expr -mux_undef -opt -opt -%flatten% -sim -clock clk -reset rst -n 1 -w %topmodule% -memory -nordff -proc -opt;; -)***"; - -std::string inv_enhance_tmpl_datatypes = R"***( -;---------------------------------------- -; Single Inductive Invariant Synthesis -; Generated from ILAng -;---------------------------------------- -(set-option :fp.engine spacer) - - -%% - -;(declare-rel INIT (|%1%_s|)) -;(declare-rel T (|%1%_s|) (|%1%_s|)) -(declare-rel INV (|%1%_s|)) -(declare-rel fail ()) - - -(declare-var |__I__| |%1%_s|) - -(declare-var |__S__| |%1%_s|) -(declare-var |__S'__| |%1%_s|) - -; -------------------------------- -; note if you want it a bit faster -; if can try removing wrapper-u in rule 1 -; or remove the assume previous invariants -; -------------------------------- - -; init => inv -(rule (=> (and - (|%1%_i| |__I__|) - (|%1%_h| |__I__|) - (|%1%_u| |__I__|)) - (INV |__I__|))) - -; inv /\ T => inv -(rule (=> (and - (INV |__S__|) - (|%1%_u| |__S__|) - (|%1%_u| |__S'__|) - (|%1%_h| |__S__|) - (|%1%_h| |__S'__|) - (|%1%_t| |__S__| |__S'__|)) - (INV |__S'__|))) - -; inv /\ ~p => \bot -(rule (=> (and - (INV |__S__|) - (|%1%_u| |__S__|) - (|%1%_h| |__S__|) - (not (|%1%_a| |__S__|))) - fail)) - -; (query fail :print-certificate true) - -)***"; - -std::string inv_enhance_tmpl_wo_datatypes = R"***( -;---------------------------------------- -; Single Inductive Invariant Synthesis -; Generated from ILAng -;---------------------------------------- - -%% - -(declare-rel INV %WrapperDataType%) -(declare-rel fail ()) - -%InitVar% -;(declare-var |__I__state| Type) - -%State% -%StatePrime% -;(declare-var |__S__state| Type) -;(declare-var |__S'__state| Type) - -; same for flattened - -; init => inv -(rule (=> (and - (|%WrapperName%_i| %Is%) - (|%WrapperName%_h| %Is%) - (|%WrapperName%_u| %Is%)) - (INV %Is%))) - -; inv /\ T => inv -(rule (=> (and - (INV %Ss%) - (|%WrapperName%_u| %Ss%) - (|%WrapperName%_u| %Sps%) - (|%WrapperName%_h| %Ss%) - (|%WrapperName%_h| %Sps%) - (|%WrapperName%_t| %Ss% %Sps%)) - (INV %Sps%))) - -; inv /\ ~p => \bot -(rule (=> (and - (INV %Ss%) - (|%WrapperName%_u| %Ss%) - (|%WrapperName%_h| %Ss%) - (not (|%WrapperName%_a| %Ss%))) - fail)) - -; (query fail :print-certificate true) - -)***"; - -static std::string RewriteDatatypeChc(const std::string& tmpl, - const std::vector& dt, - const std::string& wrapper_mod_name); - -VlgSglTgtGen_Chc_wCNF::~VlgSglTgtGen_Chc_wCNF() {} - -VlgSglTgtGen_Chc_wCNF::VlgSglTgtGen_Chc_wCNF( - const std::string& - output_path, // will be a sub directory of the output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, const VerilogGenerator::VlgGenConfig& config, - nlohmann::json& _rf_vmap, nlohmann::json& _rf_cond, - VlgTgtSupplementaryInfo& _sup_info, VerilogInfo* _vlg_info_ptr, - const std::string& vlg_mod_inst_name, const std::string& ila_mod_inst_name, - const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector vbackend, - synthesis_backend_selector sbackend, const target_type_t& target_tp, - advanced_parameters_t* adv_ptr, bool GenerateProof, _chc_target_t chctarget) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, config, _rf_vmap, _rf_cond, - _sup_info, _vlg_info_ptr, vlg_mod_inst_name, - ila_mod_inst_name, wrapper_name, implementation_srcs, - implementation_include_path, vtg_config, vbackend, target_tp, - adv_ptr), - s_backend(sbackend), generate_proof(GenerateProof), - has_cex(adv_ptr && adv_ptr->_cex_obj_ptr), chc_target(chctarget) { - - ILA_CHECK(vbackend == backend_selector::YOSYS) - << "Only support using yosys for chc target"; - - ILA_CHECK(chctarget == _chc_target_t::CEX) << "Target type must be chc"; - ILA_CHECK(target_tp == target_type_t::INV_SYN_DESIGN_ONLY) - << "for cex chc, target type must be INV_SYN_DESIGN_ONLY: " << target_tp; - ILA_CHECK(has_cex) << "for cex chc, cex must be provided!"; - ILA_ERROR_IF(_vtg_config.YosysSmtStateSort != _vtg_config.Datatypes) - << "will ignore smt non-datatype encoding option"; - - ILA_CHECK(sbackend == synthesis_backend_selector::GRAIN) - << "Only support grain backend" << sbackend; - - if (sbackend == synthesis_backend_selector::GRAIN) - ILA_CHECK(vtg_config.YosysSmtFlattenDatatype) - << "For Grain, datatype must be flattened!"; -} - -/// Add an assumption -void VlgSglTgtGen_Chc_wCNF::add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) { - _problems.assumptions[dspt].exprs.push_back(aspt); -} -/// Add an assertion -void VlgSglTgtGen_Chc_wCNF::add_a_direct_assertion(const std::string& asst, - const std::string& dspt) { - _problems.assertions[dspt].exprs.push_back(asst); -} - -void VlgSglTgtGen_Chc_wCNF::PreExportProcess() { - - std::string all_assert_wire_content; - std::string all_assume_wire_content; - - ILA_CHECK(target_type == target_type_t::INV_SYN_DESIGN_ONLY); - ILA_ERROR_IF(_problems.assertions.size() != 1) << "BUG in cex extract"; - - // you need to add assumptions as well - for (auto&& pbname_prob_pair : _problems.assumptions) { - const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - ILA_DLOG("VlgSglTgtGen_Chc_wCNF.PreExportProcess") - << "Adding assumption:" << prbname; - - for (auto&& p : prob.exprs) { - vlg_wrapper.add_stmt("assume property (" + p + "); //" + prbname + "\n"); - if (all_assume_wire_content.empty()) - all_assume_wire_content = "(" + p + ")"; - else - all_assume_wire_content += "&& (" + p + ")"; - } // for prob.exprs - } // for _problems.assumption - - bool first = true; - // this is to check given invariants - for (auto&& pbname_prob_pair : _problems.assertions) { - const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - - // ILA_CHECK(prbname == "cex_nonreachable_assert") - // << "BUG: assertion can only be cex reachability queries."; - // sanity check, should only be invariant's related asserts - - for (auto&& p : prob.exprs) { - vlg_wrapper.add_stmt("assert property (" + p + "); //" + prbname + "\n"); - // there should be only one expression (for cex target) - // ILA_CHECK(all_assert_wire_content.empty()); - if (first) - all_assert_wire_content = p; - else - all_assert_wire_content += " && " + p; - - first = false; - } // for expr - } // for problem - // add assert wire (though no use : make sure will not optimized away) - ILA_CHECK(!all_assert_wire_content.empty()) << "no property to check!"; - - vlg_wrapper.add_wire("__all_assert_wire__", 1, true); - vlg_wrapper.add_output("__all_assert_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); - - if (!all_assume_wire_content.empty()) { - vlg_wrapper.add_wire("__all_assume_wire__", 1, true); - vlg_wrapper.add_output("__all_assume_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assume_wire__", all_assume_wire_content); - } -} // PreExportProcess - -/// export the script to run the verification : -/// like "yosys gemsmt.ys" -void VlgSglTgtGen_Chc_wCNF::Export_script(const std::string& script_name, - const std::string& cnf_name) { - chc_run_script_name = script_name; - /// TODO: BUG: modify this : use z3/freqHorn - - auto fname = os_portable_append_dir(_output_path, script_name); - std::ofstream fout(fname); - if (!fout.is_open()) { - ILA_ERROR << "Error writing to file:" << fname; - return; - } - fout << "#!/bin/bash" << std::endl; - // fout << "trap \"trap - SIGTERM && kill -- -$$\" SIGINT SIGTERM"< lineno - // open, read, count and write - // if it is a port name, we will ask user to specify its upper level - // signal name - VerilogModifier vlg_mod(vlg_info_ptr, - static_cast( - _vtg_config.PortDeclStyle), - _vtg_config.PonoAddKeep, - supplementary_info.width_info); - - for (auto&& refered_vlg_item : _all_referred_vlg_names) { - auto idx = refered_vlg_item.first.find("["); - auto removed_range_name = refered_vlg_item.first.substr(0, idx); - vlg_mod.RecordKeepSignalName(removed_range_name); - // auto sig = // no use, this is too late, vlg_wrapper already exported - vlg_mod.RecordConnectSigName(removed_range_name, - refered_vlg_item.second.range); - // vlg_wrapper.add_output(sig.first, sig.second); - } - vlg_mod.FinishRecording(); - - // auto tmp_fn = os_portable_append_dir(_output_path, tmp_design_file); - auto tmp_fn = os_portable_append_dir(_output_path, top_file_name); - // now let's do the job - for (auto&& fn : vlg_design_files) { - std::ifstream fin(fn); - std::ofstream fout(tmp_fn, std::ios_base::app); // append to a temp file - if (!fin.is_open()) { - ILA_ERROR << "Cannot read file:" << fn; - continue; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot open file for write:" << tmp_fn; - continue; - } - vlg_mod.ReadModifyWrite(fn, fin, fout); - } // for (auto && fn : vlg_design_files) - - // handles the includes - // .. (copy all the verilog file in the folder), this has to be os independent - if (vlg_include_files_path.size() != 0) { - // copy the files and specify the -I commandline to the run.sh - for (auto&& include_path : vlg_include_files_path) - os_portable_copy_dir(include_path, _output_path); - } - -} // Export_modify_verilog - -/// export the memory abstraction (implementation) -/// Yes, this is also implementation specific, (jasper may use a different one) -void VlgSglTgtGen_Chc_wCNF::Export_mem(const std::string& mem_name) { - // we will ignore the mem_name - - auto outfn = os_portable_append_dir(_output_path, top_file_name); - std::ofstream fout(outfn, std::ios_base::app); // append - - VlgAbsMem::OutputMemFile(fout, - _vtg_config.VerificationSettingAvoidIssueStage); -} - -// export the chc file -void VlgSglTgtGen_Chc_wCNF::Export_problem(const std::string& extra_name) { - // used by export script! - chc_prob_fname = extra_name; - - // first generate a temporary smt - // and extract from it the necessary info - - // first generate a temporary smt - // and extract from it the necessary info - // this is the CHC-style thing - design_only_gen_smt( - os_portable_append_dir(_output_path, "__design_smt.smt2"), - os_portable_append_dir(_output_path, "__gen_smt_script.ys")); - - convert_smt_to_chc_datatype( - os_portable_append_dir(_output_path, "__design_smt.smt2"), - os_portable_append_dir(_output_path, - s_backend == synthesis_backend_selector::GRAIN - ? "grain_prep.txt" - : extra_name)); - - // for grain : convert wrapper# --> w wrapper_ --> w - if (s_backend == synthesis_backend_selector::GRAIN) { - std::ifstream fin(os_portable_append_dir(_output_path, "grain_prep.txt")); - std::ofstream fout(os_portable_append_dir(_output_path, extra_name)); - if (!fin.is_open()) { - ILA_ERROR << "Cannot read from : " - << os_portable_append_dir(_output_path, "grain_prep.txt"); - return; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot write to : " - << os_portable_append_dir(_output_path, extra_name); - return; - } - std::string line; - while (std::getline(fin, line)) { - fout << ReplaceAll(ReplaceAll(line, "wrapper#", "w"), "wrapper_", "w_") - << "\n"; - } - } - -} // Export_problem - -std::shared_ptr -VlgSglTgtGen_Chc_wCNF::GetDesignSmtInfo() const { - return design_smt_info; -} - -void VlgSglTgtGen_Chc_wCNF::ExportAll( - const std::string& wrapper_name, // wrapper.v - const std::string& ila_vlg_name, // no use - const std::string& script_name, // the run.sh - const std::string& extra_name, // the chc - const std::string& mem_name, const std::string& cnf_name, - const InvariantInCnf& cnf) { // no use - - PreExportProcess(); - - if (os_portable_mkdir(_output_path) == false) - ILA_WARN << "Cannot create output directory:" << _output_path; - - // you don't need to worry about the path and names - Export_wrapper(wrapper_name); - // design only - // if (target_type == target_type_t::INSTRUCTIONS) - // Export_ila_vlg(ila_vlg_name); // this has to be after Export_wrapper - - // for Jasper, this will be put to multiple files - // for CoSA & Yosys, this will be put after the wrapper file (wrapper.v) - Export_modify_verilog(); // this must be after Export_wrapper - Export_mem(mem_name); - - // you need to create the map function -- - Export_problem(extra_name); // the gensmt.ys - if (_vtg_config.GrainHintsUseCnfStyle) - Export_cnf(cnf, cnf_name); - else - Export_coci(cnf, cnf_name); - Export_script(script_name, cnf_name); -} - -void VlgSglTgtGen_Chc_wCNF::Export_coci(const InvariantInCnf& cnf, - const std::string& cnf_fn) const { - auto fn = os_portable_append_dir(_output_path, cnf_fn); - std::ofstream fout(fn); - if (!fout.is_open()) { - ILA_ERROR << "Unable to open " << fn << " for write."; - return; - } - cnf.ExportInCociFormat(fout); -} - -void VlgSglTgtGen_Chc_wCNF::Export_cnf(const InvariantInCnf& cnf, - const std::string& cnf_fn) const { - auto fn = os_portable_append_dir(_output_path, cnf_fn); - std::ofstream fout(fn); - if (!fout.is_open()) { - ILA_ERROR << "Unable to open " << fn << " for write."; - return; - } - cnf.ExportInCnfFormat(fout); -} - -void VlgSglTgtGen_Chc_wCNF::Export_script(const std::string& script_name) { - ILA_CHECK(false) << "Deprecated. Should not be used!"; -} -void VlgSglTgtGen_Chc_wCNF::ExportAll(const std::string& wrapper_name, - const std::string& ila_vlg_name, - const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name) { - ILA_CHECK(false) << "Deprecated. Should not be used!"; -} - -/// generate the wrapper's smt first -void VlgSglTgtGen_Chc_wCNF::design_only_gen_smt( - const std::string& smt_name, const std::string& ys_script_name) { - - auto ys_output_full_name = - os_portable_append_dir(_output_path, "__yosys_exec_result.txt"); - { // export to ys_script_name - std::ofstream ys_script_fout(ys_script_name); - - std::string write_smt2_options = - " -mem -bv "; // future work : -stbv, or nothing - write_smt2_options += "-stdt "; - - ys_script_fout << "read_verilog -sv " - << os_portable_append_dir(_output_path, top_file_name) - << std::endl; - ys_script_fout << "prep -top " << top_mod_name << std::endl; - ys_script_fout << ReplaceAll( - ReplaceAll(chcEnhanceGenerateSmtScript_wo_Array, "%flatten%", - _vtg_config.YosysSmtFlattenHierarchy ? "flatten;" : ""), - "%topmodule%", top_mod_name); - ys_script_fout << "write_smt2" << write_smt2_options << smt_name; - } // finish writing - - std::string yosys = "yosys"; - - if (!_vtg_config.YosysPath.empty()) - yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); - - // execute it - std::vector cmd; - cmd.push_back(yosys); - cmd.push_back("-s"); - cmd.push_back(ys_script_name); - auto res = os_portable_execute_shell(cmd, ys_output_full_name); - ILA_ERROR_IF(res.failure != res.NONE) << "Executing Yosys failed!"; - ILA_ERROR_IF(res.failure == res.NONE && res.ret != 0) - << "Yosys returns error code:" << res.ret; -} // design_only_gen_smt - -void VlgSglTgtGen_Chc_wCNF::convert_smt_to_chc_datatype( - const std::string& smt_fname, const std::string& chc_fname) { - - std::stringstream ibuf; - { // read file - std::ifstream smt_fin(smt_fname); - if (!smt_fin.is_open()) { - ILA_ERROR << "Cannot read from " << smt_fname; - return; - } - ibuf << smt_fin.rdbuf(); - } // end read file - - std::string smt_converted; - design_smt_info = std::make_shared(ibuf.str()); - // if (_vtg_config.YosysSmtFlattenDatatype) { - design_smt_info->BreakDatatypes(); - // smt_rewriter.AddNoChangeStateUpdateFunction(); - smt_converted = design_smt_info->Export(); - //} else { - // smt_converted = ibuf.str(); - //} - - std::string wrapper_mod_name = - design_smt_info->get_module_def_orders().back(); - // construct the template - - std::string chc; - // if (_vtg_config.YosysSmtFlattenDatatype) { - const auto& datatype_top_mod = - design_smt_info->get_module_flatten_dt(wrapper_mod_name); - auto tmpl = inv_enhance_tmpl_wo_datatypes; - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_h| %Ss%)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%WrapperName%_h| %Ss%)"); - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_h| %Sps%)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%WrapperName%_h| %Sps%)"); - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_h| %BIs%)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%WrapperName%_h| %BIs%)"); - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_h| %Is%)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%WrapperName%_h| %Is%)"); - chc = RewriteDatatypeChc(tmpl, datatype_top_mod, wrapper_mod_name); - chc = ReplaceAll(chc, "%%", smt_converted); - //} else { - // chc = inv_enhance_tmpl_datatypes; - // chc = ReplaceAll(chc, "(|%1%_h| |__BI__|)", - // _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__BI__|)"); chc = - // ReplaceAll(chc, "(|%1%_h| |__I__|)" , - // _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__I__|)"); chc = - // ReplaceAll(chc, "(|%1%_h| |__S__|)" , - // _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__S__|)"); chc = - // ReplaceAll(chc, "(|%1%_h| |__S'__|)", - // _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__S'__|)"); chc = - // ReplaceAll(chc,"%1%", wrapper_mod_name); chc = ReplaceAll(chc, "%%", - // smt_converted ); - //} // end of ~_vtg_config.YosysSmtFlattenDatatype -- no convert - - { // (query fail :print-certificate true) - if (generate_proof) - chc += "\n(query fail :print-certificate true)\n"; - else - chc += "\n(query fail)\n"; - } - - { // write file - std::ofstream chc_fout(chc_fname); - if (!chc_fout.is_open()) { - ILA_ERROR << "Error writing to : " << chc_fname; - return; - } - chc_fout << chc; - } // end write file - -} // convert_smt_to_chc_datatype - -// %WrapperName% -// %WrapperDataType% -// %InitVar% -// %State% -// %StatePrime% -// %BIs% %Is% %Ss% %Sps% -static std::string RewriteDatatypeChc(const std::string& tmpl, - const std::vector& dt, - const std::string& wrapper_mod_name) { - - std::string chc = tmpl; - - std::vector inv_tps; - smt::YosysSmtParser::convert_datatype_to_type_vec(dt, inv_tps); - auto WrapperDataType = smt::var_type::toString(inv_tps); - - // %InitVar% - // %State% - // %StatePrime% - // declare-var s ... - std::string InitVar; - std::string State; - std::string StatePrime; - // %BIs% %Is% %Ss% %Sps% - std::string BIs; - std::string Is; - std::string Ss; - std::string Sps; - bool first = true; - - std::set name_set; // avoid repetition - for (auto&& st : dt) { - auto st_name = st.verilog_name.back() == '.' || st.verilog_name.empty() - ? st.internal_name - : st.verilog_name; - st_name = ReplaceAll(st_name, "|", ""); // remove its || - // check no repetition is very important! - ILA_CHECK(!IN(st_name, name_set)) << "Bug: name repetition!"; - ILA_CHECK(!st._type.is_datatype()); - name_set.insert(st_name); - auto type_string = st._type.toString(); - InitVar += "(declare-var |I_" + st_name + "| " + type_string + ")\n"; - State += "(declare-var |S_" + st_name + "| " + type_string + ")\n"; - StatePrime += "(declare-var |S'_" + st_name + "| " + type_string + ")\n"; - - if (!first) { - Is += " "; - Ss += " "; - Sps += " "; - } - first = false; - Is += "|I_" + st_name + "|"; - Ss += "|S_" + st_name + "|"; - Sps += "|S'_" + st_name + "|"; - } - // Replacement - chc = ReplaceAll(chc, "%WrapperName%", wrapper_mod_name); - chc = ReplaceAll(chc, "%WrapperDataType%", WrapperDataType); - chc = ReplaceAll(chc, "%InitVar%", InitVar); - chc = ReplaceAll(chc, "%State%", State); - chc = ReplaceAll(chc, "%StatePrime%", StatePrime); - chc = ReplaceAll(chc, "%Is%", Is); - chc = ReplaceAll(chc, "%Ss%", Ss); - chc = ReplaceAll(chc, "%Sps%", Sps); - - return chc; -} // RewriteDatatypeChc - -}; // namespace ilang - -#endif // INVSYN_INTERFACE diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index c06e7d20e..df9ed6adc 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -82,7 +82,9 @@ VlgSglTgtGen::VlgSglTgtGen( // [this](const std::string& n) -> bool { return TryFindIlaInput(n); }, // [this](const std::string& n) -> bool { return TryFindVlgState(n); }), // ref to refmaps - refinement_map(refinement, ??? /*type checker*/, + refinement_map(refinement, /*type checker*/ + [this](const std::string& n) -> rfmap::RfVarTypeOrig { + return this->VarTypeCheckForRfExprParsing(n); }, vlg_ila.GetDecodeSignalName(instr_ptr), vlg_ila.GetValidSignalName(instr_ptr)), @@ -140,19 +142,7 @@ VlgSglTgtGen::VlgSglTgtGen( ILA_ERROR << "Implementation bug btw. vlg gen and vtarget-gen"; _bad_state = true; } - - auto& instr = get_current_instruction_rf(); - if (instr.is_null()) { - ILA_ERROR << "No refinement relation is defined for current instruction:" - << instr_ptr->name().str(); - _bad_state = true; - } - // check for fields in - if (!IN("instruction", instr) || !instr["instruction"].is_string()) { - ILA_ERROR << "RF: `instruction` field must be a string for " - << instr_ptr->name().str(); - _bad_state = true; - } + } // END of target_type == INSTRUCTION else if (target_type == target_type_t::INVARIANTS) { ILA_WARN_IF(instr_ptr != nullptr) @@ -169,8 +159,26 @@ void VlgSglTgtGen::ConstructWrapper_generate_header() { void VlgSglTgtGen::ConstructWrapper_add_inputmap_assumptions() { + std::set ila_input_names; + + for (size_t input_idx = 0; input_idx < _host->input_num(); ++input_idx) + ila_input_names.insert(_host->input(input_idx)->name().str()); + for (const auto & iv_rfmap : refinement_map.ila_input_var_map) { - + const auto & iname = iv_rfmap.first; + if(ila_input_names.find(iname) != ila_input_names.end()) { + ILA_ERROR << "Cannot find ILA input with name: " << iname; + continue; + } + ila_input_names.erase(iname); + } + + + + if(!ila_input_names.empty()) { + ILA_ERROR << "Lack input var map for the following variables:"; + for(const auto & in : ila_input_names) + ILA_ERROR << in; } } @@ -235,45 +243,32 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { for (size_t state_idx = 0; state_idx < _host->state_num(); ++state_idx) ila_state_names.insert(_host->state(state_idx)->name().str()); - nlohmann::json& state_mapping = IN("state mapping", rf_vmap) - ? rf_vmap["state mapping"] - : rf_vmap["state-mapping"]; - for (auto& i : state_mapping.items()) { - auto sname = i.key(); - if (!IN(sname, ila_state_names)) { + for (const auto & sv_rfmap : refinement_map.ila_state_var_map) { + const auto & sname = sv_rfmap.first; + if(!IN(sname, ila_state_names)) { ILA_ERROR << sname << " is not a state of the ILA:" << _host->name().str(); continue; } + ila_state_names.erase(sname); + if (_vtg_config.OnlyCheckInstUpdatedVars && _instr_ptr->update(sname) == nullptr) { - - // do not skip memory, though we don't use the eq signal it returns - if (_host->state(sname)->is_mem()) - GetStateVarMapExpr(sname, i.value(), true); - - ILA_DLOG("VtargetGen") << "Skip checking variable:" << sname - << " for instruction:" << _instr_ptr->name().str(); - continue; + ILA_DLOG("VtargetGen") << "Skip assume EQ on variable:" << sname + << " for instruction:" << _instr_ptr->name().str(); + continue; } - - ila_state_names.erase(sname); - - // report the need of refinement map - if (_instr_ptr->update(sname)) { - FunctionApplicationFinder func_app_finder(_instr_ptr->update(sname)); - for (auto&& func_ptr : func_app_finder.GetReferredFunc()) { - // handle the IteUnknown function case - - ILA_ERROR_IF(!(IN("functions", rf_vmap) && - rf_vmap["functions"].is_object() && - IN(func_ptr->name().str(), rf_vmap["functions"]))) - << "uf: " << func_ptr->name().str() << " in " - << _instr_ptr->name().str() << " updating state:" << sname - << " is not provided in rfmap!"; - } + ILA_DLOG("VtargetGen.ConstructWrapper_add_varmap_assertions") << sname; + + // just check if we miss any function in uf section + FunctionApplicationFinder func_app_finder(_instr_ptr->update(sname)); + for (auto&& func_ptr : func_app_finder.GetReferredFunc()) { + // handle the IteUnknown function case + ILA_ERROR_IF(!IN(func_ptr->name().str(), refinement_map.uf_application)) + << "uf: " << func_ptr->name().str() << " in " + << _instr_ptr->name().str() << " updating state:" << sname + << " is not provided in rfmap!"; } - // ISSUE ==> vmap std::string precondition = "(~ __IEND__) || "; @@ -292,10 +287,9 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { // for Yosys inv-synthesis, we don't mind the precondition // that's part the assertions, so it should be fine - add_an_assertion(precondition + "(" + - GetStateVarMapExpr(sname, i.value(), true) + ")", - problem_name); - } + + Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, false, "(~ __IEND__ )|| (", ")" ); + } // end - for each state var } // ConstructWrapper_add_varmap_assertions // NON-FLUSH case @@ -344,13 +338,10 @@ void VlgSglTgtGen::ConstructWrapper() { ILA_DLOG("VtargetGen") << "STEP:" << 5.4; ConstructWrapper_add_inv_assumption_or_assertion_target_instruction(); } else if (target_type == target_type_t::INVARIANTS) { - ConstructWrapper_inv_syn_connect_mem(); // the same as inv-syn so I add it - // here ConstructWrapper_add_inv_assumption_or_assertion_target_invariant(); max_bound = _vtg_config.MaxBound; } else if (target_type == target_type_t::INV_SYN_DESIGN_ONLY) { ConstructWrapper_inv_syn_cond_signals(); - ConstructWrapper_inv_syn_connect_mem(); ConstructWrapper_add_inv_assumption_or_assertion_target_inv_syn_design_only(); } @@ -383,10 +374,6 @@ void VlgSglTgtGen::ConstructWrapper() { // add monitor -- inside the monitor, there will be // disable logic if it is for invariant type target - // 6. helper memory - ConstructWrapper_add_helper_memory(); // need to decide what is the target - // type - // 5.0 add the extra wires to the top module wrapper if (VlgVerifTgtGenBase::backend_needs_yosys(_backend)) ConstructWrapper_register_extra_io_wire(); @@ -445,8 +432,7 @@ void VlgSglTgtGen::Export_ila_vlg(const std::string& ila_vlg_name) { void VlgSglTgtGen::ExportAll(const std::string& wrapper_name, const std::string& ila_vlg_name, const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name) { + const std::string& extra_name) { PreExportProcess(); if (os_portable_mkdir(_output_path) == false) ILA_WARN << "Cannot create output directory:" << _output_path; @@ -458,9 +444,9 @@ void VlgSglTgtGen::ExportAll(const std::string& wrapper_name, // for Jasper, this will be put to multiple files // for CoSA & Yosys, this will be put after the wrapper file (wrapper.v) Export_modify_verilog(); // this must be after Export_wrapper - Export_mem(mem_name); - Export_problem(extra_name); + Export_problem(extra_name); // for JG this is do.tcl + // for Pono: this is the yosys.script and Export_script(script_name); } // end of ExportAll diff --git a/src/vtarget-out/single_target_inv_syn_support.cc b/src/vtarget-out/single_target_inv_syn_support.cc index f34e222fc..235403489 100644 --- a/src/vtarget-out/single_target_inv_syn_support.cc +++ b/src/vtarget-out/single_target_inv_syn_support.cc @@ -73,14 +73,17 @@ void VlgSglTgtGen::add_inv_obj_as_assertion(InvariantObject* inv_obj) { vlg_wrapper.add_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair), true); vlg_wrapper.add_assign_stmt(std::get<0>(name_expr_pair), - ReplExpr(std::get<1>(name_expr_pair), true)); + ReplExpr( + refinement_map.ParseRfExprFromString( + std::get<1>(name_expr_pair)))); } for (auto&& name_w_pair : inv_obj->GetExtraFreeVarDefs()) { vlg_wrapper.add_wire(name_w_pair.first, name_w_pair.second, true); vlg_wrapper.add_input(name_w_pair.first, name_w_pair.second); } for (auto&& inv_expr : inv_obj->GetVlgConstraints()) { - auto new_cond = ReplExpr(inv_expr, true); + auto new_cond = ReplExpr( + refinement_map.ParseRfExprFromString(inv_expr)); ILA_CHECK(!S_IN("][", new_cond)) << "Inv translate error: ][ found in:" << new_cond; add_an_assertion(new_cond, "invariant_assert"); @@ -93,14 +96,16 @@ void VlgSglTgtGen::add_inv_obj_as_assumption(InvariantObject* inv_obj) { vlg_wrapper.add_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair), true); vlg_wrapper.add_assign_stmt(std::get<0>(name_expr_pair), - ReplExpr(std::get<1>(name_expr_pair), true)); + ReplExpr( + refinement_map.ParseRfExprFromString(std::get<1>(name_expr_pair)))); } for (auto&& name_w_pair : inv_obj->GetExtraFreeVarDefs()) { vlg_wrapper.add_wire(name_w_pair.first, name_w_pair.second, true); vlg_wrapper.add_input(name_w_pair.first, name_w_pair.second); } for (auto&& inv_expr : inv_obj->GetVlgConstraints()) { - auto new_cond = ReplExpr(inv_expr, true); + auto new_cond = ReplExpr( + refinement_map.ParseRfExprFromString(inv_expr)); ILA_CHECK(!S_IN("][", new_cond)) << "Inv translate error: ][ found in:" << new_cond; add_an_assumption(new_cond, "invariant_assume"); @@ -109,11 +114,8 @@ void VlgSglTgtGen::add_inv_obj_as_assumption(InvariantObject* inv_obj) { void VlgSglTgtGen::add_rf_inv_as_assumption() { if (has_rf_invariant) { - nlohmann::json& inv = IN("global invariants", rf_cond) - ? rf_cond["global invariants"] - : rf_cond["global-invariants"]; - for (auto& cond : inv) { - auto new_cond = ReplExpr(cond.get(), true); + for (auto&& cond : refinement_map.global_invariants) { + auto new_cond = ReplExpr(cond); add_an_assumption(new_cond, "invariant_assume"); // without new var added } // for inv in global invariants field } @@ -122,12 +124,9 @@ void VlgSglTgtGen::add_rf_inv_as_assumption() { void VlgSglTgtGen::add_rf_inv_as_assertion() { // the provided invariants if (has_rf_invariant) { - nlohmann::json& inv = IN("global invariants", rf_cond) - ? rf_cond["global invariants"] - : rf_cond["global-invariants"]; - for (auto& cond : inv) { + for (auto& cond : refinement_map.global_invariants) { auto new_cond = - ReplExpr(cond.get(), true); // force vlg state + ReplExpr(cond); // force vlg state add_an_assertion("(" + new_cond + ")", "invariant_assert"); } } // has_rf_invariant @@ -211,8 +210,9 @@ void VlgSglTgtGen:: // this is cex reachability checking // -- assertions -- // auto new_cond = - ReplExpr(_advanced_param_ptr->_cex_obj_ptr->GenInvAssert(""), - true); // force vlg state + ReplExpr( + refinement_map.ParseRfExprFromString( + _advanced_param_ptr->_cex_obj_ptr->GenInvAssert(""))); // force vlg state add_an_assertion("~(" + new_cond + ")", "cex_nonreachable_assert"); // -- assumption -- // if (_vtg_config.InvariantSynthesisReachableCheckKeepOldInvariant) { @@ -249,45 +249,5 @@ void VlgSglTgtGen::ConstructWrapper_inv_syn_cond_signals() { vlg_wrapper.add_input("__STARTED__", 1); } -void VlgSglTgtGen::ConstructWrapper_inv_syn_connect_mem() { - ILA_CHECK(target_type == target_type_t::INV_SYN_DESIGN_ONLY || - target_type == target_type_t::INVARIANTS); - - std::map> ila_mem_state_names; - - for (size_t state_idx = 0; state_idx < _host->state_num(); ++state_idx) { - if (_host->state(state_idx)->is_mem()) - ila_mem_state_names.insert( - std::make_pair(_host->state(state_idx)->name().str(), - std::make_pair( - _host->state(state_idx)->sort()->addr_width(), - _host->state(state_idx)->sort()->data_width()))); - } - nlohmann::json& state_mapping = IN("state mapping", rf_vmap) - ? rf_vmap["state mapping"] - : rf_vmap["state-mapping"]; - for (auto& i : state_mapping.items()) { - auto sname = i.key(); // ila state name - if (!IN(sname, ila_mem_state_names)) - continue; // we only care about the mem states - if (i.value().is_null()) { - ILA_ERROR << "Ignore mapping memory: " << sname; - continue; - } - // ILA_INFO << i.key() << i.value(); - // Connect memory here - if (i.value().is_string() && - StrStartsWith(i.value().get(), "**")) { - _idr.SetMemNameAndWidth( - i.value(), sname, _vtg_config.MemAbsReadAbstraction, - ila_mem_state_names[sname].first, ila_mem_state_names[sname].second); - ila_mem_state_names.erase(sname); - } - } - - // check for unmapped memory - for (auto&& m : ila_mem_state_names) - ILA_ERROR << "No mapping exists for memory : " << m.first; -} // ConstructWrapper_inv_syn_connect_mem } // namespace ilang diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 1dd6e7b10..f9183c85c 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -197,7 +197,7 @@ void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { for(const auto & n_tracker : refinement_map.phase_tracker) { - const auto & name = n_tracker.first; + const auto & tracker = n_tracker.second; for (const auto & vardef : tracker.var_defs) { const auto & vn = vardef.first; @@ -248,7 +248,7 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { const auto& monitor_rec = refinement_map.customized_monitor; for (auto&& m_rec : monitor_rec) { - const auto& mname = m_rec.first; // actually no use + const auto& mdef = m_rec.second; // generalMonitor std::string vlg_expr; diff --git a/src/vtarget-out/vtarget_gen.cc b/src/vtarget-out/vtarget_gen.cc index 24cdbba30..b634b6e21 100644 --- a/src/vtarget-out/vtarget_gen.cc +++ b/src/vtarget-out/vtarget_gen.cc @@ -10,10 +10,11 @@ namespace ilang { bool VlgVerifTgtGenBase::isValidVerifBackend(backend_selector vbackend) { - if (vbackend == backend_selector::COSA) + if (vbackend == backend_selector::PONO) return true; if (vbackend == backend_selector::JASPERGOLD) return true; + /* if (vbackend == backend_selector::RELCHC) return true; if ((vbackend & backend_selector::YOSYS) == backend_selector::YOSYS) { @@ -27,7 +28,7 @@ bool VlgVerifTgtGenBase::isValidVerifBackend(backend_selector vbackend) { vbackend == backend_selector::Z3PDR) return true; } - } + }*/ return false; } @@ -39,12 +40,14 @@ VerilogVerificationTargetGenerator::VerilogVerificationTargetGenerator( const std::string& refinement_conditions, const std::string& output_path, const InstrLvlAbsPtr& ila_ptr, backend_selector backend, const vtg_config_t& vtg_config, - const VerilogGenerator::VlgGenConfig& config) + const VerilogGenerator::VlgGenConfig& notused) : _generator(new VlgVerifTgtGen( implementation_include_path, implementation_srcs, - implementation_top_module, refinement_variable_mapping, - refinement_conditions, output_path, ila_ptr, backend, vtg_config, - config, NULL)) {} + implementation_top_module, + rfmap::VerilogRefinementMap( + refinement_variable_mapping,refinement_conditions), + output_path, ila_ptr, backend, vtg_config, + NULL)) {} VerilogVerificationTargetGenerator::~VerilogVerificationTargetGenerator() { if (_generator) diff --git a/src/vtarget-out/vtarget_gen_cosa.cc b/src/vtarget-out/vtarget_gen_cosa.cc deleted file mode 100644 index 9134400f2..000000000 --- a/src/vtarget-out/vtarget_gen_cosa.cc +++ /dev/null @@ -1,291 +0,0 @@ -/// \file Source of generating CoSA accepted problem, vlg, mem, script -// --- Hongce Zhang - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace ilang { - -#define VLG_TRUE "`true" -#define VLG_FALSE "`false" - -VlgSglTgtGen_Cosa::VlgSglTgtGen_Cosa( - const std::string& - output_path, // will be a sub directory of the output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, const VerilogGenerator::VlgGenConfig& config, - nlohmann::json& _rf_vmap, nlohmann::json& _rf_cond, - VlgTgtSupplementaryInfo& _supplementary_info, VerilogInfo* _vlg_info_ptr, - const std::string& vlg_mod_inst_name, const std::string& ila_mod_inst_name, - const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector backend, - const target_type_t& target_tp, advanced_parameters_t* adv_ptr) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, config, _rf_vmap, _rf_cond, - _supplementary_info, _vlg_info_ptr, vlg_mod_inst_name, - ila_mod_inst_name, wrapper_name, implementation_srcs, - implementation_include_path, vtg_config, backend, target_tp, - adv_ptr) {} - -#if 0 -// currently this function has no use -std::string convert_expr_to_cosa(const std::string& in) { - return ReplaceAll( - ReplaceAll(ReplaceAll(ReplaceAll(ReplaceAll(ReplaceAll(in, "&&", "&"), - "||", "|"), - "~", "!"), - "==", "="), - VLG_TRUE, "True"), - VLG_FALSE, "False"); -} -#endif - -/// Add an assumption -void VlgSglTgtGen_Cosa::add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) { - _problems.assumptions.push_back(aspt); -} -/// Add an assertion -void VlgSglTgtGen_Cosa::add_a_direct_assertion(const std::string& asst, - const std::string& dspt) { - _problems.probitem[dspt].assertions.push_back(asst); -} - -/// export the script to run the verification -void VlgSglTgtGen_Cosa::Export_script(const std::string& script_name) { - auto fname = os_portable_append_dir(_output_path, script_name); - std::ofstream fout(fname); - if (!fout.is_open()) { - ILA_ERROR << "Error writing to file:" << fname; - return; - } - fout << "#!/bin/bash" << std::endl; - if (!_vtg_config.CosaPyEnvironment.empty()) - fout << "source " << _vtg_config.CosaPyEnvironment << std::endl; - - std::string cosa = "CoSA"; - std::string options; - - if (!_vtg_config.CosaSolver.empty()) - options += " --solver-name=" + _vtg_config.CosaSolver; - if (_vtg_config.CosaGenTraceVcd) - options += " --vcd"; - if (_vtg_config.CosaFullTrace) - options += " --full-trace"; - options += " " + _vtg_config.CosaOtherSolverOptions; - - // no need, copy is good enough - // if(vlg_include_files_path.size() != 0) - // options += " -I./"; - - if (!_vtg_config.CosaPath.empty()) { - cosa = os_portable_append_dir(_vtg_config.CosaPath, cosa) + ".py"; - } - - if (cosa_prob_fname != "") - fout << cosa << " --problem " << cosa_prob_fname << options << std::endl; - else - fout << "echo 'Nothing to check!'" << std::endl; -} - -void VlgSglTgtGen_Cosa::Export_jg_tester_script(const std::string& extra_name) { - if (_problems.probitem.size() == 0) - return; - - std::ofstream fout(os_portable_append_dir(_output_path, extra_name)); - if (!fout.is_open()) { - ILA_ERROR << "Error writing file: " - << os_portable_append_dir(_output_path, extra_name); - return; - } - fout << "analyze -sva " << top_file_name << std::endl; - fout << "elaborate -top " << top_mod_name << std::endl; - fout << "clock clk" << std::endl; - fout << "reset rst" << std::endl; - - decltype(_problems.assumptions) local_assumpt; - for (auto&& p : _problems.assumptions) { - if (p == "reset_done = 1_1 -> rst = 0_1") - continue ; // must match with single_target_cond.cc - if (p == "reset_done = 1_1 -> next( reset_done ) = 1_1") - continue ; // must match with single_target_cond.cc - auto eq_idx = p.find('='); - auto rm_eq_p = p.substr(0, eq_idx); - local_assumpt.push_back(rm_eq_p); - - fout << "assume { " << rm_eq_p << " }" << std::endl; - } - // separate assumptions - // std::string assmpt = "(" + Join(local_assumpt, ") && (") + ")"; - - for (auto&& pbname_prob_pair : _problems.probitem) { - const auto& prob = pbname_prob_pair.second; - - decltype(prob.assertions) local_asst; - for (auto&& p : prob.assertions) { - auto eq_idx = p.find('='); - auto rm_eq_p = p.substr(0, eq_idx); - local_asst.push_back(rm_eq_p); - } - - auto asst = "(" + Join(local_asst, ") && (") + ")"; - fout << "assert { " << asst << " }" << std::endl; - } -} - -/// export extra things (problem) -void VlgSglTgtGen_Cosa::Export_problem(const std::string& extra_name) { - if (_problems.probitem.size() == 0) { - ILA_ERROR << "Nothing to prove, no assertions inserted!"; - return; - } - - cosa_prob_fname = extra_name; - - std::ofstream rstf(os_portable_append_dir(_output_path, "rst.ets")); - if (!rstf.is_open()) { - ILA_ERROR << "Error writing file: " - << os_portable_append_dir(_output_path, "rst.ets"); - return; - } - - rstf << "I: rst = 1_1" << std::endl; - rstf << "I: reset_done = 0_1" << std::endl; - - unsigned cycle_after_i = 1; - unsigned reset_cycle_needed = - (target_type == target_type_t::INSTRUCTIONS) && (!_vtg_config.ForceInstCheckReset )? 1: - supplementary_info.cosa_yosys_reset_config.reset_cycles; - - for (; cycle_after_i < reset_cycle_needed; ++cycle_after_i) { - rstf << "S" << cycle_after_i << ": rst = 1_1" << std::endl; - rstf << "S" << cycle_after_i << ": reset_done = 0_1" << std::endl; - } - rstf << "S" << cycle_after_i << ": rst = 0_1" << std::endl; - rstf << "S" << cycle_after_i << ": reset_done = 1_1" << std::endl; - rstf << "# TRANS" << std::endl; - rstf << "I -> S1" << std::endl; - for (cycle_after_i = 1; cycle_after_i < reset_cycle_needed; ++cycle_after_i) - rstf << "S" << cycle_after_i << " -> S" << (cycle_after_i + 1) << std::endl; - rstf << "S" << cycle_after_i << " -> S" << cycle_after_i << std::endl; - - std::ofstream fout(os_portable_append_dir(_output_path, extra_name)); - if (!fout.is_open()) { - ILA_ERROR << "Error writing file: " - << os_portable_append_dir(_output_path, extra_name); - return; - } - - fout << "[GENERAL]" << std::endl; - fout << "model_files:"; // - fout << top_file_name << "[" << top_mod_name << "],"; - // if(target_type != target_type_t::INVARIANTS ) - // fout << ila_file_name<<","; // will be combined - fout << "rst.ets"; - // for(auto && fn : vlg_design_files) // will be combined - // fout << "," << os_portable_file_name_from_path(fn); - fout << std::endl; - - fout << "assume_if_true: True" << std::endl; - fout << "abstract_clock: True" << std::endl; - fout << "[DEFAULT]" << std::endl; - fout << "bmc_length: " << std::to_string(max_bound + 5) << std::endl; - fout << "precondition: reset_done = 1_1" << std::endl; - fout << std::endl; - - std::string assmpt = "(" + Join(_problems.assumptions, ") & (") + ")"; - for (auto&& pbname_prob_pair : _problems.probitem) { - const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - auto asst = "(" + Join(prob.assertions, ") & (") + ")"; - auto prob_name = vlg_wrapper.sanitizeName(prbname); - fout << "[" << prob_name << "]" << std::endl; - fout << "description:\"" << prbname << "\"" << std::endl; - fout << "properties:" << asst << std::endl; - if (assmpt != "()") - fout << "assumptions:" << assmpt << std::endl; - fout << "prove: True" << std::endl; - fout << "verification: safety" << std::endl; - if (VlgAbsMem::hasAbsMem()) - fout << "strategy: AUTO" << std::endl; - else - fout << "strategy: ALL" << std::endl; - fout << "expected: True" << std::endl; - } - - if (_vtg_config.CosaGenJgTesterScript) - Export_jg_tester_script("jg.tcl"); - -} // only for cosa - -/// export the memory abstraction (implementation) -/// Yes, this is also implementation specific, (jasper may use a different one) -void VlgSglTgtGen_Cosa::Export_mem(const std::string& mem_name) { - // we will ignore the mem_name - - auto outfn = os_portable_append_dir(_output_path, top_file_name); - std::ofstream fout(outfn, std::ios_base::app); // append - - VlgAbsMem::OutputMemFile(fout, - _vtg_config.VerificationSettingAvoidIssueStage); -} - -/// For jasper, this means do nothing, for yosys, you need to add (*keep*) -void VlgSglTgtGen_Cosa::Export_modify_verilog() { - // collect all locations: filename -> lineno - // open, read, count and write - // if it is a port name, we will ask user to specify its upper level - // signal name - VerilogModifier vlg_mod(vlg_info_ptr, - static_cast( - _vtg_config.PortDeclStyle), - _vtg_config.PonoAddKeep, - supplementary_info.width_info); - - for (auto&& refered_vlg_item : _all_referred_vlg_names) { - auto idx = refered_vlg_item.first.find("["); - auto removed_range_name = refered_vlg_item.first.substr(0, idx); - vlg_mod.RecordKeepSignalName(removed_range_name); - // auto sig = // no use, this is too late, vlg_wrapper already exported - vlg_mod.RecordConnectSigName(removed_range_name, - refered_vlg_item.second.range); - // vlg_wrapper.add_output(sig.first, sig.second); - } - vlg_mod.FinishRecording(); - - // now let's do the job - for (auto&& fn : vlg_design_files) { - auto outfn = os_portable_append_dir(_output_path, top_file_name); - std::ifstream fin(fn); - std::ofstream fout(outfn, std::ios_base::app); // append - if (!fin.is_open()) { - ILA_ERROR << "Cannot read file:" << fn; - continue; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot open file for write:" << outfn; - continue; - } - vlg_mod.ReadModifyWrite(fn, fin, fout); - } // for (auto && fn : vlg_design_files) - // .. (copy all the verilog file in the folder), this has to be os dependent - if (vlg_include_files_path.size() != 0) { - // copy the files and specify the -I commandline to the run.sh - for (auto&& include_path : vlg_include_files_path) - os_portable_copy_dir(include_path, _output_path); - } - -} // Export_modify_verilog - -}; // namespace ilang diff --git a/src/vtarget-out/vtarget_gen_impl.cc b/src/vtarget-out/vtarget_gen_impl.cc index 768836055..c523685dc 100644 --- a/src/vtarget-out/vtarget_gen_impl.cc +++ b/src/vtarget-out/vtarget_gen_impl.cc @@ -12,14 +12,14 @@ #include #include #include -#include +#include #include -#include -#include +// #include +// #include // for invariant synthesis -#include -#include -#include +// #include +// #include +// #include namespace ilang { @@ -29,100 +29,29 @@ VlgVerifTgtGen::VlgVerifTgtGen( const std::vector& implementation_include_path, const std::vector& implementation_srcs, const std::string& implementation_top_module, - const std::string& refinement_variable_mapping, - const std::string& refinement_conditions, const std::string& output_path, - const InstrLvlAbsPtr& ila_ptr, backend_selector backend, + const rfmap::VerilogRefinementMap & refinement, + const std::string& output_path, + const InstrLvlAbsPtr& ila_ptr, + backend_selector backend, const vtg_config_t& vtg_config, - const VerilogGenerator::VlgGenConfig& vlg_gen_config, advanced_parameters_t* adv_ptr) : _vlg_impl_include_path(implementation_include_path), _vlg_impl_srcs(implementation_srcs), _vlg_impl_top_name(implementation_top_module), - _rf_var_map_name(refinement_variable_mapping), - _rf_cond_name(refinement_conditions), _output_path(output_path), + _refinement(refinement), + _output_path(output_path), _ila_ptr(ila_ptr), // configure is only for ila, generate the start signal vlg_info_ptr( NULL), // not creating it now, because we don't have the info to do so - _backend(backend), _cfg(vlg_gen_config), _vtg_config(vtg_config), + _backend(backend), _vtg_config(vtg_config), _advanced_param_ptr(adv_ptr), _bad_state(false) { - load_json(_rf_var_map_name, rf_vmap); - supplementary_info.FromJson(rf_vmap); - load_json(_rf_cond_name, rf_cond); - set_module_instantiation_name(); + if (_ila_ptr == nullptr) { ILA_ERROR << "ILA should not be none"; _bad_state = true; } - // check for json file -- global-invariants - if (!IN("global invariants", rf_cond) && !IN("global-invariants", rf_cond)) { - ILA_ERROR << "'global-invariants' must exist, can be an empty array"; - _bad_state = true; - } else if (IN("global invariants", rf_cond) && - !rf_cond["global invariants"].is_array()) { - ILA_ERROR << "'global invariants' must be an array of string"; - _bad_state = true; - } else if (IN("global-invariants", rf_cond) && - !rf_cond["global-invariants"].is_array()) { - ILA_ERROR << "'global-invariants' must be an array of string"; - _bad_state = true; - } else if (IN("global invariants", rf_cond) && - rf_cond["global invariants"].size() != 0) { - if (!rf_cond["global invariants"][0].is_string()) { - ILA_ERROR << "'global invariants' must be an array of string"; - _bad_state = true; - } - } else if (IN("global-invariants", rf_cond) && - rf_cond["global-invariants"].size() != 0) { - if (!rf_cond["global-invariants"][0].is_string()) { - ILA_ERROR << "'global-invariants' must be an array of string"; - _bad_state = true; - } - } - // check for json file -- instructions - if (!IN("instructions", rf_cond)) { - ILA_ERROR << "'instructions' must exist."; - _bad_state = true; - } else if (!rf_cond["instructions"].is_array()) { - ILA_ERROR << "'instructions' must be an array of objects."; - _bad_state = true; - } else if (rf_cond["instructions"].size() == 0) { - ILA_WARN << "No instruction in the rf specification"; - } else { - for (auto&& it : rf_cond["instructions"].items()) { - if (!it.value().is_object()) { - ILA_ERROR << "'instructions' must be an array of objects."; - _bad_state = true; - break; - } else { - if (!IN("instruction", it.value())) { - ILA_ERROR << "'instruction' field must exist in the rf object."; - _bad_state = true; - break; - } else if (!it.value()["instruction"].is_string()) { - ILA_ERROR - << "'instruction' field must be a string of instruction name."; - _bad_state = true; - break; - } - } - } - } - - // check vmap - if (!IN("models", rf_vmap) || !rf_vmap["models"].is_object()) { - ILA_ERROR << "'model' field must exist in vmap and be a map of ILA/VERILOG " - "-> 'instance name' "; - _bad_state = true; - } - if (!((IN("state mapping", rf_vmap) && - rf_vmap["state mapping"].is_object()) || - (IN("state-mapping", rf_vmap) && - rf_vmap["state-mapping"].is_object()))) { - ILA_ERROR << "'state-mapping' field must exist in vmap and be a map : " - "ila_var -> impl_var"; - _bad_state = true; - } + // TODO: check more } @@ -135,9 +64,6 @@ const std::vector& VlgVerifTgtGen::GetRunnableScriptName() const { return runnable_script_name; } -const VlgTgtSupplementaryInfo& VlgVerifTgtGen::GetSupplementaryInfo() const { - return supplementary_info; -} void VlgVerifTgtGen::GenerateTargets(void) { if (bad_state_return()) @@ -146,7 +72,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { runnable_script_name.clear(); vlg_info_ptr = new VerilogInfo(_vlg_impl_include_path, _vlg_impl_srcs, - _vlg_mod_inst_name, _vlg_impl_top_name); + "RTL", _vlg_impl_top_name); if (vlg_info_ptr == NULL || vlg_info_ptr->in_bad_state()) { ILA_ERROR << "Unable to generate targets. Verilog parser failed."; @@ -154,7 +80,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { } if (!isValidVerifBackend(_backend)) { - ILA_ERROR << "Unknown backend specification:" << _backend << ", quit."; + ILA_ERROR << "Unknown backend specification:" << int(_backend) << ", quit."; return; } @@ -162,15 +88,10 @@ void VlgVerifTgtGen::GenerateTargets(void) { _vtg_config.target_select == vtg_config_t::INV) { // check if there are really invariants: bool invariantExists = false; - if (IN("global invariants", rf_cond) || IN("global-invariants", rf_cond)) { - nlohmann::json& inv = IN("global invariants", rf_cond) - ? rf_cond["global invariants"] - : rf_cond["global-invariants"]; - if (inv.is_array() && inv.size() != 0) - invariantExists = true; - else if (inv.is_string() && inv.get() != "") - invariantExists = true; - else if ((_vtg_config.ValidateSynthesizedInvariant == + if(!_refinement.global_invariants.empty()) + invariantExists = true; + + if ((_vtg_config.ValidateSynthesizedInvariant == vtg_config_t::_validate_synthesized_inv::ALL || _vtg_config.ValidateSynthesizedInvariant == vtg_config_t::_validate_synthesized_inv::CONFIRMED) && @@ -179,7 +100,8 @@ void VlgVerifTgtGen::GenerateTargets(void) { !_advanced_param_ptr->_inv_obj_ptr->GetVlgConstraints() .empty())) invariantExists = true; - else if ((_vtg_config.ValidateSynthesizedInvariant == + + if ((_vtg_config.ValidateSynthesizedInvariant == vtg_config_t::_validate_synthesized_inv::ALL || _vtg_config.ValidateSynthesizedInvariant == vtg_config_t::_validate_synthesized_inv::CANDIDATE) && @@ -188,39 +110,40 @@ void VlgVerifTgtGen::GenerateTargets(void) { !_advanced_param_ptr->_candidate_inv_ptr->GetVlgConstraints() .empty())) invariantExists = true; - } + auto sub_output_path = os_portable_append_dir(_output_path, "invariants"); - if (_backend == backend_selector::COSA && invariantExists) { - auto target = VlgSglTgtGen_Cosa( + if (_backend == backend_selector::PONO && invariantExists) { + auto target = VlgSglTgtGen_Pono( sub_output_path, NULL, // invariant - _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + _ila_ptr, _refinement, vlg_info_ptr, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INVARIANTS, _advanced_param_ptr); target.ConstructWrapper(); - target.ExportAll("wrapper.v", "ila.v", "run.sh", "problem.txt", - "absmem.v"); - target.do_not_instantiate(); + target.ExportAll("wrapper.v", "ila.v", "run.sh", "problem.txt"); + target.do_not_instantiate(); // no use, just for coverage } else if (_backend == backend_selector::JASPERGOLD && invariantExists) { auto target = VlgSglTgtGen_Jasper( sub_output_path, NULL, // invariant - _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + _ila_ptr, _refinement, vlg_info_ptr, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INVARIANTS, _advanced_param_ptr); target.ConstructWrapper(); - target.ExportAll("wrapper.v", "ila.v", "run.sh", "do.tcl", "absmem.v"); - target.do_not_instantiate(); - } else if (_backend == backend_selector::RELCHC && invariantExists) { + target.ExportAll("wrapper.v", "ila.v", "run.sh", "do.tcl"); + target.do_not_instantiate(); // no use, just for coverage + } +#if 0 + else if (_backend == backend_selector::RELCHC && invariantExists) { // will actually fail : not supported for using relchc for invariant // targets auto target = VlgSglTgtGen_Relchc( sub_output_path, NULL, // invariant _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INVARIANTS, _advanced_param_ptr); target.ConstructWrapper(); @@ -234,7 +157,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { sub_output_path, NULL, // instruction _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INVARIANTS, _advanced_param_ptr, _chc_target_t::GENERAL_PROPERTY); @@ -252,7 +175,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { target.ExportAll("wrapper.v", "ila.v", "run.sh", design_file, "absmem.v"); target.do_not_instantiate(); } - +#endif if (invariantExists) runnable_script_name.push_back( os_portable_append_dir(sub_output_path, "run.sh")); @@ -263,9 +186,8 @@ void VlgVerifTgtGen::GenerateTargets(void) { // now let's deal w. instructions in rf_cond if (_vtg_config.target_select == vtg_config_t::BOTH || _vtg_config.target_select == vtg_config_t::INST) { - auto& instrs = rf_cond["instructions"]; - for (auto&& instr : instrs) { - std::string iname = instr["instruction"].get(); + for (auto&& instr : _refinement.inst_complete_cond) { + std::string iname = instr.first; if (_vtg_config.CheckThisInstructionOnly != "" && _vtg_config.CheckThisInstructionOnly != iname) continue; // skip, not checking this instruction @@ -279,37 +201,38 @@ void VlgVerifTgtGen::GenerateTargets(void) { auto sub_output_path = os_portable_append_dir(_output_path, iname); - if (_backend == backend_selector::COSA) { - auto target = VlgSglTgtGen_Cosa( + if (_backend == backend_selector::PONO) { + auto target = VlgSglTgtGen_Pono( sub_output_path, instr_ptr, // instruction - _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + _ila_ptr, _refinement, vlg_info_ptr, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INSTRUCTIONS, _advanced_param_ptr); target.ConstructWrapper(); - target.ExportAll("wrapper.v", "ila.v", "run.sh", "problem.txt", - "absmem.v"); + target.ExportAll("wrapper.v", "ila.v", "run.sh", "problem.txt"); target.do_not_instantiate(); } else if (_backend == backend_selector::JASPERGOLD) { auto target = VlgSglTgtGen_Jasper( sub_output_path, instr_ptr, // instruction - _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + _ila_ptr, _refinement, vlg_info_ptr, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INSTRUCTIONS, _advanced_param_ptr); target.ConstructWrapper(); - target.ExportAll("wrapper.v", "ila.v", "run.sh", "do.tcl", "absmem.v"); + target.ExportAll("wrapper.v", "ila.v", "run.sh", "do.tcl"); target.do_not_instantiate(); - } else if (_backend == backend_selector::RELCHC) { + } +#if 0 + else if (_backend == backend_selector::RELCHC) { // will actually fail : not supported for using relchc for invariant // targets auto target = VlgSglTgtGen_Relchc( sub_output_path, instr_ptr, // instruction _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INSTRUCTIONS, _advanced_param_ptr); target.ConstructWrapper(); @@ -327,7 +250,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { sub_output_path, instr_ptr, // instruction _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INSTRUCTIONS, _advanced_param_ptr, _chc_target_t::GENERAL_PROPERTY); @@ -346,6 +269,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { "absmem.v"); target.do_not_instantiate(); } // end case backend +#endif runnable_script_name.push_back( os_portable_append_dir(sub_output_path, "run.sh")); } // end for instrs @@ -364,7 +288,7 @@ bool VlgVerifTgtGen::bad_state_return(void) { } // bad_state_return -#ifdef INVSYN_INTERFACE +#if 0 std::shared_ptr VlgVerifTgtGen::GenerateInvSynTargets(synthesis_backend_selector s_backend) { @@ -375,7 +299,7 @@ VlgVerifTgtGen::GenerateInvSynTargets(synthesis_backend_selector s_backend) { delete vlg_info_ptr; vlg_info_ptr = new VerilogInfo(_vlg_impl_include_path, _vlg_impl_srcs, - _vlg_mod_inst_name, _vlg_impl_top_name); + "RTL", _vlg_impl_top_name); if (vlg_info_ptr == NULL or vlg_info_ptr->in_bad_state()) { ILA_ERROR << "Unable to generate targets. Verilog parser failed."; return nullptr; // @@ -390,7 +314,7 @@ VlgVerifTgtGen::GenerateInvSynTargets(synthesis_backend_selector s_backend) { os_portable_append_dir(_output_path, "inv-syn/"), NULL, // invariant _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, tmp_vtg_config, _backend, s_backend, target_type_t::INV_SYN_DESIGN_ONLY, _advanced_param_ptr, true, _chc_target_t::CEX); @@ -414,7 +338,7 @@ VlgVerifTgtGen::GenerateInvSynEnhanceTargets(const InvariantInCnf& cnf) { delete vlg_info_ptr; vlg_info_ptr = new VerilogInfo(_vlg_impl_include_path, _vlg_impl_srcs, - _vlg_mod_inst_name, _vlg_impl_top_name); + "RTL", _vlg_impl_top_name); if (vlg_info_ptr == NULL or vlg_info_ptr->in_bad_state()) { ILA_ERROR << "Unable to generate targets. Verilog parser failed."; return nullptr; // @@ -426,19 +350,6 @@ VlgVerifTgtGen::GenerateInvSynEnhanceTargets(const InvariantInCnf& cnf) { tmp_vtg_config.YosysSmtFlattenDatatype = true; tmp_vtg_config.CosaDotReferenceNotify = vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_PANIC; -#if 0 - // currently we do this on the outer level - // here we remove the last one, because it is the one we want to enhance - InvariantObject * inv_obj_backup = NULL; - if (_advanced_param_ptr->_inv_obj_ptr) { - InvariantObject * reduced_inv = new InvariantObject(*( _advanced_param_ptr->_inv_obj_ptr)); // make a copy - ILA_NOT_NULL(reduced_inv); - if (reduced_inv->NumInvariant() > 0) - reduced_inv->RemoveInvByIdx(reduced_inv->NumInvariant()-1); - inv_obj_backup = _advanced_param_ptr->_inv_obj_ptr; - _advanced_param_ptr->_inv_obj_ptr = reduced_inv; - } -#endif // TODO: you may need to change a bit of _advanced_param_ptr's inv // and maybe the assume inv part @@ -446,7 +357,7 @@ VlgVerifTgtGen::GenerateInvSynEnhanceTargets(const InvariantInCnf& cnf) { os_portable_append_dir(_output_path, "inv-enhance/"), NULL, // invariant _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, tmp_vtg_config, _backend, VlgVerifTgtGenBase::synthesis_backend_selector::GRAIN, target_type_t::INV_SYN_DESIGN_ONLY, _advanced_param_ptr, true, @@ -458,12 +369,7 @@ VlgVerifTgtGen::GenerateInvSynEnhanceTargets(const InvariantInCnf& cnf) { runnable_script_name.clear(); runnable_script_name.push_back(os_portable_append_dir( os_portable_append_dir(_output_path, "inv-enhance/"), "run.sh")); -#if 0 - if (inv_obj_backup) { // recover the invariant - delete (_advanced_param_ptr->_inv_obj_ptr); - _advanced_param_ptr->_inv_obj_ptr = inv_obj_backup; - } // recover the invariant -#endif + return target.GetDesignSmtInfo(); } // GenerateInvSynEnhanceTargets @@ -477,7 +383,7 @@ void VlgVerifTgtGen::GenerateInvSynTargetsAbc(bool useGla, bool useCorr, delete vlg_info_ptr; vlg_info_ptr = new VerilogInfo(_vlg_impl_include_path, _vlg_impl_srcs, - _vlg_mod_inst_name, _vlg_impl_top_name); + "RTL", _vlg_impl_top_name); if (vlg_info_ptr == NULL or vlg_info_ptr->in_bad_state()) { ILA_ERROR << "Unable to generate targets. Verilog parser failed."; return; // @@ -491,7 +397,7 @@ void VlgVerifTgtGen::GenerateInvSynTargetsAbc(bool useGla, bool useCorr, os_portable_append_dir(_output_path, "inv-syn-abc/"), NULL, // invariant _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - _vlg_mod_inst_name, _ila_mod_inst_name, "wrapper", _vlg_impl_srcs, + "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, tmp_vtg_config, _backend, synthesis_backend_selector::ABC, target_type_t::INV_SYN_DESIGN_ONLY, _advanced_param_ptr, true, _chc_target_t::CEX, useGla, useCorr, useAiger); diff --git a/src/vtarget-out/vtarget_gen_jasper.cc b/src/vtarget-out/vtarget_gen_jasper.cc index 5d394c7c4..4b21b946f 100644 --- a/src/vtarget-out/vtarget_gen_jasper.cc +++ b/src/vtarget-out/vtarget_gen_jasper.cc @@ -19,18 +19,16 @@ VlgSglTgtGen_Jasper::VlgSglTgtGen_Jasper( output_path, // will be a sub directory of the output_path of its parent const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, const VerilogGenerator::VlgGenConfig& config, - nlohmann::json& _rf_vmap, nlohmann::json& _rf_cond, - VlgTgtSupplementaryInfo& _supplementary_info, VerilogInfo* _vlg_info_ptr, - const std::string& vlg_mod_inst_name, const std::string& ila_mod_inst_name, + const InstrLvlAbsPtr& ila_ptr, + const rfmap::VerilogRefinementMap & refinement, + VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, const vtg_config_t& vtg_config, backend_selector backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, config, _rf_vmap, _rf_cond, - _supplementary_info, _vlg_info_ptr, vlg_mod_inst_name, - ila_mod_inst_name, wrapper_name, implementation_srcs, + : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, refinement, + _vlg_info_ptr, wrapper_name, implementation_srcs, implementation_include_path, vtg_config, backend, target_tp, adv_ptr) {} @@ -55,6 +53,23 @@ void VlgSglTgtGen_Jasper::add_reg_cassign_assumption( "(~(" + cond + ") || ((" + varname + ") == (" + expression + ")))", dspt); } + +/// Add SMT-lib2 assumption +void VlgSglTgtGen_Jasper::add_a_direct_smt_assumption(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) { + ILA_CHECK(false) << "SMT assumption should not be generated for JasperGold"; +} + +/// Add SMT-lib2 assertion +void VlgSglTgtGen_Jasper::add_a_direct_smt_assertion(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) { + ILA_CHECK(false) << "SMT assertions should not be generated for JasperGold"; +} + /// Add an assumption void VlgSglTgtGen_Jasper::add_an_assumption(const std::string& aspt, const std::string& dspt) { @@ -77,15 +92,6 @@ void VlgSglTgtGen_Jasper::add_a_direct_assertion(const std::string& asst, assertions.push_back(std::make_pair(asst, dspt)); } -void VlgSglTgtGen_Jasper::add_addition_clock_info( - const std::string& clock_expr) { - additional_clock_expr.push_back(clock_expr); -} - -void VlgSglTgtGen_Jasper::add_addition_reset_info( - const std::string& reset_expr) { - additional_reset_expr.push_back(reset_expr); -} /// export the script to run the verification void VlgSglTgtGen_Jasper::Export_script(const std::string& script_name) { @@ -120,22 +126,11 @@ void VlgSglTgtGen_Jasper::Export_problem(const std::string& extra_name) { if (top_file_name != "") fout << " \\\n " << top_file_name; - if (abs_mem_name != "") - fout << " \\\n " << abs_mem_name; - fout << "\n\n"; fout << "elaborate -top " << top_mod_name << std::endl; - if (additional_clock_expr.empty()) - fout << "clock clk" << std::endl; - else - ILA_ERROR << "Not supporting multiple clock. Future work!"; - - if (additional_reset_expr.empty()) - fout << "reset rst" << std::endl; - else - fout << "reset -expression " << Join(additional_reset_expr, " ") - << std::endl; + fout << "clock clk" << std::endl; + fout << "reset rst" << std::endl; unsigned No = 0; for (auto&& asmpt_dspt_pair : assumptions) @@ -147,22 +142,8 @@ void VlgSglTgtGen_Jasper::Export_problem(const std::string& extra_name) { fout << "assert -name " << asst_dspt_pair.second + std::to_string(No++) << " {" << asst_dspt_pair.first << "}" << std::endl; -} // -/// export the memory abstraction (implementation) -/// Yes, this is also implementation specific, (jasper may use a different one) -void VlgSglTgtGen_Jasper::Export_mem(const std::string& mem_name) { - // TODO; - if (!VlgAbsMem::hasAbsMem()) - return; +} - abs_mem_name = mem_name; - - auto outfn = os_portable_append_dir(_output_path, mem_name); - std::ofstream fout(outfn); // will not append - - VlgAbsMem::OutputMemFile(fout, - _vtg_config.VerificationSettingAvoidIssueStage); -} /// For jasper, this means do nothing, for yosys, you need to add (*keep*) void VlgSglTgtGen_Jasper::Export_modify_verilog() { // COPY Files? diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc new file mode 100644 index 000000000..60ffe8dd9 --- /dev/null +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -0,0 +1,295 @@ +/// \file Source of generating Pono accepted problem, vlg, mem, script +// --- Hongce Zhang + +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace ilang { + +#define VLG_TRUE "`true" +#define VLG_FALSE "`false" + + +// should not be used +static std::string yosysGenerateBtor = R"***( +hierarchy -check +proc +chformal -assume -early; +memory -nomap; +flatten +sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% +)***"; + + +VlgSglTgtGen_Pono::VlgSglTgtGen_Pono( + const std::string& + output_path, // will be a sub directory of the output_path of its parent + const InstrPtr& instr_ptr, // which could be an empty pointer, and it will + // be used to verify invariants + const InstrLvlAbsPtr& ila_ptr, + const rfmap::VerilogRefinementMap & refinement, + VerilogInfo* _vlg_info_ptr, + const std::string& wrapper_name, + const std::vector& implementation_srcs, + const std::vector& implementation_include_path, + const vtg_config_t& vtg_config, backend_selector vbackend, + const target_type_t& target_tp, advanced_parameters_t* adv_ptr) + : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, refinement, + _vlg_info_ptr, wrapper_name, implementation_srcs, + implementation_include_path, vtg_config, vbackend, target_tp, + adv_ptr) {} + + +/// Add an assumption +void VlgSglTgtGen_Pono::add_a_direct_assumption(const std::string& aspt, + const std::string& dspt) { + _problems.assumptions[dspt].exprs.push_back(aspt); +} +/// Add an assertion +void VlgSglTgtGen_Pono::add_a_direct_assertion(const std::string& asst, + const std::string& dspt) { + _problems.assertions[dspt].exprs.push_back(asst); +} + +/// export the script to run the verification +void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { + + auto fname = os_portable_append_dir(_output_path, script_name); + std::ofstream fout(fname); + if (!fout.is_open()) { + ILA_ERROR << "Error writing to file:" << fname; + return; + } + fout << "#!/bin/bash" << std::endl; + + { + std::string yosys = "yosys"; + + if (!_vtg_config.YosysPath.empty()) + yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); + + // execute it + fout << yosys << " -s" << ys_script_name << " > __yosys_exec_result.txt\n"; + } + + + std::string pono = "pono"; + std::string options; + + if (!_vtg_config.PonoVcdOutputName.empty()) + options += " --vcd " + _vtg_config.PonoVcdOutputName; + options += " " + _vtg_config.PonoOtherOptions; + + // no need, copy is good enough + // if(vlg_include_files_path.size() != 0) + // options += " -I./"; + + if (!_vtg_config.PonoPath.empty()) { + pono = os_portable_append_dir(_vtg_config.PonoPath, pono); + } + + fout << pono << "problem.btor2" << std::endl; + +} + + +/// Add SMT-lib2 assumption +void VlgSglTgtGen_Pono::add_a_direct_smt_assumption(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) { + size_t idx = _problems.smt_assumptions.size(); + _problems.smt_assumptions.push_back( + "(define-fun assumption."+std::to_string(idx)+" " + arg + " " + ret + " " + body+")"); + +} + +/// Add SMT-lib2 assertion +void VlgSglTgtGen_Pono::add_a_direct_smt_assertion(const std::string& arg, + const std::string& ret, + const std::string& body, + const std::string& dspt) { + size_t idx = _problems.smt_assertions.size(); + _problems.smt_assertions.push_back( + "(define-fun assertion."+std::to_string(idx)+" " + arg + " " + ret + " " + body+")"); +} + +/// export the yosys script +void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { + if (_problems.assertions.empty()) { + ILA_ERROR << "Nothing to prove, no assertions inserted!"; + return; + } + + ys_script_name = yosys_script_name; + + std::string ys_script_name_path = os_portable_append_dir(_output_path, ys_script_name); + { // export to ys_script_name + std::ofstream ys_script_fout(ys_script_name_path); + + std::string write_btor_options; + write_btor_options += _vtg_config.BtorAddCommentsInOutputs ? " -v" : ""; + write_btor_options += _vtg_config.BtorSingleProperty ? " -s" : ""; + + ys_script_fout << "read_verilog -sv " + << os_portable_append_dir(_output_path, top_file_name) + << std::endl; + ys_script_fout << "prep -top " << top_mod_name << std::endl; + + ys_script_fout << + ReplaceAll( + ReplaceAll( + ReplaceAll(yosysGenerateBtor, + "%rstlen%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%cycle%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%module%", top_mod_name); + + // this is for pono, I don't know why it is unhappy, but we need fix this + // in the long run + ys_script_fout << "setundef -undriven -zero\n"; + ys_script_fout << "write_btor " << write_btor_options << " problem.btor2" << std::endl; + } // finish writing + + + auto smt_property_fname = + os_portable_append_dir(_output_path, "property.smt2"); + { + std::ofstream smt_fout(smt_property_fname); + for(const auto & prop : _problems.smt_assumptions) + smt_fout << prop << std::endl; + + for(const auto & prop : _problems.smt_assertions) + smt_fout << prop << std::endl; + } +} // only for Pono + + + +// PreExportProcess is about how to add assumption/assertions +void VlgSglTgtGen_Pono::PreExportProcess() { + + std::string all_assert_wire_content; + std::string all_assume_wire_content; + + // you need to add assumptions as well + for (auto&& pbname_prob_pair : _problems.assumptions) { + const auto& prbname = pbname_prob_pair.first; + const auto& prob = pbname_prob_pair.second; + ILA_DLOG("VlgSglTgtGen_Pono.PreExportProcess") + << "Adding assumption:" << prbname; + + for (auto&& p : prob.exprs) { + if (all_assume_wire_content.empty()) + all_assume_wire_content = "(" + p + ")"; + else + all_assume_wire_content += "&& (" + p + ")"; + } // for prob.exprs + } // for _problems.assumption + + // this is to check given invariants + for (auto&& pbname_prob_pair : _problems.assertions) { + // const auto& prbname = pbname_prob_pair.first; + const auto& prob = pbname_prob_pair.second; + + // ILA_CHECK(prbname == "cex_nonreachable_assert") + // << "BUG: assertion can only be cex reachability queries."; + // sanity check, should only be invariant's related asserts + + for (auto&& p : prob.exprs) { + // there should be only one expression (for cex target) + // ILA_CHECK(all_assert_wire_content.empty()); + if (all_assert_wire_content.empty()) + all_assert_wire_content = p; + else + all_assert_wire_content += " && " + p; + } // for expr + } // for problem + // add assert wire (though no use : make sure will not optimized away) + ILA_CHECK(!all_assert_wire_content.empty()) << "no property to check!"; + + vlg_wrapper.add_wire("__all_assert_wire__", 1, true); + vlg_wrapper.add_output("__all_assert_wire__", 1); + vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); + + if (!all_assume_wire_content.empty()) { + vlg_wrapper.add_wire("__all_assume_wire__", 1, true); + vlg_wrapper.add_output("__all_assume_wire__", 1); + vlg_wrapper.add_assign_stmt("__all_assume_wire__", all_assume_wire_content); + } + + vlg_wrapper.add_stmt( + "assert property ( __all_assert_wire__ ); // the only assertion \n"); + if (!all_assume_wire_content.empty()) + vlg_wrapper.add_stmt( + "assume property ( __all_assume_wire__ ); // the only assumption \n"); +} // PreExportProcess + +/// For jasper, this means do nothing, for yosys, you need to add (*keep*) +void VlgSglTgtGen_Pono::Export_modify_verilog() { + // collect all locations: filename -> lineno + // open, read, count and write + // if it is a port name, we will ask user to specify its upper level + // signal name + VerilogModifier vlg_mod(vlg_info_ptr, + static_cast( + _vtg_config.PortDeclStyle), + _vtg_config.PonoAddKeep, + refinement_map.width_info); + + for (auto&& refered_vlg_item : refinement_map.var_replacement) { + auto old_name = refered_vlg_item.second.get_orig_name(); + auto new_name = refered_vlg_item.second.get_new_name(); + + if(StrStartsWith(new_name, "__ILA_")) + continue; + + auto idx = old_name.find("["); + auto removed_range_name = old_name.substr(0, idx); + vlg_mod.RecordKeepSignalName(removed_range_name); + // auto sig = // no use, this is too late, vlg_wrapper already exported + vlg_mod.RecordConnectSigName(removed_range_name, + refered_vlg_item.second.range_o); + // vlg_wrapper.add_output(sig.first, sig.second); + } + vlg_mod.FinishRecording(); + + // auto tmp_fn = os_portable_append_dir(_output_path, tmp_design_file); + auto tmp_fn = os_portable_append_dir(_output_path, top_file_name); + // now let's do the job + for (auto&& fn : vlg_design_files) { + std::ifstream fin(fn); + std::ofstream fout(tmp_fn, std::ios_base::app); // append to a temp file + if (!fin.is_open()) { + ILA_ERROR << "Cannot read file:" << fn; + continue; + } + if (!fout.is_open()) { + ILA_ERROR << "Cannot open file for write:" << tmp_fn; + continue; + } + vlg_mod.ReadModifyWrite(fn, fin, fout); + } // for (auto && fn : vlg_design_files) + + // handles the includes + // .. (copy all the verilog file in the folder), this has to be os independent + if (vlg_include_files_path.size() != 0) { + // copy the files and specify the -I commandline to the run.sh + for (auto&& include_path : vlg_include_files_path) + os_portable_copy_dir(include_path, _output_path); + } + +} // Export_modify_verilog + +}; // namespace ilang diff --git a/src/vtarget-out/vtarget_gen_relchc.cc b/src/vtarget-out/vtarget_gen_relchc.cc deleted file mode 100644 index f7fa224ba..000000000 --- a/src/vtarget-out/vtarget_gen_relchc.cc +++ /dev/null @@ -1,393 +0,0 @@ -/// \file Source of generating rel chc synthesis target -/// the inv-syn related horn clasue generation is located in inv-syn/rel_chc.cc -// --- Hongce Zhang - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ilang { - -#define VLG_TRUE "`true" -#define VLG_FALSE "`false" - -/// template for generating relchc script wo arrays -static std::string relchcGenerateSmtScript_wo_Array = R"***( -hierarchy -check -proc -opt -opt_expr -mux_undef -opt -opt -flatten \%dutmodulename% -%setundef -undriven -init -expose% -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -memory -nordff -proc -opt;; -)***"; -// you may want to flatten just -/// template for generating relchc script -static std::string relchcGenerateSmtScript_w_Array = R"***( -hierarchy -check -proc -opt -opt_expr -mux_undef -opt -opt -flatten \%dutmodulename% -%setundef -undriven -init -expose% -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -memory_dff -wr_only -memory_collect; -memory_unpack -splitnets -driver -opt;; -memory_collect; -pmuxtree -proc -opt;; -)***"; - - -VlgSglTgtGen_Relchc::VlgSglTgtGen_Relchc( - const std::string& - output_path, // will be a sub directory of the output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, const VerilogGenerator::VlgGenConfig& config, - nlohmann::json& _rf_vmap, nlohmann::json& _rf_cond, VlgTgtSupplementaryInfo & _sup_info, - VerilogInfo* _vlg_info_ptr, const std::string& vlg_mod_inst_name, - const std::string& ila_mod_inst_name, const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector backend, - const target_type_t& target_tp, - advanced_parameters_t* adv_ptr ) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, config, _rf_vmap, _rf_cond, _sup_info, - _vlg_info_ptr, vlg_mod_inst_name, ila_mod_inst_name, - wrapper_name, implementation_srcs, - implementation_include_path, vtg_config, backend, - target_tp, adv_ptr) { - - ILA_ASSERT(! _vtg_config.YosysSmtArrayForRegFile) - << "Future work to support array in synthesis"; - - ILA_ASSERT( - target_tp == target_type_t::INSTRUCTIONS ) - << "Only support target type : INSTRUCTIONS, but get: " << target_tp; - - ILA_ASSERT(! vtg_config.YosysSmtFlattenHierarchy) - << "Monolithic synthesis requires not to flatten hierarchy"; - - ILA_ASSERT(! vtg_config.YosysSmtFlattenDatatype) - << "BUG: not implemented, future work."; - - } - - - -/// Add an assumption -void VlgSglTgtGen_Relchc::add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) { - _problems.assumptions[dspt].exprs.push_back(aspt); -} -/// Add an assertion -void VlgSglTgtGen_Relchc::add_a_direct_assertion(const std::string& asst, - const std::string& dspt) { - _problems.assertions[dspt].exprs.push_back(asst); -} - -/// Pre export work : add assume and asssert to the top level -/// collect the type of assumptions and assertions -/// Assertions: variable_map_assert (no invariant_assert --- not for invariant target) -/// Assumptions: -/// 1. global: noreset, funcmap, absmem, additonal_mapping_control_assume -/// 2. only at starting state: -/// variable_map_assume, issue_decode, issue_valid, ... -/// Question: invariant assume? where to put it? Depends on ? - -void VlgSglTgtGen_Relchc::PreExportProcess() { -/* - std::string global_assume = "`true"; - std::string start_assume = "`true"; - - for(auto&& dspt_exprs_pair : _problems.assumptions) { - const auto & dspt = dspt_exprs_pair.first; - const auto & expr = dspt_exprs_pair.second; - for (auto&& p: expr.exprs) - vlg_wrapper.add_stmt( - "assume property ("+p+"); // " + dspt - ); - } - - //std::string assmpt = "(" + Join(_problems.assumptions, ") & (") + ")"; - std::string all_assert_wire_content = "`true"; -*/ - - if(target_type == target_type_t::INSTRUCTIONS) { - // this is to synthesize invariants - for (auto & pbname_prob_pair : _problems.assumptions) { - const auto& prbname = pbname_prob_pair.first; - auto& prob = pbname_prob_pair.second; // will be modified !!! - - if (prbname == "invariant_assume") { // add to submodule ? why? - for (auto & p : prob.exprs) { - // p does not contain "top." - - auto assumption_wire_name = - vlg_wrapper.sanitizeName(prbname) + "_sub_" + new_mapping_id(); - - vlg_mod_inv_vec.push_back( - "wire " + assumption_wire_name + - " = " + p +";"); - - p = assumption_wire_name; - } - } // dspt == invariant_assume - } // for assumptions - } -#if 0 // Target Type Invariant, we will not handle - else if(target_type == target_type_t::INVARIANTS) { - // this is to check given invariants - for (auto&& pbname_prob_pair : _problems.assertions) { - const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - - ILA_ASSERT(prbname == "invariant_assert"); - // sanity check, should only be invariant's related asserts - - for (auto&& p: prob.exprs) { - vlg_wrapper.add_stmt( - "assert property ("+p+"); //" + prbname + "\n" - ); - all_assert_wire_content += "&& ( " + p + " ) "; - } // for expr - } // for problem - } // target_type == target_type_t::INVARIANTS - - vlg_wrapper.add_wire("__all_assert_wire__", 1, true); - vlg_wrapper.add_output("__all_assert_wire__",1); - vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); -#endif // Target Type Invariant, we will not handle - -} // PreExportProcess - -/// export the script to run the verification : -/// like "yosys gemsmt.ys" -void VlgSglTgtGen_Relchc::Export_script(const std::string& script_name) { - relchc_run_script_name = script_name; - - auto fname = os_portable_append_dir(_output_path, script_name); - std::ofstream fout(fname); - if (!fout.is_open()) { - ILA_ERROR << "Error writing to file:" << fname; - return; - } - fout << "#!/bin/bash" << std::endl; - //fout << "trap \"trap - SIGTERM && kill -- -$$\" SIGINT SIGTERM"< lineno - // open, read, count and write - // if it is a port name, we will ask user to specify its upper level - // signal name - VerilogModifier vlg_mod(vlg_info_ptr, - static_cast( - _vtg_config.PortDeclStyle), - _vtg_config.PonoAddKeep, - supplementary_info.width_info); - - // add mod stmt (wire something ... like that) - for (auto && stmt : vlg_mod_inv_vec) - vlg_mod.RecordAdditionalVlgModuleStmt(stmt, _vlg_mod_inst_name); - - for (auto&& refered_vlg_item : _all_referred_vlg_names) { - auto idx = refered_vlg_item.first.find("["); - auto removed_range_name = refered_vlg_item.first.substr(0, idx); - vlg_mod.RecordKeepSignalName(removed_range_name); - // auto sig = // no use, this is too late, vlg_wrapper already exported - vlg_mod.RecordConnectSigName(removed_range_name, - refered_vlg_item.second.range); - // vlg_wrapper.add_output(sig.first, sig.second); - } - vlg_mod.FinishRecording(); - - - //auto tmp_fn = os_portable_append_dir(_output_path, tmp_design_file); - auto tmp_fn = os_portable_append_dir(_output_path, top_file_name); - // now let's do the job - for (auto&& fn : vlg_design_files) { - std::ifstream fin(fn); - std::ofstream fout(tmp_fn, std::ios_base::app); // append to a temp file - if (!fin.is_open()) { - ILA_ERROR << "Cannot read file:" << fn; - continue; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot open file for write:" << tmp_fn; - continue; - } - vlg_mod.ReadModifyWrite(fn, fin, fout); - } // for (auto && fn : vlg_design_files) - - // handles the includes - // .. (copy all the verilog file in the folder), this has to be os independent - if (vlg_include_files_path.size() != 0) { - // copy the files and specify the -I commandline to the run.sh - for (auto&& include_path : vlg_include_files_path) - os_portable_copy_dir(include_path, _output_path); - } - -} // Export_modify_verilog - - -/// export the memory abstraction (implementation) -/// Yes, this is also implementation specific, (jasper may use a different one) -void VlgSglTgtGen_Relchc::Export_mem(const std::string& mem_name) { - // we will ignore the mem_name - - auto outfn = os_portable_append_dir(_output_path, top_file_name); - std::ofstream fout(outfn, std::ios_base::app); // append - - VlgAbsMem::OutputMemFile(fout, _vtg_config.VerificationSettingAvoidIssueStage); -} - - -// export the gensmt.ys -void VlgSglTgtGen_Relchc::Export_problem(const std::string& extra_name) { - // used by export script! - relchc_prob_fname = extra_name; - - ILA_CHECK(!_vtg_config.ForceInstCheckReset) << - "If start from init, please use Yosys target."; - // generate tpl - - // first generate a temporary smt - // and extract from it the necessary info - auto smt_info = dual_inv_gen_smt("__design_smt.smt2","__gen_smt_script.ys"); - auto final_smt_name = - os_portable_append_dir(_output_path, - os_portable_remove_file_name_extension(top_file_name) + ".smt2" ); - - dual_inv_tpl(final_smt_name, smt_info); - dual_inv_problem(extra_name); - -} // Export_problem - - -void VlgSglTgtGen_Relchc::ExportAll(const std::string& wrapper_name, - const std::string& ila_vlg_name, - const std::string& script_name, - const std::string& extra_name, - const std::string& mem_name) { - - PreExportProcess(); - if (os_portable_mkdir(_output_path) == false) - ILA_WARN << "Cannot create output directory:" << _output_path; - - // you don't need to worry about the path and names - Export_wrapper(wrapper_name); - if (target_type == target_type_t::INSTRUCTIONS) - Export_ila_vlg(ila_vlg_name); // this has to be after Export_wrapper - - // for Jasper, this will be put to multiple files - // for CoSA & Yosys, this will be put after the wrapper file (wrapper.v) - Export_modify_verilog(); // this must be after Export_wrapper - Export_mem(mem_name); - - // you need to create the map function -- - Export_problem(extra_name); // the gensmt.ys - - Export_script(script_name); -} - - -/// generate the wrapper's smt first -std::string VlgSglTgtGen_Relchc::dual_inv_gen_smt( - const std::string & smt_name, - const std::string & ys_script_name) { - - auto ys_full_name = - os_portable_append_dir(_output_path, ys_script_name); - { // export to ys_full_name - std::ofstream ys_script_fout( ys_full_name ); - - std::string write_smt2_options = " -mem -bv -stdt "; // future work : -stbv, or nothing - - ys_script_fout << "read_verilog -sv " - << os_portable_append_dir( _output_path , top_file_name ) << std::endl; - ys_script_fout << "prep -top " << top_mod_name << std::endl; - ys_script_fout << - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - relchcGenerateSmtScript_wo_Array, - "%setundef -undriven -init -expose%", _vtg_config.YosysUndrivenNetAsInput ? "setundef -undriven -init -expose" : ""), - "%module%", top_mod_name), - "%rstlen%", "1" // this is because, the reset analysis is applied on the DUT not the wrapper - /*std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)*/), - "%cycle%", "1" // this is because, the reset analysis is applied on the DUT not the wrapper - /*std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles) */), - "%dutmodulename%", vlg_info_ptr->get_top_module_name()) - ; - ys_script_fout << "write_smt2"< cmd; - cmd.push_back(yosys); cmd.push_back("-s"); cmd.push_back(ys_full_name); - - std::string logfilename = - os_portable_append_dir(_output_path, "yosys_output.log"); - - auto res = os_portable_execute_shell( cmd , logfilename); // this does not redirect - ILA_ERROR_IF( res.failure != res.NONE ) - << "Executing Yosys failed!"; - ILA_ERROR_IF( res.failure == res.NONE && res.ret != 0) - << "Yosys returns error code:" << res.ret; - - { // now read in the file - std::stringstream ibuf; - auto smt_in_fn = os_portable_append_dir(_output_path, smt_name); - std::ifstream smtfin( smt_in_fn ); - - if (! smtfin.is_open()) { - ILA_ERROR << "Cannot read from: " << smt_in_fn; - return ""; - } - ibuf << smtfin.rdbuf(); - return ibuf.str(); - } // finish file readin -} // dual_inv_gen_smt - - -}; // namespace ilang diff --git a/src/vtarget-out/vtarget_gen_yosys.cc b/src/vtarget-out/vtarget_gen_yosys.cc deleted file mode 100644 index badaa7e85..000000000 --- a/src/vtarget-out/vtarget_gen_yosys.cc +++ /dev/null @@ -1,1030 +0,0 @@ -/// \file Source of generating Yosys accepted problem, vlg, mem, script -/// the inv-syn related HC generation is located in inv_syn.cc -// --- Hongce Zhang - -#include - -#include -#include -#include - -#include -#include -#include -#include - -namespace ilang { - -#define VLG_TRUE "`true" -#define VLG_FALSE "`false" - -// initialize templates -static std::string chcGenerateSmtScript_wo_Array = R"***( -hierarchy -check -proc -opt -opt_expr -mux_undef -opt -opt -%flatten% -%setundef -undriven -init -expose% -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -memory -nordff -proc -opt;; -)***"; - -// should not be used -static std::string chcGenerateSmtScript_w_Array = R"***( -hierarchy -check -proc -opt -opt_expr -mux_undef -opt -opt -%flatten% -%setundef -undriven -init -expose% -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -memory_dff -wr_only -memory_collect; -memory_unpack -splitnets -driver -opt;; -memory_collect; -pmuxtree -proc -opt;; -)***"; - -static std::string chc_tmpl_datatypes = R"***( -;---------------------------------------- -; Single Inductive Invariant Synthesis -; Generated from ILAng -;---------------------------------------- -%(set-option :fp.engine spacer)% - -%% - -(declare-rel INV (|%1%_s|)) -(declare-rel fail ()) - -(declare-var |__S__| |%1%_s|) -(declare-var |__S'__| |%1%_s|) - -; -------------------------------- -; note if you want it a bit faster -; if can try removing wrapper-u in rule 1 -; or remove the assume previous invariants -; -------------------------------- - -; init => inv -(rule (=> - (and - (|%1%_i| |__S__|) - (|%1%_u| |__S__|) - (|%1%_h| |__S__|) - ) - (INV |__S__|))) - -; inv /\ T => inv -(rule (=> (and - (INV |__S__|) - (|%1%_u| |__S__|) - (|%1%_u| |__S'__|) - (|%1%_h| |__S__|) - (|%1%_h| |__S'__|) - (|%1%_t| |__S__| |__S'__|)) - (INV |__S'__|))) - -; inv /\ ~p => \bot -(rule (=> (and - (INV |__S__|) - (|%1%_u| |__S__|) - (|%1%_h| |__S__|) - (not (|%1%_a| |__S__|))) - fail)) - -; (query fail :print-certificate true) - -)***"; - -static std::string chc_tmpl_wo_datatypes = R"***( -;---------------------------------------- -; Single Inductive Invariant Synthesis -; Generated from ILAng -;---------------------------------------- -%(set-option :fp.engine spacer)% - -%% - -(declare-rel INV %WrapperDataType%) -(declare-rel fail ()) - - -%State% -%StatePrime% -;(declare-var |__S__state| Type) -;(declare-var |__S'__state| Type) - -; same for flattened - -; init => inv -(rule (=> - (and - (|%WrapperName%_i| %Ss%) - (|%WrapperName%_u| %Ss%) - (|%WrapperName%_h| %Ss%) - ) - (INV %Ss%))) - -; inv /\ T => inv -(rule (=> (and - (INV %Ss%) - (|%WrapperName%_u| %Ss%) - (|%WrapperName%_u| %Sps%) - (|%WrapperName%_h| %Ss%) - (|%WrapperName%_h| %Sps%) - (|%WrapperName%_t| %Ss% %Sps%)) - (INV %Sps%))) - -; inv /\ ~p => \bot -(rule (=> (and - (INV %Ss%) - (|%WrapperName%_u| %Ss%) - (|%WrapperName%_h| %Ss%) - (not (|%WrapperName%_a| %Ss%))) - fail)) - -; (query fail :print-certificate true) - -)***"; - -// yosys template -static std::string abcGenerateAigerWInit_wo_Array = R"***( -read_verilog -formal %topfile% -prep -top %module% -sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% -miter -assert %module% -flatten -%setundef -undriven -init -expose% -memory -nordff -opt_clean -techmap -abc -fast -g AND -write_aiger -zinit -map %mapname% %aigname% -write_blif %blifname% -)***"; - -static std::string abcAigCmdNoGLA = R"***( - &read %aigname% - &put - fold - pdr {-v -d} - {inv_min} - {inv_print -v} -)***"; - -static std::string abcAigCmdGLA = R"***( - &read %aigname% - &gla -T %glatime% -F %glaframe% -v - &gla_derive - &put - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - dc2 -v - {scorr} - dc2 -v - dc2 -v - dc2 -v - dc2 -v - {lcorr} - dc2 -v - dc2 -v - dc2 -v - dc2 -v - pdr {-v -d} - {inv_min} - {inv_print -v} -)***"; - -#define IMPLY(a, b) (!(a) || (b)) - -VlgSglTgtGen_Yosys::~VlgSglTgtGen_Yosys() {} - -VlgSglTgtGen_Yosys::VlgSglTgtGen_Yosys( - const std::string& - output_path, // will be a sub directory of the output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, const VerilogGenerator::VlgGenConfig& config, - nlohmann::json& _rf_vmap, nlohmann::json& _rf_cond, - VlgTgtSupplementaryInfo& _sup_info, VerilogInfo* _vlg_info_ptr, - const std::string& vlg_mod_inst_name, const std::string& ila_mod_inst_name, - const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector vbackend, - const target_type_t& target_tp, advanced_parameters_t* adv_ptr, - _chc_target_t _chc_target) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, config, _rf_vmap, _rf_cond, - _sup_info, _vlg_info_ptr, vlg_mod_inst_name, - ila_mod_inst_name, wrapper_name, implementation_srcs, - implementation_include_path, vtg_config, vbackend, target_tp, - adv_ptr), - - s_backend(synthesis_backend_selector(vbackend ^ backend_selector::YOSYS)), - chc_target(_chc_target) { - - ILA_CHECK(chc_target == _chc_target_t::GENERAL_PROPERTY); - - ILA_CHECK(target_tp == target_type_t::INVARIANTS || - target_tp == target_type_t::INSTRUCTIONS) - << "Unknown target type: " << target_tp; - - ILA_CHECK((vbackend & backend_selector::YOSYS) == backend_selector::YOSYS) - << "Must use Yosys as vbackend"; - - ILA_CHECK(s_backend == synthesis_backend_selector::ABC || - s_backend == synthesis_backend_selector::Z3 || - s_backend == synthesis_backend_selector::GRAIN || - s_backend == synthesis_backend_selector::ELDERICA || - s_backend == synthesis_backend_selector::NOSYN); - - ILA_CHECK(IMPLY(s_backend == synthesis_backend_selector::GRAIN, - vtg_config.YosysSmtFlattenDatatype && - vtg_config.YosysSmtFlattenHierarchy)) - << "Grain requires not to flatten hierarchy/datatype"; - - ILA_CHECK(IMPLY(s_backend == synthesis_backend_selector::ABC, - _vtg_config.AbcUseAiger)) - << "Currently only support using AIGER"; - - ILA_CHECK(IMPLY(s_backend == synthesis_backend_selector::ABC, - vtg_config.YosysSmtFlattenHierarchy)) - << "ABC requires to flatten hierarchy"; - // This is hard-coded in the Yosys script - // if not flattened, abc will be unhappy - - ILA_CHECK(IMPLY(s_backend == synthesis_backend_selector::ABC, - vbackend == backend_selector::ABCPDR)); - - ILA_CHECK(IMPLY(s_backend == synthesis_backend_selector::GRAIN, - vbackend == backend_selector::GRAIN_SYGUS && - _vtg_config.YosysSmtStateSort == _vtg_config.Datatypes)); - - ILA_CHECK(IMPLY(s_backend == synthesis_backend_selector::Z3, - vbackend == backend_selector::Z3PDR)); - - ILA_CHECK(IMPLY(vbackend == backend_selector::BTOR_GENERIC, - s_backend == synthesis_backend_selector::NOSYN)); - - ILA_CHECK(s_backend != synthesis_backend_selector::ELDERICA) - << "Bug : not implemented yet!"; - - ILA_CHECK(!(_vtg_config.YosysSmtFlattenDatatype && - _vtg_config.YosysSmtStateSort != _vtg_config.Datatypes)) - << "Must use Datatypes to encode state in order to flatten"; -} // VlgSglTgtGen_Yosys - -/// Add an assumption -void VlgSglTgtGen_Yosys::add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) { - _problems.assumptions[dspt].exprs.push_back(aspt); -} -/// Add an assertion -void VlgSglTgtGen_Yosys::add_a_direct_assertion(const std::string& asst, - const std::string& dspt) { - _problems.assertions[dspt].exprs.push_back(asst); -} - -// PreExportProcess is about how to add assumption/assertions -void VlgSglTgtGen_Yosys::PreExportProcess() { - - std::string all_assert_wire_content; - std::string all_assume_wire_content; - - // you need to add assumptions as well - for (auto&& pbname_prob_pair : _problems.assumptions) { - const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - ILA_DLOG("VlgSglTgtGen_Yosys.PreExportProcess") - << "Adding assumption:" << prbname; - - for (auto&& p : prob.exprs) { - if (all_assume_wire_content.empty()) - all_assume_wire_content = "(" + p + ")"; - else - all_assume_wire_content += "&& (" + p + ")"; - } // for prob.exprs - } // for _problems.assumption - - // this is to check given invariants - for (auto&& pbname_prob_pair : _problems.assertions) { - // const auto& prbname = pbname_prob_pair.first; - const auto& prob = pbname_prob_pair.second; - - // ILA_CHECK(prbname == "cex_nonreachable_assert") - // << "BUG: assertion can only be cex reachability queries."; - // sanity check, should only be invariant's related asserts - - for (auto&& p : prob.exprs) { - // there should be only one expression (for cex target) - // ILA_CHECK(all_assert_wire_content.empty()); - if (all_assert_wire_content.empty()) - all_assert_wire_content = p; - else - all_assert_wire_content += " && " + p; - } // for expr - } // for problem - // add assert wire (though no use : make sure will not optimized away) - ILA_CHECK(!all_assert_wire_content.empty()) << "no property to check!"; - - vlg_wrapper.add_wire("__all_assert_wire__", 1, true); - vlg_wrapper.add_output("__all_assert_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); - - if (!all_assume_wire_content.empty()) { - vlg_wrapper.add_wire("__all_assume_wire__", 1, true); - vlg_wrapper.add_output("__all_assume_wire__", 1); - vlg_wrapper.add_assign_stmt("__all_assume_wire__", all_assume_wire_content); - } - - if ((_backend & backend_selector::CHC) == backend_selector::CHC) { - vlg_wrapper.add_stmt( - "assert property ( __all_assert_wire__ ); // the only assertion \n"); - if (!all_assume_wire_content.empty()) - vlg_wrapper.add_stmt( - "assume property ( __all_assume_wire__ ); // the only assumption \n"); - } else if (_backend == backend_selector::ABCPDR) { - if (all_assume_wire_content.empty()) { - vlg_wrapper.add_stmt( - "assert property ( __all_assert_wire__ ); // the only assertion \n"); - } else { - std::string precond; - ILA_CHECK( - !(_vtg_config.AbcUseAiger == false && - _vtg_config.AbcAssumptionStyle == _vtg_config.AigMiterExtraOutput)) - << "If you don't use aiger, and has assumptions, there is no way to " - "pass the extra output."; - if (_vtg_config.AbcAssumptionStyle == _vtg_config.AigMiterExtraOutput) { - ILA_CHECK(_vtg_config.AbcUseGla == false) << "Cannot use it with GLA"; - vlg_wrapper.add_stmt("assume property (__all_assume_wire__);\n"); - } else { - vlg_wrapper.add_reg("__all_assumed_reg__", 1); - vlg_wrapper.add_stmt("always @(posedge clk) begin"); - vlg_wrapper.add_stmt("if (rst) __all_assumed_reg__ <= 0;"); - vlg_wrapper.add_stmt( - "else if (!__all_assume_wire__) __all_assumed_reg__ <= 1; end"); - precond = "!( __all_assume_wire__ && !__all_assumed_reg__) || "; - } - vlg_wrapper.add_stmt("assert property (" + precond + - " __all_assert_wire__ ); // the only assertion \n"); - } // all_assume_wire_content has sth. there - } // if (_backend == backend_selector::ABCPDR) - else { - // same as CHC - vlg_wrapper.add_stmt( - "assert property ( __all_assert_wire__ ); // the only assertion \n"); - if (!all_assume_wire_content.empty()) - vlg_wrapper.add_stmt( - "assume property ( __all_assume_wire__ ); // the only assumption \n"); - } -} // PreExportProcess - -/// For jasper, this means do nothing, for yosys, you need to add (*keep*) -void VlgSglTgtGen_Yosys::Export_modify_verilog() { - // collect all locations: filename -> lineno - // open, read, count and write - // if it is a port name, we will ask user to specify its upper level - // signal name - VerilogModifier vlg_mod(vlg_info_ptr, - static_cast( - _vtg_config.PortDeclStyle), - _vtg_config.PonoAddKeep, - refinement_map.width_info); - - for (auto&& refered_vlg_item : refinement_map.var_replacement) { - auto old_name = refered_vlg_item.second.get_orig_name(); - auto new_name = refered_vlg_item.second.get_new_name(); - - if(StrStartsWith(new_name, "__ILA_")) - continue; - - auto idx = old_name.find("["); - auto removed_range_name = old_name.substr(0, idx); - vlg_mod.RecordKeepSignalName(removed_range_name); - // auto sig = // no use, this is too late, vlg_wrapper already exported - vlg_mod.RecordConnectSigName(removed_range_name, - refered_vlg_item.second.range_o); - // vlg_wrapper.add_output(sig.first, sig.second); - } - vlg_mod.FinishRecording(); - - // auto tmp_fn = os_portable_append_dir(_output_path, tmp_design_file); - auto tmp_fn = os_portable_append_dir(_output_path, top_file_name); - // now let's do the job - for (auto&& fn : vlg_design_files) { - std::ifstream fin(fn); - std::ofstream fout(tmp_fn, std::ios_base::app); // append to a temp file - if (!fin.is_open()) { - ILA_ERROR << "Cannot read file:" << fn; - continue; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot open file for write:" << tmp_fn; - continue; - } - vlg_mod.ReadModifyWrite(fn, fin, fout); - } // for (auto && fn : vlg_design_files) - - // handles the includes - // .. (copy all the verilog file in the folder), this has to be os independent - if (vlg_include_files_path.size() != 0) { - // copy the files and specify the -I commandline to the run.sh - for (auto&& include_path : vlg_include_files_path) - os_portable_copy_dir(include_path, _output_path); - } - -} // Export_modify_verilog - -/// export the memory abstraction (implementation) -/// Yes, this is also implementation specific, (jasper may use a different one) -void VlgSglTgtGen_Yosys::Export_mem(const std::string& mem_name) { - // we will ignore the mem_name - - auto outfn = os_portable_append_dir(_output_path, top_file_name); - std::ofstream fout(outfn, std::ios_base::app); // append - - VlgAbsMem::OutputMemFile(fout, - _vtg_config.VerificationSettingAvoidIssueStage); -} - -void VlgSglTgtGen_Yosys::ExportAll(const std::string& wrapper_name, // wrapper.v - const std::string& ila_vlg_name, // no use - const std::string& script_name, // the run.sh - const std::string& extra_name, // the chc - const std::string& mem_name) { // no use - - PreExportProcess(); - - if (os_portable_mkdir(_output_path) == false) - ILA_WARN << "Cannot create output directory:" << _output_path; - - // you don't need to worry about the path and names - Export_wrapper(wrapper_name); - // design only - if (target_type == target_type_t::INSTRUCTIONS) - Export_ila_vlg(ila_vlg_name); // this has to be after Export_wrapper - - // for Jasper, this will be put to multiple files - // for CoSA & Yosys, this will be put after the wrapper file (wrapper.v) - Export_modify_verilog(); // this must be after Export_wrapper - Export_mem(mem_name); - - // you need to create the map function -- - Export_problem(extra_name); // the gensmt.ys - - Export_script(script_name); -} - -// ------------------------------------------------------------------ -// The above is generic for all -// The followings are backend specific -// ------------------------------------------------------------------ - -void VlgSglTgtGen_Yosys::Export_script(const std::string& script_name) { - run_script_name = script_name; - - auto fname = os_portable_append_dir(_output_path, script_name); - std::ofstream fout(fname); - if (!fout.is_open()) { - ILA_ERROR << "Error writing to file:" << fname; - return; - } - fout << "#!/bin/bash" << std::endl; - - std::string runnable; - std::string options; - std::string redirect; - - if (s_backend == synthesis_backend_selector::Z3) { - runnable = "z3"; - if (!_vtg_config.Z3Path.empty()) - runnable = os_portable_append_dir(_vtg_config.Z3Path, runnable); - } else if (s_backend == synthesis_backend_selector::GRAIN) { - runnable = "bv"; - if (!_vtg_config.GrainPath.empty()) - runnable = os_portable_append_dir(_vtg_config.GrainPath, runnable); - for (auto&& op : _vtg_config.GrainOptions) - options += " " + op; - - if (_vtg_config.GrainHintsUseCnfStyle) { - ILA_ERROR_IF(!S_IN(" --cnf ", options) && !S_IN(" --grammar ", options)) - << "You must provide grammar in Grain options!"; - } else { - ILA_ERROR_IF(!S_IN(" --grammar-file=", options)) - << "You must provide grammar in Grain options!"; - options += " --chc-file=\"" + prob_fname + "\""; - } - redirect = " 2> ../grain.result"; - } else if (s_backend == synthesis_backend_selector::ABC) { - runnable = "abc"; - if (!_vtg_config.AbcPath.empty()) - runnable = os_portable_append_dir(_vtg_config.AbcPath, runnable); - std::string abc_cmd; - if (_vtg_config.AbcUseGla) - abc_cmd = abcAigCmdGLA; - else - abc_cmd = abcAigCmdNoGLA; - - abc_cmd = ReplaceAll(abc_cmd, "%glatime%", - std::to_string(_vtg_config.AbcGlaTimeLimit)); - abc_cmd = ReplaceAll(abc_cmd, "%glaframe%", - std::to_string(_vtg_config.AbcGlaFrameLimit)); - abc_cmd = ReplaceAll(abc_cmd, "{scorr}", - _vtg_config.AbcUseCorr ? "scorr -v -l -k -F 4" : ""); - abc_cmd = ReplaceAll(abc_cmd, "{lcorr}", - _vtg_config.AbcUseCorr ? "lcorr -v" : ""); - abc_cmd = ReplaceAll(abc_cmd, "{inv_min}", - _vtg_config.AbcMinimizeInv ? "inv_min -l" : ""); - abc_cmd = - ReplaceAll(abc_cmd, "{-v -d}", - _vtg_config.YosysPropertyCheckShowProof ? "-v -d" : ""); - abc_cmd = ReplaceAll( - abc_cmd, "{inv_print -v}", - _vtg_config.YosysPropertyCheckShowProof ? "inv_print -v" : ""); - - std::string abc_command_file_name = "abcCmd.txt"; - { // generate abc command - abc_cmd = ReplaceAll(abc_cmd, "%blifname%", "__aiger_prepare.blif"); - abc_cmd = ReplaceAll(abc_cmd, "%aigname%", prob_fname); - auto abc_cmd_fname = - os_portable_append_dir(_output_path, abc_command_file_name); - std::ofstream abc_cmd_fn(abc_cmd_fname); - if (!abc_cmd_fn.is_open()) { - ILA_ERROR << "Error writing to file:" << abc_cmd_fname; - return; - } - abc_cmd_fn << abc_cmd; - } // generate abc command - options = " -F " + abc_command_file_name; - - } else if (s_backend == synthesis_backend_selector::ELDERICA) { - ILA_CHECK(false) << "Not implemented."; - } else if (s_backend == synthesis_backend_selector::NOSYN) { - if (!_vtg_config.BtorGenericCmdline.empty()) { - runnable = - ReplaceAll(_vtg_config.BtorGenericCmdline, "%btorfile%", prob_fname); - options = ""; - } else { - runnable = "echo"; - options = " \"btor file is available as: " + prob_fname + "\""; - } - } - - if (prob_fname != "") { - if (s_backend == synthesis_backend_selector::Z3 || - (s_backend == synthesis_backend_selector::GRAIN && - _vtg_config.GrainHintsUseCnfStyle)) - fout << runnable << options << " " << prob_fname << redirect << std::endl; - else // ABC, GRAIN, None - fout << runnable << options << redirect << std::endl; - } else - fout << "echo 'Nothing to check!'" << std::endl; - -} // Export_script - -std::shared_ptr -VlgSglTgtGen_Yosys::GetDesignSmtInfo() const { - ILA_CHECK((_backend & backend_selector::CHC) == backend_selector::CHC && - _vtg_config.YosysSmtStateSort == _vtg_config.Datatypes) - << "Only CHC target with datatypes will generate suitable smt-lib2."; - ILA_CHECK(design_smt_info != nullptr); - return design_smt_info; -} - -// export the chc file -void VlgSglTgtGen_Yosys::Export_problem(const std::string& extra_name) { - // used by export script! - prob_fname = extra_name; - if (s_backend == synthesis_backend_selector::ABC) { - generate_aiger( - os_portable_append_dir(_output_path, "__aiger_prepare.blif"), - os_portable_append_dir(_output_path, extra_name), - os_portable_append_dir(_output_path, extra_name + ".map"), - os_portable_append_dir(_output_path, "__gen_blif_script.ys")); - } else if (s_backend == synthesis_backend_selector::GRAIN || - s_backend == synthesis_backend_selector::Z3) { - // first generate a temporary smt - // and extract from it the necessary info - // this is the CHC-style thing - design_only_gen_smt( - os_portable_append_dir(_output_path, "__design_smt.smt2"), - os_portable_append_dir(_output_path, "__gen_smt_script.ys")); - // if (_vtg_config.YosysSmtStateSort == _vtg_config.DataSort) - convert_smt_to_chc_datatype( - os_portable_append_dir(_output_path, "__design_smt.smt2"), - os_portable_append_dir(_output_path, - s_backend == synthesis_backend_selector::GRAIN - ? "grain_prep.txt" - : extra_name)); - // design_smt_info is assigned here in this function - - // for grain : convert wrapper# --> w wrapper_ --> w - if (s_backend == synthesis_backend_selector::GRAIN) { - std::ifstream fin(os_portable_append_dir(_output_path, "grain_prep.txt")); - std::ofstream fout(os_portable_append_dir(_output_path, extra_name)); - if (!fin.is_open()) { - ILA_ERROR << "Cannot read from : " - << os_portable_append_dir(_output_path, "grain_prep.txt"); - return; - } - if (!fout.is_open()) { - ILA_ERROR << "Cannot write to : " - << os_portable_append_dir(_output_path, extra_name); - return; - } - std::string line; - while (std::getline(fin, line)) { - fout << ReplaceAll(ReplaceAll(line, "wrapper#", "w"), "wrapper_", "w_") - << "\n"; - } - } - } else if (s_backend == synthesis_backend_selector::ELDERICA) - ILA_CHECK(false) << "Not implemented."; - else if (s_backend == synthesis_backend_selector::NOSYN) { - design_only_gen_btor( - os_portable_append_dir(_output_path, extra_name), - os_portable_append_dir(_output_path, "__gen_btor_script.ys")); - } - // else: None , Eldarica -} // Export_problem - -/// generate the wrapper's btor -void VlgSglTgtGen_Yosys::design_only_gen_btor( - const std::string& btor_name, const std::string& ys_script_name) { - - auto ys_output_full_name = - os_portable_append_dir(_output_path, "__yosys_exec_result.txt"); - { // export to ys_script_name - std::ofstream ys_script_fout(ys_script_name); - - std::string write_btor_options; - write_btor_options += _vtg_config.BtorAddCommentsInOutputs ? " -v" : ""; - write_btor_options += _vtg_config.BtorSingleProperty ? " -s" : ""; - - ys_script_fout << "read_verilog -sv " - << os_portable_append_dir(_output_path, top_file_name) - << std::endl; - ys_script_fout << "prep -top " << top_mod_name << std::endl; - - auto chcGenSmtTemplate = _vtg_config.ChcWordBlastArray - ? chcGenerateSmtScript_wo_Array - : chcGenerateSmtScript_w_Array; - - ys_script_fout << ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll(ReplaceAll(chcGenSmtTemplate, "%flatten%", - _vtg_config.YosysSmtFlattenHierarchy - ? "flatten;" - : ""), - "%setundef -undriven -init -expose%", - _vtg_config.YosysUndrivenNetAsInput - ? "setundef -undriven -init -expose" - : ""), - "%rstlen%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%cycle%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%module%", top_mod_name); - - // this is for cosa2, I don't know why it is unhappy, but we need fix this - // in the long run - ys_script_fout << "setundef -undriven -zero\n"; - ys_script_fout << "write_btor " << write_btor_options << " " << btor_name; - } // finish writing - - std::string yosys = "yosys"; - - if (!_vtg_config.YosysPath.empty()) - yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); - - // execute it - std::vector cmd; - cmd.push_back(yosys); - cmd.push_back("-s"); - cmd.push_back(ys_script_name); - auto res = os_portable_execute_shell(cmd, ys_output_full_name); - ILA_ERROR_IF(res.failure != res.NONE) << "Executing Yosys failed!"; - ILA_ERROR_IF(res.failure == res.NONE && res.ret != 0) - << "Yosys returns error code:" << res.ret; -} // design_only_gen_smt - -/// generate the wrapper's smt first -void VlgSglTgtGen_Yosys::design_only_gen_smt( - const std::string& smt_name, const std::string& ys_script_name) { - - auto ys_output_full_name = - os_portable_append_dir(_output_path, "__yosys_exec_result.txt"); - { // export to ys_script_name - std::ofstream ys_script_fout(ys_script_name); - - std::string write_smt2_options = - " -mem -bv "; // future work : -stbv, or nothing - if (_vtg_config.YosysSmtStateSort == _vtg_config.Datatypes) - write_smt2_options += "-stdt "; - else if (_vtg_config.YosysSmtStateSort == _vtg_config.BitVec) - write_smt2_options += "-stbv "; - else - ILA_CHECK(false) << "Unsupported smt state sort encoding:" - << _vtg_config.YosysSmtStateSort; - - ys_script_fout << "read_verilog -sv " - << os_portable_append_dir(_output_path, top_file_name) - << std::endl; - ys_script_fout << "prep -top " << top_mod_name << std::endl; - - auto chcGenSmtTemplate = _vtg_config.ChcWordBlastArray - ? chcGenerateSmtScript_wo_Array - : chcGenerateSmtScript_w_Array; - - ys_script_fout << ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll(ReplaceAll(chcGenSmtTemplate, "%flatten%", - _vtg_config.YosysSmtFlattenHierarchy - ? "flatten;" - : ""), - "%setundef -undriven -init -expose%", - _vtg_config.YosysUndrivenNetAsInput - ? "setundef -undriven -init -expose" - : ""), - "%rstlen%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%cycle%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%module%", top_mod_name); - - ys_script_fout << "write_smt2" << write_smt2_options << smt_name; - } // finish writing - - std::string yosys = "yosys"; - - if (!_vtg_config.YosysPath.empty()) - yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); - - // execute it - std::vector cmd; - cmd.push_back(yosys); - cmd.push_back("-s"); - cmd.push_back(ys_script_name); - auto res = os_portable_execute_shell(cmd, ys_output_full_name); - ILA_ERROR_IF(res.failure != res.NONE) << "Executing Yosys failed!"; - ILA_ERROR_IF(res.failure == res.NONE && res.ret != 0) - << "Yosys returns error code:" << res.ret; -} // design_only_gen_smt - -// %WrapperName% -// %WrapperDataType% -// %State% -// %StatePrime% -// %Ss% %Sps% -static std::string RewriteDatatypeChc(const std::string& tmpl, - const std::vector& dt, - const std::string& wrapper_mod_name) { - - std::string chc = tmpl; - - std::vector inv_tps; - smt::YosysSmtParser::convert_datatype_to_type_vec(dt, inv_tps); - auto WrapperDataType = smt::var_type::toString(inv_tps); - - // %BeforeInitVar% - // %InitVar% - // %State% - // %StatePrime% - // declare-var s ... - std::string State; - std::string StatePrime; - // %BIs% %Is% %Ss% %Sps% - std::string Ss; - std::string Sps; - bool first = true; - - std::set name_set; // avoid repetition - for (auto&& st : dt) { - auto st_name = st.verilog_name.back() == '.' || st.verilog_name.empty() - ? st.internal_name - : st.verilog_name; - st_name = ReplaceAll(st_name, "|", ""); // remove its || - // check no repetition is very important! - ILA_CHECK(!IN(st_name, name_set)) << "Bug: name repetition!"; - ILA_CHECK(!st._type.is_datatype()); - name_set.insert(st_name); - auto type_string = st._type.toString(); - State += "(declare-var |S_" + st_name + "| " + type_string + ")\n"; - StatePrime += "(declare-var |S'_" + st_name + "| " + type_string + ")\n"; - - if (!first) { - Ss += " "; - Sps += " "; - } - first = false; - Ss += "|S_" + st_name + "|"; - Sps += "|S'_" + st_name + "|"; - } - // Replacement - chc = ReplaceAll(chc, "%WrapperName%", wrapper_mod_name); - chc = ReplaceAll(chc, "%WrapperDataType%", WrapperDataType); - chc = ReplaceAll(chc, "%State%", State); - chc = ReplaceAll(chc, "%StatePrime%", StatePrime); - chc = ReplaceAll(chc, "%Ss%", Ss); - chc = ReplaceAll(chc, "%Sps%", Sps); - - return chc; -} // RewriteDatatypeChc - -void VlgSglTgtGen_Yosys::convert_smt_to_chc_datatype( - const std::string& smt_fname, const std::string& chc_fname) { - - std::stringstream ibuf; - { // read file - std::ifstream smt_fin(smt_fname); - if (!smt_fin.is_open()) { - ILA_ERROR << "Cannot read from " << smt_fname; - return; - } - ibuf << smt_fin.rdbuf(); - } // end read file - - std::string smt_converted; - if (_vtg_config.YosysSmtStateSort == _vtg_config.Datatypes) - design_smt_info = std::make_shared(ibuf.str()); - - if (_vtg_config.YosysSmtFlattenDatatype) { - ILA_NOT_NULL(design_smt_info); - design_smt_info->BreakDatatypes(); - // smt_rewriter.AddNoChangeStateUpdateFunction(); - smt_converted = design_smt_info->Export(); - } else { - smt_converted = ibuf.str(); - } - - std::string wrapper_mod_name = - design_smt_info ? design_smt_info->get_module_def_orders().back() - : "wrapper"; - // construct the template - - std::string chc; - if (_vtg_config.YosysSmtFlattenDatatype) { - ILA_NOT_NULL(design_smt_info); - const auto& datatype_top_mod = - design_smt_info->get_module_flatten_dt(wrapper_mod_name); - auto tmpl = - ReplaceAll(chc_tmpl_wo_datatypes, "%(set-option :fp.engine spacer)%", - s_backend == synthesis_backend_selector::GRAIN - ? "" - : "(set-option :fp.engine spacer)"); - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_u| %Ss%)", - _vtg_config.ChcAssumptionsReset ? "(|%WrapperName%_u| %Ss%)" : ""); - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_u| %Sps%)", - _vtg_config.ChcAssumptionNextState ? "(|%WrapperName%_u| %Sps%)" : ""); - tmpl = ReplaceAll(tmpl, "(|%WrapperName%_u| %Ss%)", - _vtg_config.ChcAssumptionEnd ? "(|%WrapperName%_u| %Ss%)" - : ""); - tmpl = ReplaceAll( - tmpl, "(|%WrapperName%_h| %Ss%)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%WrapperName%_h| %Ss%)"); - tmpl = ReplaceAll(tmpl, "(|%WrapperName%_h| %Sps%)", - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : "(|%WrapperName%_h| %Sps%)"); - tmpl = ReplaceAll(tmpl, "(and", - !_vtg_config.ChcAssumptionsReset && - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : "(and"); - tmpl = ReplaceAll(tmpl, ")", - !_vtg_config.ChcAssumptionsReset && - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : ")"); - chc = RewriteDatatypeChc(tmpl, datatype_top_mod, wrapper_mod_name); - chc = ReplaceAll(chc, "%%", smt_converted); - } else { - chc = ReplaceAll(chc_tmpl_datatypes, "%(set-option :fp.engine spacer)%", - "(set-option :fp.engine spacer)"); - - chc = - ReplaceAll(chc, "(|%1%_u| |__S__|)", - _vtg_config.ChcAssumptionsReset ? "(|%1%_u| |__S__|)" : ""); - chc = ReplaceAll(chc, "(|%1%_u| |__S'__|)", - _vtg_config.ChcAssumptionNextState ? "(|%1%_u| |__S'__|)" - : ""); - chc = ReplaceAll(chc, "(|%1%_u| |__S__|)", - _vtg_config.ChcAssumptionEnd ? "(|%1%_u| |__S__|)" : ""); - chc = ReplaceAll( - chc, "(|%1%_h| |__S__|)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__S__|)"); - chc = ReplaceAll( - chc, "(|%1%_h| |__S'__|)", - _vtg_config.YosysSmtFlattenHierarchy ? "" : "(|%1%_h| |__S'__|)"); - chc = ReplaceAll(chc, "(and", - !_vtg_config.ChcAssumptionsReset && - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : "(and"); - chc = ReplaceAll(chc, ")", - !_vtg_config.ChcAssumptionsReset && - _vtg_config.YosysSmtFlattenHierarchy - ? "" - : ")"); - chc = ReplaceAll(chc, "%1%", wrapper_mod_name); - chc = ReplaceAll(chc, "%%", smt_converted); - } // end of ~_vtg_config.YosysSmtFlattenDatatype -- no convert - - { // (query fail :print-certificate true) - if (_vtg_config.YosysPropertyCheckShowProof) - chc += "\n(query fail :print-certificate true)\n"; - else - chc += "\n(query fail)\n"; - } - - { // write file - std::ofstream chc_fout(chc_fname); - if (!chc_fout.is_open()) { - ILA_ERROR << "Error writing to : " << chc_fname; - return; - } - chc_fout << chc; - } // end write file - -} // convert_smt_to_chc_datatype - -/// generate the wrapper's smt first -void VlgSglTgtGen_Yosys::generate_aiger(const std::string& blif_name, - const std::string& aiger_name, - const std::string& map_name, - const std::string& ys_script_name) { - - auto ys_output_full_name = - os_portable_append_dir(_output_path, "__yosys_exec_result.txt"); - { // export to ys_script_name - std::ofstream ys_script_fout(ys_script_name); - - ys_script_fout << ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll(abcGenerateAigerWInit_wo_Array, - "%topfile%", - os_portable_append_dir( - _output_path, top_file_name)), - "%module%", top_mod_name), - "%blifname%", blif_name), - "%aigname%", aiger_name), - "%mapname%", map_name), - "%setundef -undriven -init -expose%", - _vtg_config.YosysUndrivenNetAsInput - ? "setundef -undriven -init -expose" - : ""), - "%rstlen%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)), - "%cycle%", - std::to_string( - supplementary_info.cosa_yosys_reset_config.reset_cycles)); - } // finish writing - - std::string yosys = "yosys"; - - if (!_vtg_config.YosysPath.empty()) - yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); - - // execute it - std::vector cmd; - cmd.push_back(yosys); - cmd.push_back("-s"); - cmd.push_back(ys_script_name); - auto res = os_portable_execute_shell(cmd, ys_output_full_name); - ILA_ERROR_IF(res.failure != res.NONE) << "Executing Yosys failed!"; - ILA_ERROR_IF(res.failure == res.NONE && res.ret != 0) - << "Yosys returns error code:" << res.ret; -} // generate_aiger - -}; // namespace ilang diff --git a/test/t_inv_extract.cc b/test/t_inv_extract.cc index eb59645f6..1c9c1c18f 100644 --- a/test/t_inv_extract.cc +++ b/test/t_inv_extract.cc @@ -6,7 +6,7 @@ #include #include #include -#include +// #include #include #include "unit-include/config.h" @@ -28,7 +28,7 @@ class TestInvExtract : public ::testing::Test { }; // class TestInvExtract -#ifdef ILANG_BUILD_INVSYN +#if 0 TEST_F(TestInvExtract, Abc) { diff --git a/test/t_inv_obj.cc b/test/t_inv_obj.cc index 7f8013205..ccff04f72 100644 --- a/test/t_inv_obj.cc +++ b/test/t_inv_obj.cc @@ -5,7 +5,7 @@ #include #include #include -#include +// #include #include #include "unit-include/config.h" diff --git a/test/t_inv_syn.cc b/test/t_inv_syn.cc index ad27e5bf0..c54f5b2ee 100644 --- a/test/t_inv_syn.cc +++ b/test/t_inv_syn.cc @@ -4,7 +4,7 @@ #include #include #include -#include +// #include #include #include "unit-include/config.h" @@ -14,7 +14,8 @@ namespace ilang { -#ifdef ILANG_BUILD_INVSYN +// #ifdef ILANG_BUILD_INVSYN +#if 0 #define DBG_TAG "VlgVerifInvSyn" diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index f4d1bb270..8c8f850d7 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -21,7 +21,6 @@ TEST(TestVlgTargetGen, PipeExample) { auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); auto rfDir = os_portable_append_dir(dirName, "rfmap"); auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.CosaGenJgTesterScript = true; VerilogVerificationTargetGenerator vg( {}, // no include @@ -31,7 +30,7 @@ TEST(TestVlgTargetGen, PipeExample) { os_portable_append_dir(rfDir, "cond.json"), // instruction-mapping os_portable_append_dir(dirName, "verify"), // verification dir ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::COSA, // engine + VerilogVerificationTargetGenerator::backend_selector::PONO, // engine vtg_config); EXPECT_FALSE(vg.in_bad_state()); @@ -39,6 +38,7 @@ TEST(TestVlgTargetGen, PipeExample) { vg.GenerateTargets(); } +#if 0 TEST(TestVlgTargetGen, PipeExampleZ3) { auto ila_model = SimplePipe::BuildModel(); @@ -204,6 +204,8 @@ TEST(TestVlgTargetGen, PipeExampleAbc) { vg.GenerateTargets(); } +#endif + TEST(TestVlgTargetGen, PipeExampleRfmapPost) { auto ila_model = SimplePipe::BuildModel(); @@ -220,7 +222,7 @@ TEST(TestVlgTargetGen, PipeExampleRfmapPost) { "cond-rfmap-pvholder.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_pvholder"), // verification dir ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::COSA // engine + VerilogVerificationTargetGenerator::backend_selector::PONO // engine ); EXPECT_FALSE(vg.in_bad_state()); @@ -264,7 +266,7 @@ TEST(TestVlgTargetGen, PipeExampleNotEqu) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond.json"})), os_portable_append_dir(dirName, "disprove/"), ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -284,7 +286,7 @@ TEST(TestVlgTargetGen, Memory) { os_portable_append_dir(dirName, P({"cond.json"})), dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -309,7 +311,7 @@ TEST(TestVlgTargetGen, MemoryInternal) { // test the expansion of memory os_portable_append_dir(dirName, "cond-expand.json"), dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, vtg_cfg, + VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg, vlg_cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -331,7 +333,7 @@ TEST(TestVlgTargetGen, MemoryInternalExternal) { os_portable_append_dir(dirName, "cond-rfarray.json"), dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -352,7 +354,7 @@ TEST(TestVlgTargetGen, MemoryInternalExternalEntry6) { dirName + "cond-rfarray.json", // cond path dirName + "rfarray_rf6/", // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, vtg_cfg); + VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -371,7 +373,7 @@ TEST(TestVlgTargetGen, MemoryRead) { dirName + "cond-rd.json", // cond path dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -381,8 +383,6 @@ TEST(TestVlgTargetGen, MemoryRead) { TEST(TestVlgTargetGen, MemoryAbsRead) { VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; - vtg_cfg.MemAbsReadAbstraction = true; // enable read abstraction - auto ila_model = MemorySwap::BuildModel(); auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; @@ -394,7 +394,7 @@ TEST(TestVlgTargetGen, MemoryAbsRead) { dirName + "cond.json", // cond path dirName + "rdabs/", // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, vtg_cfg); + VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -404,8 +404,6 @@ TEST(TestVlgTargetGen, MemoryAbsRead) { TEST(TestVlgTargetGen, MemoryReadAbsRead) { VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; - vtg_cfg.MemAbsReadAbstraction = true; // enable read abstraction - auto ila_model = MemorySwap::BuildRdModel(); auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; @@ -417,7 +415,7 @@ TEST(TestVlgTargetGen, MemoryReadAbsRead) { dirName + "cond-rd.json", // cond path dirName + "rdabs/", // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, vtg_cfg); + VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -427,8 +425,6 @@ TEST(TestVlgTargetGen, MemoryReadAbsRead) { TEST(TestVlgTargetGen, MemoryReadAbsReadJasperGold) { VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; - vtg_cfg.MemAbsReadAbstraction = true; // enable read abstraction - auto ila_model = MemorySwap::BuildRdModel(); auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; @@ -460,7 +456,7 @@ TEST(TestVlgTargetGen, UndetValue) { dirName + "cond-val.json", // cond path dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -479,28 +475,7 @@ TEST(TestVlgTargetGen, UndetFunc) { dirName + "cond-func.json", // cond path dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} - -TEST(TestVlgTargetGen, UndetFuncIteUnknown) { - auto ila_model = UndetFunc::BuildIteUknModel(); - auto vtg_cfg = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_cfg.IteUnknownAutoIgnore = true; - - auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/undetf2/"; - VerilogVerificationTargetGenerator vg( - {}, // no include - {dirName + "func.v"}, // vlog files - "undetfunc", // top_module_name - dirName + "vmap-func.json", // variable mapping - dirName + "cond-func.json", // cond path - dirName, // output path - ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, vtg_cfg); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -523,7 +498,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path os_portable_append_dir(dirName, "out"), // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -544,7 +519,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path os_portable_append_dir(dirName, "out"), // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -565,7 +540,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path os_portable_append_dir(dirName, "out"), // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -586,7 +561,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path os_portable_append_dir(dirName, "out"), // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -607,7 +582,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path os_portable_append_dir(dirName, "out"), // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA); + VerilogVerificationTargetGenerator::backend_selector::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -615,58 +590,5 @@ TEST(TestVlgTargetGen, ResetAnnotation) { } } -TEST(TestVlgTargetGen, ResetAnnotationZ3) { - auto ila_model = MemorySwap::BuildResetterTest(); - auto dirName = os_portable_join_dir( - {ILANG_TEST_SRC_ROOT, "unit-data", "vpipe", "reset"}); - - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.YosysPath = "N/A"; - vtg_config.GrainPath = "N/A"; - vtg_config.Z3Path = "N/A"; - vtg_config.AbcPath = "N/A"; - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_join_dir({dirName, "verilog", "resetter.v"})}, // vlog files - "resetter", // top_module_name - os_portable_join_dir({dirName, "rfmap", "vmap.json"}), // variable mapping - os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path - os_portable_append_dir(dirName, "out-z3"), // output path - ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::Z3PDR, vtg_config); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} - -TEST(TestVlgTargetGen, ResetAnnotationABC) { - auto ila_model = MemorySwap::BuildResetterTest(); - auto dirName = os_portable_join_dir( - {ILANG_TEST_SRC_ROOT, "unit-data", "vpipe", "reset"}); - - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.YosysPath = "N/A"; - vtg_config.GrainPath = "N/A"; - vtg_config.Z3Path = "N/A"; - vtg_config.AbcPath = "N/A"; - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_join_dir({dirName, "verilog", "resetter.v"})}, // vlog files - "resetter", // top_module_name - os_portable_join_dir({dirName, "rfmap", "vmap.json"}), // variable mapping - os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path - os_portable_append_dir(dirName, "out-abc"), // output path - ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::ABCPDR, vtg_config); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} - -TEST(TestVlgTargetGen, AesExample) {} }; // namespace ilang From f669a750c23ca4d12d7beb47871cf889bef1ea3a Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 21 Jul 2021 11:03:28 +0800 Subject: [PATCH 26/78] update vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 10d544861..efe2ea43b 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 10d544861341a9cf9f26f0d71fe1d87f6d651430 +Subproject commit efe2ea43b48f2be0ae923232ce4157b76605f76c From cf009f544c8a4af567922e15d752257e08f19a4b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 28 Jul 2021 17:02:42 +0800 Subject: [PATCH 27/78] rfexpr wip --- include/ilang/rfmap-in/rfexpr_shortcut.h | 37 ++ include/ilang/rfmap-in/rfmap_typecheck.h | 69 ++- include/ilang/rfmap-in/rfvar_type.h | 12 +- include/ilang/rfmap-in/verilog_rfmap.h | 2 + include/ilang/vtarget-out/vtarget_gen_impl.h | 91 +++- .../ilang/vtarget-out/vtarget_gen_jasper.h | 12 +- src/rfmap-in/CMakeLists.txt | 1 + src/rfmap-in/rfexpr_shortcut.cc | 74 +++ src/rfmap-in/rfmap_typecheck.cc | 288 ++++------- src/rfmap-in/verilog_rfmap.cc | 30 +- src/vtarget-out/gen_util.cc | 474 +++++++++++------- src/vtarget-out/single_target.cc | 86 ++-- src/vtarget-out/single_target_as.cc | 103 +--- src/vtarget-out/single_target_cond.cc | 71 ++- src/vtarget-out/single_target_connect.cc | 25 +- .../single_target_inv_syn_support.cc | 47 +- src/vtarget-out/single_target_misc.cc | 124 ++++- src/vtarget-out/vlg_mod.cc | 6 +- src/vtarget-out/vtarget_gen_impl.cc | 2 +- src/vtarget-out/vtarget_gen_jasper.cc | 16 +- src/vtarget-out/vtarget_gen_pono.cc | 9 +- test/unit-data/vpipe/rfmap/cond.json | 40 +- test/unit-data/vpipe/rfmap/vmap.json | 49 +- 23 files changed, 915 insertions(+), 753 deletions(-) create mode 100644 include/ilang/rfmap-in/rfexpr_shortcut.h create mode 100644 src/rfmap-in/rfexpr_shortcut.cc diff --git a/include/ilang/rfmap-in/rfexpr_shortcut.h b/include/ilang/rfmap-in/rfexpr_shortcut.h new file mode 100644 index 000000000..9f7d0d22b --- /dev/null +++ b/include/ilang/rfmap-in/rfexpr_shortcut.h @@ -0,0 +1,37 @@ +/// \file rfexpr_shortcut.h Refinement map expression +/// construction +/// Hongce Zhang (zhanghongce@126.com) + + +#ifndef ILANG_RFEXPR_SHORTCUT_H__ +#define ILANG_RFEXPR_SHORTCUT_H__ + +#include + +namespace ilang { + +rfmap::RfExpr rfmap_imply(const rfmap::RfExpr &l, const rfmap::RfExpr &r); +rfmap::RfExpr rfmap_and(const rfmap::RfExpr &l, const rfmap::RfExpr &r); +rfmap::RfExpr rfmap_or(const rfmap::RfExpr &l, const rfmap::RfExpr &r); +rfmap::RfExpr rfmap_and(const std::vector &v); +rfmap::RfExpr rfmap_or(const std::vector &v); + +rfmap::RfExpr rfmap_ite(const rfmap::RfExpr &c, const rfmap::RfExpr &l, + const rfmap::RfExpr &r); + +rfmap::RfExpr rfmap_eq(const rfmap::RfExpr &l, const rfmap::RfExpr &r); +rfmap::RfExpr rfmap_le(const rfmap::RfExpr &l, const rfmap::RfExpr &r); + +rfmap::RfExpr rfmap_not(const rfmap::RfExpr &l); + +rfmap::RfExpr rfmap_const(unsigned w, unsigned b, unsigned v); +/// if it is RTL. or ILA. then will use MakeVar +/// otherwise will use MakeSpecial +/// will not determine its type +/// ReplExpr will determine the type +rfmap::RfExpr rfmap_var(const std::string &v); + +} // namespace ilang + +#endif // ILANG_RFEXPR_SHORTCUT_H__ + diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index a4096d38e..ccdae444e 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -37,39 +37,20 @@ class TypeAnnotation : struct VarReplacement { RfExpr origvar; // this is certainly a var RfExpr newvar; // this is certainly a var - std::string range_o; // but this could be different - VarReplacement(const RfExpr & o, const RfExpr & n, const std::string & r = "") : - origvar(o), newvar(n), range_o (r) {} + VarReplacement(const RfExpr & o, const RfExpr & n); + // returns v or v[range] std::string get_orig_name() const { - if(is_orig_var_array() && !range_o.empty()) - return ( - std::dynamic_pointer_cast - (origvar)->get_name().first + "[" + range_o + "]" - ); - // else return std::dynamic_pointer_cast( origvar)->get_name().first; } std::string get_new_name() const{ - //if(is_orig_var_array() && !range_o.empty()) - // return ( - // std::dynamic_pointer_cast - // (origvar)->get_name().first + "_" + ReplaceAll(range_o,"'","") + "_" - // ); - // else return std::dynamic_pointer_cast (newvar)->get_name().first; } RfVarTypeOrig get_type_new() const { - /*if(is_orig_var_array() && !range_o.empty()) { - TypeAnnotation ret; - ret.type = RfMapVarType(get_type_orig().type.data_width); - ret.var_ref_type = TypeAnnotation::VARTYPE::NOTVAR; - return ret; - }*/ return get_type_orig(); } @@ -120,6 +101,8 @@ class TypeAnalysisUtility { protected: var_typecheck_t typechecker; + // used in TypedVerilogRefinementMap::TypeInferTravserRfExpr + // this is only used in the first stage : aux var width determination // internal use only, does not do recursion itself // therefore, an order of invocation is needed @@ -129,6 +112,7 @@ class TypeAnalysisUtility { class RfExprAstUtility { public: + static bool HasArrayVar(const RfExpr & in, std::map & array_var); /// determine if a rf expr is a boolean expr static bool IsLastLevelBooleanOp(const RfExpr & in); /// get the variables from a expression @@ -148,19 +132,16 @@ struct TypedVerilogRefinementMap : using VarDef = GeneralVerilogMonitor::VarDef; // constructor + // typechecker is only used in TypeInferTraverseRfExpr TypedVerilogRefinementMap( const std::string & varmap_json_file, const std::string & instcond_json_file, - var_typecheck_t type_checker, - const std::string & ila_inst_decode_signal_name, - const std::string & ila_valid_signal_name + var_typecheck_t type_checker ); TypedVerilogRefinementMap( const VerilogRefinementMap & refinement, - var_typecheck_t type_checker, - const std::string & ila_inst_decode_signal_name, - const std::string & ila_valid_signal_name + var_typecheck_t type_checker ); @@ -176,28 +157,38 @@ struct TypedVerilogRefinementMap : // 1. first round : only explict ones // this is to collect information before running the // the AST type checks - // 2. second round : will be populated by the AST type checks - // so this can NOT be used in creating vars stage? - // Var creating stage should deal with separate ones std::map all_var_def_types; + // the above is only used in the first round + // 2. second round : AST type check + // so this is NOT used in creating vars? + // Var creating stage should deal with separate ones + // this should include phase-tracker (m,v,alias) // ... ? void TraverseAllRfExpr(std::function func); /// used by vtarget_gen to replace rtl/ila vars - RfExpr ReplacingRtlIlaVar(const RfExpr & in, bool replace_dot); + RfExpr ReplacingRtlIlaVar(const RfExpr & in); + + /// Register internal variables and also the mapping + void RegisterInternalVariableWithMapping( + const std::string & n, + const VarReplacement & in) { var_replacement.emplace(n, in); } + + VarReplacement * CheckReplacement(const std::string & origname) const { + auto pos = var_replacement.find(origname); + if(pos != var_replacement.end()) + return &(pos->second); + return NULL; + } + +protected: /// the replacement used for creating new wires std::map var_replacement; // including rtl/ilas/ilav -protected: - - void initialize( - const std::string & ila_inst_decode_signal_name, - const std::string & ila_valid_signal_name); - void CollectInternallyDefinedVars( - const std::string & ila_inst_decode_signal_name, - const std::string & ila_valid_signal_name); + void initialize(); + void CollectInternallyDefinedVars(); void TraverseRfExpr(RfExpr & inout, std::function func) ; void TraverseCondMap(SingleVarMap & inout, std::function func) ; diff --git a/include/ilang/rfmap-in/rfvar_type.h b/include/ilang/rfmap-in/rfvar_type.h index 11c8e325d..0926eb07b 100644 --- a/include/ilang/rfmap-in/rfvar_type.h +++ b/include/ilang/rfmap-in/rfvar_type.h @@ -6,6 +6,7 @@ #ifndef ILANG_RFMAP_VARTYPE_H__ #define ILANG_RFMAP_VARTYPE_H__ +#include namespace ilang { namespace rfmap { @@ -28,6 +29,14 @@ struct RfMapVarType { /// for array type RfMapVarType(unsigned a, unsigned d) : type(TYPE::MEM), addr_width(a), data_width(d) {} unsigned unified_width() const { return type == RfMapVarType::TYPE::BV ? width : data_width; } + + std::string to_string() const { + if(is_unknown()) + return "(unknown)"; + if(is_bv) + return "(_ BitVec " + std::to_string(width)+")"; + return "(Array (_ BitVec " + std::to_string(addr_width)+") (_ BitVec " + std::to_string(data_width)+"))"; + } }; class RfVarTypeOrig { @@ -37,10 +46,7 @@ class RfVarTypeOrig { ILAS, /*state var*/ ILAI, /*ila input*/ RTLV, /*rtl signal*/ - PHASE, /*stage name*/ DEFINE_VAR, /*defined vars*/ - DELAY, /*inline delay*/ - VALUE_RECORDER, /*inline value recorder*/ INTERNAL /* those already translated: like __CYCLE_CNT__, __START__*/ }; diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index ce5f20ae3..0b09bc864 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -93,6 +93,8 @@ struct ResetSpecification { unsigned reset_cycle; // customized reset sequence std::map custom_reset_sequence; + // default constructor + ResetSpecification() : reset_cycle(1) { } }; // ResetSpecification struct ClockSpecification { diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 7f6c18dca..918b826a7 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -161,24 +161,64 @@ class VlgSglTgtGen { const SignalInfoBase& vlg_var); /// get width of an ila node static unsigned get_width(const ExprPtr& n); - /// Parse and modify a condition string - std::string ReplExpr(const rfmap::RfExpr & in); + + // ----------------------------------------------------------------------- + // Refinement map handling + // ----------------------------------------------------------------------- + /// Create a variable replacement for var + /// RTL_var/ ILA_IN/ ILA_SO/ INTERNL-DEFVAR + /// a new var is always typed + /// otherwise, will not + /// this function get type information from + /// VarTypeCheckForRfExprParsing and + /// refinement_map.all_var_def_type + rfmap::VarReplacement CreateVarReplacement( + const rfmap::RfVar & var, bool replace_internal_names); + /// replace var for assumptions/assertions + /// (should only be used inside assumptions/assertions) + /// 1. GetVar 2. Check Replacement 3. add replacement using the above + /// function 4. do replacement for var 5. annotate type + rfmap::RfExpr ReplExpr(const rfmap::RfExpr & in); + /// treat `in` as var map, if it is not a Boolean, add `==` - std::string TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn); + /// this function is not used in `_bv` version below + rfmap::RfExpr TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn); - /// translate a conditional map to vlg expression - std::string condition_map_to_str( + /// translate a conditional map to rf expression + rfmap::RfExpr condition_map_to_rfexpr( const std::vector> & cond_map, const std::string & ila_state_name); + /// difference from condition_map_to_rfexpr is that + /// this will not create (v == ...) , this expects bv + rfmap::RfExpr condition_map_bv_to_rfexpr( + const std::vector> & cond_map); - std::string non_mem_map_to_str( + /// translate a single map to rfexpr + rfmap::RfExpr singlemap_to_rfexpr( const rfmap::SingleVarMap & single_map, const std::string & ila_state_name); + /// translate a single map to rfexpr (expect bit-vector) + rfmap::RfExpr singlemap_bv_to_rfexpr( + const rfmap::SingleVarMap & single_map); + + /// register a reg in refinement_map.all_var_def_type + void rfmap_add_internal_reg(const std::string &n, unsigned width); + /// register a wire in refinement_map.all_var_def_type + void rfmap_add_internal_wire(const std::string &n, unsigned width); + /// register a replacement in refinement_map + /// this will affect ReplExpr's behavior + /// (Note 1: ReplExpr will also create replacement, but it will not use + /// this function. 2: will require that the new one has been registered + /// in refinement_map.all_var_def_type) + void rfmap_add_replacement(const std::string &old, const std::string &n); /// handle a var map void Gen_varmap_assumpt_assert(const std::string& ila_state_name, - const rfmap::IlaVarMapping &vmap, const std::string & problem_name, bool true_for_assumpt_false_for_assert, - const std::string & prefix, const std::string & suffix); + const rfmap::IlaVarMapping &vmap, const std::string & problem_name, bool true_for_assumpt_false_for_assert); + + // handle an input map + void Gen_input_map_assumpt(const std::string& ila_input_name, + const rfmap::IlaVarMapping &imap, const std::string & problem_name); /// add a start condition if it is given void handle_start_condition(const std::vector & dc); @@ -315,35 +355,38 @@ class VlgSglTgtGen { const std::string& dspt) = 0; // helper function to be implemented by COSA, Yosys, invsyn, jasper is not - /// Add an assumption -- JasperGold will override this - virtual void add_an_assumption(const std::string& aspt, - const std::string& dspt); + /// Add an assumption -- if aspt can be represented in vlg + // then will only use vlg (this is true for jg) + // but for those needs Yosys, array will be handled differently + virtual void add_an_assumption(const rfmap::RfExpr& aspt, + const std::string& dspt) = 0; /// Add an assertion -- JasperGold will override this - virtual void add_an_assertion(const std::string& asst, - const std::string& dspt); + virtual void add_an_assertion(const rfmap::RfExpr& asst, + const std::string& dspt) = 0; // Add SMT assumption (using rfexpr) + // - will use add_a_direct_smt_assumption/assertion virtual void add_smt_assumption( - const std::unordered_map & vars, const rfmap::RfExpr & body, const std::string & dspt); // Add SMT assertion (using rfexpr) virtual void add_smt_assertion( - const std::unordered_map & vars, const rfmap::RfExpr & body, const std::string & dspt); - /// Add an assignment which in JasperGold could be an assignment, but in CoSA - /// has to be an assumption + /// Add an assignment which in JasperGold could be an assignment, but in Yosys-based solution + /// has to be an assumption virtual void add_wire_assign_assumption(const std::string& varname, - const std::string& expression, - const std::string& dspt); - /// Add an assignment to a register which in JasperGold could be an - /// assignment, but in CoSA has to be an assumption + const rfmap::RfExpr &aspt, + const std::string& dspt) = 0; + + /// Add an assignment, will always be an assumption + /// will use add_an_assumption, and it is up to + /// the derived class to determine whether to add as vlg/smt assumption virtual void add_reg_cassign_assumption(const std::string& varname, - const std::string& expression, - int width, const std::string& cond, + const rfmap::RfExpr & expression, + int width, const rfmap::RfExpr & cond, const std::string& dspt); public: @@ -358,6 +401,8 @@ class VlgSglTgtGen { protected: /// If it is bad state, return true and display a message bool bad_state_return(void); + /// this function make sure ila.input and ila.sv are all mapped + /// in the refinement map and no more vars are mapped void RfmapIlaStateSanityCheck(); private: diff --git a/include/ilang/vtarget-out/vtarget_gen_jasper.h b/include/ilang/vtarget-out/vtarget_gen_jasper.h index 8de5be005..c9094c9c9 100644 --- a/include/ilang/vtarget-out/vtarget_gen_jasper.h +++ b/include/ilang/vtarget-out/vtarget_gen_jasper.h @@ -69,10 +69,10 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { const std::string& body, const std::string& dspt) override; /// Add an assumption - virtual void add_an_assumption(const std::string& aspt, + virtual void add_an_assumption(const rfmap::RfExpr& aspt, const std::string& dspt) override; /// Add an assertion - virtual void add_an_assertion(const std::string& asst, + virtual void add_an_assertion(const rfmap::RfExpr& asst, const std::string& dspt) override; /// Add a direct assumption virtual void add_a_direct_assumption(const std::string& aspt, @@ -84,13 +84,7 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { /// Add an assignment which in JasperGold could be an assignment, but in CoSA /// has to be an assumption virtual void add_wire_assign_assumption(const std::string& varname, - const std::string& expression, - const std::string& dspt) override; - /// Add an assignment to a register which in JasperGold could be an - /// assignment, but in CoSA has to be an assumption - virtual void add_reg_cassign_assumption(const std::string& varname, - const std::string& expression, - int width, const std::string& cond, + const rfmap::RfExpr& expression, const std::string& dspt) override; /// Pre export work : nothing for cosa diff --git a/src/rfmap-in/CMakeLists.txt b/src/rfmap-in/CMakeLists.txt index 3a3f77874..927431f9f 100644 --- a/src/rfmap-in/CMakeLists.txt +++ b/src/rfmap-in/CMakeLists.txt @@ -5,5 +5,6 @@ target_sources(${ILANG_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/verilog_rfmap.cc ${CMAKE_CURRENT_SOURCE_DIR}/rfmap_typecheck.cc ${CMAKE_CURRENT_SOURCE_DIR}/rfexpr_to_smt.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rfexpr_shortcut.cc ) diff --git a/src/rfmap-in/rfexpr_shortcut.cc b/src/rfmap-in/rfexpr_shortcut.cc new file mode 100644 index 000000000..68b633cff --- /dev/null +++ b/src/rfmap-in/rfexpr_shortcut.cc @@ -0,0 +1,74 @@ +/// \file rfexpr_to_smt.cc Refinement map to smt-lib2 +/// Hongce Zhang (zhanghongce@126.com) + +#include +#include +#include + +namespace ilang { + +rfmap::RfExpr rfmap_imply(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { + return rfmap_or(rfmap_not(l), r); +} + +rfmap::RfExpr rfmap_and(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, l, r); +} + +rfmap::RfExpr rfmap_or(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_OR, l, r); +} + +rfmap::RfExpr rfmap_and(const std::vector &v) { + ILA_ERROR_IF(v.empty()) << "rfmap_and([])"; + + auto ret = v.at(0); + for (size_t idx = 1; idx < v.size(); ++ idx) + ret = rfmap_and(ret, v.at(idx)); + return ret; +} + +rfmap::RfExpr rfmap_or(const std::vector &v) { + ILA_ERROR_IF(v.empty()) << "rfmap_or([])"; + + auto ret = v.at(0); + for (size_t idx = 1; idx < v.size(); ++ idx) + ret = rfmap_or(ret, v.at(idx)); + return ret; +} + +rfmap::RfExpr rfmap_ite(const rfmap::RfExpr &c, const rfmap::RfExpr &l, + const rfmap::RfExpr &r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::ITE, + c, l, r); +} + +rfmap::RfExpr rfmap_eq(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, l, r); +} + +rfmap::RfExpr rfmap_le(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_LE, l, r); +} + +rfmap::RfExpr rfmap_not(const rfmap::RfExpr &l) { + return verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, l); +} + +rfmap::RfExpr rfmap_const(unsigned b, unsigned w, unsigned v) { + return verilog_expr::VExprAst::MakeConstant(w, b, IntToStrCustomBase(v, b, false)); +} +/// if it is RTL. or ILA. then will use MakeVar +/// otherwise will use MakeSpecial +/// will not determine its type +/// ReplExpr will determine the type +rfmap::RfExpr rfmap_var(const std::string &v) { + if(StrStartsWith(v, "RTL.") || StrStartsWith(v, "ILA.")) + return verilog_expr::VExprAst::MakeVar(v); + return verilog_expr::VExprAst::MakeSpecial(v); +} + + + + +} // namespace ilang diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index cdf748b7b..7cc153e15 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -20,40 +20,34 @@ std::string TypedVerilogRefinementMap::new_id() { TypedVerilogRefinementMap::TypedVerilogRefinementMap( const VerilogRefinementMap & refinement, - var_typecheck_t type_checker, - const std::string & ila_inst_decode_signal_name, - const std::string & ila_valid_signal_name + var_typecheck_t type_checker ) : VerilogRefinementMap(refinement), TypeAnalysisUtility(type_checker), counter(0) { - initialize(ila_inst_decode_signal_name,ila_valid_signal_name); + initialize(); } TypedVerilogRefinementMap::TypedVerilogRefinementMap( const std::string & varmap_json_file, const std::string & instcond_json_file, - var_typecheck_t type_checker, - const std::string & ila_inst_decode_signal_name, - const std::string & ila_valid_signal_name + var_typecheck_t type_checker ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), TypeAnalysisUtility(type_checker), counter(0) { - initialize(ila_inst_decode_signal_name,ila_valid_signal_name); + initialize(); } // TypedVerilogRefinementMap::TypedVerilogRefinementMap -void TypedVerilogRefinementMap::initialize( - const std::string & ila_inst_decode_signal_name, - const std::string & ila_valid_signal_name) { +void TypedVerilogRefinementMap::initialize() { // collect those with unknown types // a. delay // b. value holder CollectInlineDelayValueHolder(); - // collect those new vars with user-defined types - CollectInternallyDefinedVars( - ila_inst_decode_signal_name, - ila_valid_signal_name - ); + // put existing internal vars in + // all_var_def_types + CollectInternallyDefinedVars(); // determine the types of delay and value holder + // and add them to all_var_def_types + // will use current all_var_def_types ComputeDelayValueHolderWidth(); } // initialize @@ -61,9 +55,9 @@ void TypedVerilogRefinementMap::initialize( // this function will iteratively make a new copy of the whole AST. RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( - const RfExpr & in, - bool replace_internal_wire) + const RfExpr & in) { +#error "modify ReplExpr" // skip state memory mapped // provide a function to ReplExpr... auto tp_annotate = in->get_annotation(); @@ -73,135 +67,20 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( ILA_NOT_NULL(var_ptr); auto n = var_ptr->get_name(); - if(var_replacement.find(n.first) != var_replacement.end()) { - return var_replacement.at(n.first).newvar; - } - - RfVarTypeOrig tp; - - if(tp_annotate != nullptr) - tp = *tp_annotate; - if(tp.type.is_unknown()) { - auto pos_def_var = all_var_def_types.find(n.first); - auto rtl_ila_tp = typechecker(n.first); - - if(n.second) { // if it is special name - if(pos_def_var != all_var_def_types.end()) { - tp.var_ref_type = RfVarTypeOrig::VARTYPE::DEFINE_VAR; - tp.type = RfMapVarType(pos_def_var->second.width); - } else { - tp = rtl_ila_tp; - } - } else { // if it is not special name - if(!rtl_ila_tp.type.is_unknown()) - tp = rtl_ila_tp; - else if(pos_def_var != all_var_def_types.end()) { - tp.var_ref_type = RfVarTypeOrig::VARTYPE::DEFINE_VAR; - tp.type = RfMapVarType(pos_def_var->second.width); - } - } - // put back the annotation? in new expr? - } // end if it is unknown - ILA_WARN_IF(tp.type.is_unknown()) << "type of var: " << (n.second?"#":"") << n.first << " is still unknown."; - - - if(tp.var_ref_type == RfVarTypeOrig::VARTYPE::RTLV) { - - bool is_array = tp.type.is_array(); - if(!replace_internal_wire || is_array) { - auto ret_copy = std::make_shared(*var_ptr); - ret_copy->set_annotation(std::make_shared(tp)); - return ret_copy; - // 1 will not do replacement - // 2 will not record that - } + ILA_CHECK(var_replacement.find(n.first) != var_replacement.end()) + << "variable " << n.first << " has no replacement"; - auto new_name = ReplaceAll(n.first, ".", "__DOT__"); - auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); - new_node->set_annotation(std::make_shared(tp)); - var_replacement.emplace(n.first, VarReplacement(in, new_node)); - return new_node; - } else if (tp.var_ref_type == RfVarTypeOrig::VARTYPE::ILAI) { - auto new_name = "__ILA_I_" + n.first; - auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); - new_node->set_annotation(std::make_shared(tp)); - var_replacement.emplace(n.first, VarReplacement(in, new_node)); - return new_node; - } else if (tp.var_ref_type == RfVarTypeOrig::VARTYPE::ILAS) { - auto new_name = "__ILA_SO_" + n.first; - auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); - new_node->set_annotation(std::make_shared(tp)); - var_replacement.emplace(n.first, VarReplacement(in, new_node)); - return new_node; - } - - auto ret_copy = std::make_shared(*var_ptr); - ret_copy->set_annotation(std::make_shared(tp)); - return ret_copy; // will return the annotated one anyway - } // is_var - else if (in->is_constant()) { - auto cptr = std::dynamic_pointer_cast(in); - ILA_NOT_NULL(cptr); - auto ret_copy = std::make_shared(*cptr); - if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { - RfVarTypeOrig tp; - tp.type = RfMapVarType(std::get<1>(cptr->get_constant())); // base, width,... - ret_copy->set_annotation(std::make_shared(tp)); - } - return ret_copy; // no annotation needed - } else { - // check type - auto ret_copy = std::make_shared(*in); - for (size_t idx = 0 ; idx < ret_copy->get_child_cnt(); ++ idx) { - ret_copy->child(idx) = - ReplacingRtlIlaVar( - ret_copy->get_child().at(idx), replace_internal_wire); - } // for each child - - if(!replace_internal_wire && - ret_copy->child(0)->is_var() && - ret_copy->get_op() == verilog_expr::voperator::INDEX) { - - std::shared_ptr annotate = - ret_copy->child(0)->get_annotation(); - - if(annotate != nullptr && annotate->type.is_array()) { - assert(ret_copy->get_child_cnt() == 2); - auto array_index = ret_copy->child(1); - auto n = std::dynamic_pointer_cast - ( ret_copy->child(0) )->get_name(); - - if( array_index->is_constant() ) { - std::string range_o = array_index->to_verilog(); - - auto new_name = ReplaceAll(n.first, ".", "__DOT__") + "_"+ ReplaceAll(range_o,"'","") +"_"; - auto orig_name = n.first+"["+range_o+"]"; - - if(var_replacement.find(orig_name) != var_replacement.end()) - return var_replacement.at(orig_name).newvar; - - auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); - auto new_annotation = std::make_shared(); - new_annotation->type = RfMapVarType(annotate->type.unified_width()); - new_node->set_annotation(new_annotation); - - var_replacement.emplace(orig_name, VarReplacement(in, new_node, range_o)); - return new_node; - } else { - ILA_CHECK(false) << "FIXME: currently does not handle dynamic index into array"; - // HZ note: in the future we can do this - // by allowing array shadowing, this will definitely need smt-lib2 expression - // or Jasper's capability, because we can never connect a whole Verilog array out - // using Yosys's SVA. - - } // end if it is const - } - } // special handling for array[idx] - // to determine the type of ret_copy - infer_type_based_on_op_child(ret_copy); - return ret_copy; // may use new_node instead in the special case - } // end of is_op - assert(false); // Should not be reachable + return var_replacement.at(n.first).newvar; + } else if (in->is_constant()) { + return in; + } + // else is op + auto ret_copy = std::make_shared(*in); + for (size_t idx = 0 ; idx < ret_copy->get_child_cnt(); ++ idx) { + ret_copy->child(idx) = + ReplacingRtlIlaVar( + ret_copy->get_child().at(idx)); + } // for each child } // AnnotateSignalsAndCollectRtlVars @@ -239,9 +118,11 @@ void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr & inout) { auto new_node = VExprAst::MakeVar(delay_name); if( inout->get_parameter().size() == 1 ) { + // Single a ##n int delay = inout->get_parameter().at(0); aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), delay) ); } else { // inout->get_parameter().size() == 2 + // RANGE/INF a ##[n,m] / ##[n,0] 0 represents $ int delay = inout->get_parameter().at(0); int delay_upper = inout->get_parameter().at(1); aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), delay, delay_upper) ); @@ -258,16 +139,19 @@ void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr & inout) { } } // collect_inline_delay_func +// will convert delay and @ to internal names +// but will not add type information +// will put in aux_delays +// and value_recorder void TypedVerilogRefinementMap::CollectInlineDelayValueHolder() { TraverseAllRfExpr([this](RfExpr & inout) -> void { this->collect_inline_delay_func(inout);} ); TraverseAllRfExpr([this](RfExpr & inout) -> void { this->collect_inline_value_recorder_func(inout);} ); } - -void TypedVerilogRefinementMap::CollectInternallyDefinedVars( - const std::string & ila_inst_decode_signal_name, - const std::string & ila_valid_signal_name -) { +// internal datastructure like +// phase_tracker, value_recorder, customized_monitor, aux_delay -> all_var_def_types +// +void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { for (const auto & n_st : phase_tracker) { for (const auto & var_def : n_st.second.event_alias ) { VarDef tmp; @@ -299,50 +183,14 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars( VarDef tmp; tmp.width = 1; tmp.type = VarDef::var_type::WIRE; - auto onebit_anno = std::make_shared(); - onebit_anno->type = RfMapVarType(1); - onebit_anno->var_ref_type = RfVarTypeOrig::VARTYPE::INTERNAL; all_var_def_types.emplace("decode", tmp); // these are the stage info all_var_def_types.emplace("commit", tmp); - // decode and commit stage replacement - var_replacement.emplace("decode", - VarReplacement( - verilog_expr::VExprAst::MakeSpecialName("decode"), - verilog_expr::VExprAst::MakeSpecialName("__START__") - )); - - var_replacement.emplace("commit", - VarReplacement( - verilog_expr::VExprAst::MakeSpecialName("commit"), - verilog_expr::VExprAst::MakeSpecialName("__IEND__") - )); - - var_replacement.at("decode").newvar->set_annotation(onebit_anno); - var_replacement.at("commit").newvar->set_annotation(onebit_anno); - all_var_def_types.emplace("$decode", tmp); // these are the ila.decode/ila.valid info all_var_def_types.emplace("$valid", tmp); - - // decode and commit stage replacement - var_replacement.emplace("$decode", - VarReplacement( - verilog_expr::VExprAst::MakeSpecialName("$decode"), - verilog_expr::VExprAst::MakeSpecialName(ila_inst_decode_signal_name) - )); - var_replacement.emplace("$valid", - VarReplacement( - verilog_expr::VExprAst::MakeSpecialName("commit"), - verilog_expr::VExprAst::MakeSpecialName(ila_valid_signal_name) - )); - - var_replacement.at("$decode").newvar->set_annotation(onebit_anno); - var_replacement.at("$valid").newvar->set_annotation(onebit_anno); - } // end of add decode,commit, $decode, $valid - } // CollectInternallyDefinedVars @@ -442,6 +290,7 @@ void TypedVerilogRefinementMap::TraverseRfExpr(RfExpr & inout, std::function= cnt) { parent_stack.pop_back(); if(!parent_stack.empty()) { + // refer to parent func( parent_stack.back().first->child( parent_stack.back().second ) ); ++ parent_stack.back().second; } @@ -477,7 +326,9 @@ bool _compute_const(const RfExpr & in, unsigned & out) { } - +// this does not rely on type annotation +// relies on TypeInferTravserRfExpr +// and therefore, all_var_def_types void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { for(auto & name_delay_pair: aux_delays) { if(name_delay_pair.second.width == 0) { @@ -512,6 +363,7 @@ void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { } // ComputeDelayValueHolderWidth +// relies on typechecker and all_var_def_types RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in) { if(in->is_constant()) { @@ -524,8 +376,11 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in if(n.second) { // is a special name // check special name first - if (pos_def_var != all_var_def_types.end()) - return RfMapVarType(pos_def_var->second.width); + if (pos_def_var != all_var_def_types.end()) { + ILA_WARN_IF(pos_def_var->second.width == 0) << "Using width of not yet" + << " determined var " << n.first; + return RfMapVarType(pos_def_var->second.width); + } RfVarTypeOrig rtl_ila_vartype = typechecker(n.first); if (!rtl_ila_vartype.type.is_unknown()) @@ -537,8 +392,11 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in RfVarTypeOrig rtl_ila_vartype = typechecker(n.first); if (!rtl_ila_vartype.type.is_unknown()) return rtl_ila_vartype.type; - if (pos_def_var != all_var_def_types.end()) + if (pos_def_var != all_var_def_types.end()) { + ILA_WARN_IF(pos_def_var->second.width == 0) << "Using width of not yet" + << " determined var " << n.first; return RfMapVarType(pos_def_var->second.width); + } } // if # ... # else not return RfMapVarType(); // unknown type @@ -699,6 +557,30 @@ void RfExprAstUtility::GetVars(const RfExpr & in, } // end while (stack is not empty) } // end of GetVars + +bool RfExprAstUtility::HasArrayVar( + const RfExpr & in, std::map & array_var) +{ + if(in->is_var()) { + auto anno = in->get_annotation(); + ILA_NOT_NULL(anno); + auto memvar = std::dynamic_pointer_cast(in); + ILA_NOT_NULL(memvar); + if(anno->type.is_array()) { + array_var.emplace(std::get<0>(memvar->get_name()), memvar); + return true; + } + return false; + } else if (in->is_constant()) { + return false; + } + bool has_array = false; + for (size_t idx = 0; idx < in->get_child_cnt(); idx ++) { + has_array = has_array || HasArrayVar(in->child(idx), array_var); + } + return has_array; +} + bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr & in) { std::set boolean_op = { verilog_expr::voperator::GTE, @@ -717,7 +599,7 @@ bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr & in) { if(in->is_constant() || in->is_var()) return false; auto op = in->get_op(); - return (boolean_op.find(op) == boolean_op.end()); + return (boolean_op.find(op) != boolean_op.end()); } @@ -729,18 +611,12 @@ bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr & in) { // differences from TypedVerilogRefinementMap::ReplacingRtlIlaVar // 1. no var replacement (__ILA_I_, __ILA_SO_, __DOT__), array[idx] // 2. no special name handling +// 3. this is used only in unit test void TypeAnalysisUtility::AnnotateType(const RfExpr & inout) { auto tp_annotate = inout->get_annotation(); - +#error "modify smt expr out test" if(inout->is_var()) { - auto var_ptr = std::dynamic_pointer_cast(inout); - ILA_NOT_NULL(var_ptr); - auto n = var_ptr->get_name(); - - if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { - auto rtl_ila_tp = typechecker(n.first); - inout->set_annotation(std::make_shared(rtl_ila_tp)); - } + ILA_ASSERT(tp_annotate != nullptr && !tp_annotate->type.is_unknown()); } else if (inout->is_constant()) { if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { RfVarTypeOrig tp; @@ -915,6 +791,16 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr & inout) { } // infer_type_op + +VarReplacement:: VarReplacement(const RfExpr & o, const RfExpr & n) : + origvar(o), newvar(n) +{ + auto annotation_ptr = newvar->get_annotation(); + ILA_NOT_NULL(annotation_ptr); + ILA_CHECK(!annotation_ptr->type.is_unknown()) << + "new var is not typed: " << newvar->to_verilog() ; +} + } // namespace rfmap } // namespace ilang diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 7f47ba6d1..f5e58cab3 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -83,16 +83,19 @@ RfExpr VerilogRefinementMap::ParseRfExprFromString(const std::string & in) { intp.switchInputStream(&ss); try{ intp.parse(); - return intp.GetAstRoot(); } catch (verilog_expr::VexpException &e) { - + return nullptr; } - return nullptr; + + if(intp.HasError()) + return nullptr; + return intp.GetAstRoot(); } RfExpr ParseRfMapExpr(const std::string & in) { // TODO auto ret = VerilogRefinementMap::ParseRfExprFromString(in); + ILA_ERROR_IF(ret == nullptr) << "Parsing string: `" << in << "` failed."; if (ret == nullptr) ParseRfExprErrFlag = true; return ret; @@ -154,7 +157,7 @@ bool JsonRfmapParseMem(ExternalMemPortMap & mem_rfmap , nlohmann::json & json_ob char inline to_space(char in) { return ( (in == '-' || in == '_') ? ' ' : in); } -bool SecionNameRelaxedMatch(const std::string & in1, const std::string & in2) { +bool SectionNameRelaxedMatch(const std::string & in1, const std::string & in2) { if(in1.length() != in2.length()) return false; for (size_t idx = 0; idx < in1.length(); ++ idx) { @@ -163,7 +166,7 @@ bool SecionNameRelaxedMatch(const std::string & in1, const std::string & in2) { return false; } return true; -} // SecionNameRelaxedMatch +} // SectionNameRelaxedMatch nlohmann::json * GetJsonSection(nlohmann::json & in, const std::set & sec_names, bool allow_dup = false) { nlohmann::json * ret = NULL; @@ -171,13 +174,13 @@ nlohmann::json * GetJsonSection(nlohmann::json & in, const std::set return NULL; for (const auto & n : sec_names) { for (const auto & n_v : in.items() ) { - if ( SecionNameRelaxedMatch(n_v.key(), n) ) { + if ( SectionNameRelaxedMatch(n_v.key(), n) ) { ILA_ERROR_IF(ret) << "Section " << n << " is duplicated."; if (ret && !allow_dup) return NULL; - ret = &(in[n]); + ret = &(in.at(n_v.key())); } } } @@ -366,9 +369,9 @@ std::string JsonRfMapParseVarDefs(std::mapis_string(), "`defs` field should be list of [name, width, type]"); auto tp = pos->get(); - ENSURE( SecionNameRelaxedMatch(tp, "reg") || SecionNameRelaxedMatch(tp, "wire") , "`defs` field should be list of [name, width, type (wire/reg)]" ); + ENSURE( SectionNameRelaxedMatch(tp, "reg") || SectionNameRelaxedMatch(tp, "wire") , "`defs` field should be list of [name, width, type (wire/reg)]" ); - var_defs[var_name].type = SecionNameRelaxedMatch(tp, "reg") ? + var_defs[var_name].type = SectionNameRelaxedMatch(tp, "reg") ? GeneralVerilogMonitor::VarDef::var_type::REG : GeneralVerilogMonitor::VarDef::var_type::WIRE; ++ pos; @@ -533,7 +536,7 @@ VerilogRefinementMap::VerilogRefinementMap } else if (i.value().begin()->is_array() ) { are_memports = false; } else - ERRIF(true, "Expecting array of list or objects for" + sname); + ERRIF(true, "Expecting array of list or objects for " + sname); if (are_memports) { svmp.type = IlaVarMapping::StateVarMapType::EXTERNMEM; @@ -679,7 +682,8 @@ VerilogRefinementMap::VerilogRefinementMap if (cycle) { ENSURE(cycle->is_number_unsigned(), "cycles in reset should be unsigned integer"); reset_specification.reset_cycle = cycle->get(); - } + } else + reset_specification.reset_cycle = 1; if (customreset) { bool succ = JsonRfmapParseSequence(reset_specification.custom_reset_sequence, *customreset); @@ -781,11 +785,11 @@ VerilogRefinementMap::VerilogRefinementMap if(template_field) { ENSURE(template_field->is_string(), "`template` field should be string"); auto template_name = template_field->get(); - if(SecionNameRelaxedMatch(template_name,"phase tracker")) { + if(SectionNameRelaxedMatch(template_name,"phase tracker")) { phase_tracker.emplace(name, PhaseTracker()); std::string errmsg = JsonRfmapParsePhaseTracker(phase_tracker.at(name), monitor); ENSURE(errmsg.empty(), errmsg); - } else if (SecionNameRelaxedMatch(template_name,"value recorder")) { + } else if (SectionNameRelaxedMatch(template_name,"value recorder")) { value_recorder.emplace(name, ValueRecorder()); std::string errmsg = JsonRfmapParseValueRecorder(value_recorder.at(name), monitor); ENSURE(errmsg.empty(), errmsg); diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index adccfed75..0c5910318 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -13,6 +13,8 @@ #include #include +#include + namespace ilang { #define VLG_TRUE "`true" @@ -203,245 +205,351 @@ rfmap::RfVarTypeOrig VlgSglTgtGen::VarTypeCheckForRfExprParsing(const std::strin return rfmap::RfVarTypeOrig(); // unknown } // VarTypeCheckForRfExprParsing -std::string VlgSglTgtGen::ReplExpr(const rfmap::RfExpr & in) { +rfmap::VarReplacement VlgSglTgtGen::CreateVarReplacement( + const rfmap::RfVar & var, bool replace_internal_names) +{ + const auto n = var->get_name(); + + rfmap::RfVarTypeOrig tp; + { // retrieve its old type + auto anno = var->get_annotation(); + if(anno) + tp = *anno; + } + + auto pos_def_var = refinement_map.all_var_def_types.find(n.first); + auto rtl_ila_tp = VarTypeCheckForRfExprParsing(n.first); + if(n.second) { // if it is special name + if(pos_def_var != refinement_map.all_var_def_types.end()) { + tp.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR; + tp.type = rfmap::RfMapVarType(pos_def_var->second.width); + } else { + tp = rtl_ila_tp; + } + } else { // if it is not special name + if(!rtl_ila_tp.type.is_unknown()) + tp = rtl_ila_tp; + else if(pos_def_var != refinement_map.all_var_def_types.end()) { + tp.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR; + tp.type = rfmap::RfMapVarType(pos_def_var->second.width); + } + } + ILA_WARN_IF(tp.type.is_unknown()) << "type of var: " << (n.second?"#":"") << n.first << " is still unknown."; + + if(tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::RTLV) { + + bool is_array = tp.type.is_array(); // you can never connect an array out + if(!replace_internal_names || is_array) { + auto ret_copy = std::make_shared(*var); + ret_copy->set_annotation(std::make_shared(tp)); + return rfmap::VarReplacement(var, ret_copy); + } + + auto new_name = ReplaceAll(n.first, ".", "__DOT__"); + auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); + new_node->set_annotation(std::make_shared(tp)); + return rfmap::VarReplacement(var, new_node); + + } else if (tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::ILAI) { + const auto & ila_sn = n.first; + auto dotpos = ila_sn.find('.'); + ILA_ASSERT(ila_sn.substr(0,dotpos+1) == "ILA."); + + auto new_name = "__ILA_I_" + ila_sn.substr(dotpos+1); + auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); + new_node->set_annotation(std::make_shared(tp)); + return rfmap::VarReplacement(var, new_node); + } else if (tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::ILAS) { + const auto & ila_sn = n.first; + auto dotpos = ila_sn.find('.'); + ILA_ASSERT(ila_sn.substr(0,dotpos+1) == "ILA."); + + auto new_name = "__ILA_SO_" + ila_sn.substr(dotpos+1); + auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); + new_node->set_annotation(std::make_shared(tp)); + return rfmap::VarReplacement(var, new_node); + } else if ( + tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::INTERNAL || + tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR + ) { + return rfmap::VarReplacement(var, var); + } + + ILA_ERROR << "Unknown how to replace var: " << n.first << " will keep it"; + auto ret_copy = std::make_shared(*var); + ret_copy->set_annotation(std::make_shared(tp)); + return rfmap::VarReplacement(var, ret_copy); +} + +rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr & in) { bool replace_dot = _backend != VlgSglTgtGen::backend_selector::JASPERGOLD; + + std::unordered_map vars; + refinement_map.GetVars(in, vars); + for (const auto & v : vars) { + rfmap::VarReplacement * repl = refinement_map.CheckReplacement(v.first); + if (repl == NULL) { + rfmap::VarReplacement new_repl = CreateVarReplacement(v.second, replace_dot); + + ILA_DLOG("gen_util.create_var_replacement") << new_repl.origvar->to_verilog() + << " --> " << new_repl.newvar->to_verilog(); + + refinement_map.RegisterInternalVariableWithMapping( + v.first, new_repl); + repl = refinement_map.CheckReplacement(v.first); + } + ILA_NOT_NULL(repl); + ILA_DLOG("gen_util.create_var_replacement") << repl->origvar->to_verilog() + << " --> " << repl->newvar->to_verilog(); + } - auto new_node = refinement_map.ReplacingRtlIlaVar(in, replace_dot); - return new_node->to_verilog(); + auto new_node = refinement_map.ReplacingRtlIlaVar(in); + refinement_map.AnnotateType(new_node); + return new_node; } -std::string VlgSglTgtGen::TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn) { +rfmap::RfExpr VlgSglTgtGen::TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn) { if(refinement_map.IsLastLevelBooleanOp(in)) - return ReplExpr(in); - auto vnode = verilog_expr::VExprAst::MakeVar("ILA."+ila_vn); - auto eq_node = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, vnode, in); - return ReplExpr(eq_node); + return in; + auto vnode = rfmap_var("ILA."+ila_vn); + auto eq_node = rfmap_eq(vnode, in); + return eq_node; } -std::string VlgSglTgtGen::condition_map_to_str( +rfmap::RfExpr VlgSglTgtGen::condition_map_to_rfexpr( const std::vector> & cond_map, const std::string & ila_state_name) { - std::vector all_mappings; - std::string prev_neg; // make sure it is a priority condition lists + std::vector all_mappings; + rfmap::RfExpr prev_neg; // make sure it is a priority condition lists for (const auto & cond_map_pair : cond_map) { - std::string cond_expr = ReplExpr(cond_map_pair.first); - std::string vmap_expr = TranslateMap(cond_map_pair.second, ila_state_name); - - all_mappings.push_back("~ (" + prev_neg + "(" + cond_expr + ") ) || (" + - vmap_expr + ")"); - prev_neg += "~(" + cond_expr + ")&&"; - } // end for each condition map item - ILA_ERROR_IF(all_mappings.empty()) << "Conditional map is empty!"; - auto map_str = "(" + Join(all_mappings, " )&&( ") + ")"; - return map_str; + rfmap::RfExpr cond = cond_map_pair.first; + if (prev_neg != nullptr) + cond = rfmap_and(prev_neg, cond); + rfmap::RfExpr single_map = TranslateMap(cond_map_pair.second, ila_state_name); + all_mappings.push_back( rfmap_imply(cond, single_map) ); + if (prev_neg == nullptr) + prev_neg = rfmap_not(cond); + else + prev_neg = rfmap_and(prev_neg, rfmap_not(cond)); + } // end of for each cond_map pair + ILA_CHECK(!all_mappings.empty()); + return rfmap_and(all_mappings); +} // end of condition_map_to_str + + +rfmap::RfExpr VlgSglTgtGen::condition_map_bv_to_rfexpr( + const std::vector> & cond_map) +{ + rfmap::RfExpr ret; + for(auto pos = cond_map.rbegin(); pos != cond_map.rend(); ++pos) { + if(ret == nullptr) + ret = pos->second; + else + ret = rfmap_ite(pos->first, pos->second, ret); + } + return ret; } // end of condition_map_to_str -std::string VlgSglTgtGen::non_mem_map_to_str( + +rfmap::RfExpr VlgSglTgtGen::singlemap_bv_to_rfexpr( + const rfmap::SingleVarMap & single_map) { + if(single_map.single_map != nullptr) { + return single_map.single_map; + } else { + return condition_map_bv_to_rfexpr(single_map.cond_map); + } // end map type +} + +rfmap::RfExpr VlgSglTgtGen::singlemap_to_rfexpr( const rfmap::SingleVarMap & single_map, const std::string & ila_state_name) { if(single_map.single_map != nullptr) { return (TranslateMap(single_map.single_map, ila_state_name)); } else { - auto map_str = condition_map_to_str( single_map.cond_map, ila_state_name); + auto map_str = condition_map_to_rfexpr( single_map.cond_map, ila_state_name); return (map_str); } // end map type } // non_mem_map_to_str +// compared to Gen_varmap_assumpt_assert +// problem_name, true_for_assumpt_false_for_assert +// prefix, suffix are all fixed +void VlgSglTgtGen::Gen_input_map_assumpt(const std::string& ila_input_name, + const rfmap::IlaVarMapping &imap, const std::string & problem_name) { + + bool is_mem = _host->input(ila_input_name)->is_mem(); + ILA_ERROR_IF(is_mem) << "Mem as input is not supported yet"; + + ILA_ERROR_IF(imap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) + << "ila sv " << ila_input_name << " cannot be mapped as external mem!"; + // NOTE: non_mem_map_to_str will use translate map + // but it should be able to distinguish input from state var + auto map_rfexpr = singlemap_to_rfexpr(imap.single_map, ila_input_name); + add_an_assumption(rfmap_imply(rfmap_var("decode"), map_rfexpr), problem_name); +} + void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, - const rfmap::IlaVarMapping &vmap, const std::string & problem_name, bool true_for_assumpt_false_for_assert, - const std::string & prefix, const std::string & suffix) { + const rfmap::IlaVarMapping &vmap, + const std::string & problem_name, + bool true_for_assumpt_false_for_assert) { // NOTE: prefix has ( ~ __START__ || ... // and suffix has .. ) #define ADD_CONSTR(p1) do{ \ if(true_for_assumpt_false_for_assert) \ - add_an_assumption(prefix + (p1) + suffix, problem_name); \ + add_an_assumption(rfmap_imply(rfmap_var("decode"), (p1) ), problem_name); \ else \ - add_an_assertion(prefix + (p1) + suffix, problem_name); \ + add_an_assertion(rfmap_imply(rfmap_var("commit"), (p1) ), problem_name); \ }while(0) bool is_mem = _host->state(ila_state_name)->is_mem(); - if(!is_mem) { - ILA_ERROR_IF(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) + if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { + ILA_ERROR_IF(!is_mem) << "ila sv " << ila_state_name << " is not memory!"; - auto map_str = non_mem_map_to_str(vmap.single_map, ila_state_name); + auto map_str = singlemap_to_rfexpr(vmap.single_map, ila_state_name); ADD_CONSTR(map_str); } else { - if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { + // if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { // TODO: (note: multiple ports!) // assume : START |-> // ( ila.ren && rtl.renexpr && (ila.raddr == rtl.raddrexpr) |-> // (ila.rdata === rtl.rdataexpr) ) - if(true_for_assumpt_false_for_assert) { - // mem read assumption - const auto & read_ports = vlg_ila.ila_rports.at(ila_state_name); - unsigned rfmap_node_idx = 0; - - for(const auto & rport : read_ports) { - const auto & ila_ren = rport.second.ren; - const auto & ila_raddr = rport.second.raddr; - const auto & ila_rdata = rport.second.rdata; - - while(!(vmap.externmem_map.at(rfmap_node_idx).rport_mapped) - && rfmap_node_idx < vmap.externmem_map.size()) - ++ rfmap_node_idx; - - ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) - <<"#ila.read-port=" << read_ports.size() << " does not match #rfmap.read-port" - <<", and this is a mismatch for sname:" << ila_state_name; - - const auto & rfmap_rport = vmap.externmem_map.at(rfmap_node_idx); - - auto rtl_ren = non_mem_map_to_str(rfmap_rport.ren_map, ila_state_name); - auto rtl_raddr = non_mem_map_to_str(rfmap_rport.raddr_map, ila_state_name); - auto rtl_rdata = non_mem_map_to_str(rfmap_rport.rdata_map, ila_state_name); - - auto constr = "~(" + ila_ren + "&&(" + rtl_ren + ")&&(" + ila_raddr + "==(" + rtl_raddr +"))) || "; - constr += "(" + ila_rdata + "==(" + rtl_rdata+"))"; - ADD_CONSTR(constr); - - ++ rfmap_node_idx; - - } // for each read port - - } else { - // assert : IEND |-> - // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> - // (ila.wdata_d1 == rtl.wdataexpr) && (ila.waddr_d1 == rtl.waddrexpr) ) ) - - // mem write assertion - // vlg_ila.ila_wports - const auto & write_ports = vlg_ila.ila_wports.at(ila_state_name); - unsigned rfmap_node_idx = 0; - - for(const auto & wport : write_ports) { - // the reason for _d1: see ConstructWrapper_get_ila_module_inst - // in single_target_connect.cc - const auto & ila_wen = wport.second.wen + "_d1"; - const auto & ila_waddr = wport.second.waddr + "_d1"; - const auto & ila_wdata = wport.second.wdata + "_d1"; - - while(!(vmap.externmem_map.at(rfmap_node_idx).wport_mapped) - && rfmap_node_idx < vmap.externmem_map.size()) - ++ rfmap_node_idx; - - ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) - <<"#ila.write-port=" << write_ports.size() << " does not match #rfmap.write-port" - <<", and this is a mismatch for sname:" << ila_state_name; - - const auto & rfmap_wport = vmap.externmem_map.at(rfmap_node_idx); - - auto rtl_wen = non_mem_map_to_str(rfmap_wport.wen_map, ila_state_name); - auto rtl_waddr = non_mem_map_to_str(rfmap_wport.waddr_map, ila_state_name); - auto rtl_wdata = non_mem_map_to_str(rfmap_wport.wdata_map, ila_state_name); - - auto constr = "("+ila_wen + "==(" + rtl_wen+")) &&( ~" + ila_wen - +"||(" + ila_waddr +"==("+rtl_waddr+") && " +ila_wdata +"==("+ rtl_wdata +")" +"))"; - ADD_CONSTR(constr); - - ++ rfmap_node_idx; - } // for each write port - } // end of if assume else assert - } // end of extern mem - else { // the case when internal mem - bool is_jg = _backend == backend_selector::JASPERGOLD; - bool is_pono = _backend == backend_selector::PONO; - if(is_jg) { - // same as non-mem var + if(true_for_assumpt_false_for_assert) { + // mem read assumption + const auto & read_ports = vlg_ila.ila_rports.at(ila_state_name); + unsigned rfmap_node_idx = 0; + + for(const auto & rport : read_ports) { + auto ila_ren = rfmap_var(rport.second.ren); + auto ila_raddr = rfmap_var(rport.second.raddr); + auto ila_rdata = rfmap_var(rport.second.rdata); + + while(!(vmap.externmem_map.at(rfmap_node_idx).rport_mapped) + && rfmap_node_idx < vmap.externmem_map.size()) + ++ rfmap_node_idx; + + ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) + <<"#ila.read-port=" << read_ports.size() << " does not match #rfmap.read-port" + <<", and this is a mismatch for sname:" << ila_state_name; - if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::SINGLE) { - ADD_CONSTR(TranslateMap(vmap.single_map.single_map, ila_state_name)); - } else if (vmap.type == rfmap::IlaVarMapping::StateVarMapType::CONDITIONAL) { - std::vector all_mappings; - std::string prev_neg; // make sure it is a priority condition lists - for (const auto & cond_map_pair : vmap.single_map.cond_map) { - std::string cond_expr = ReplExpr(cond_map_pair.first); - std::string vmap_expr = TranslateMap(cond_map_pair.second, ila_state_name); - - all_mappings.push_back("~ (" + prev_neg + "(" + cond_expr + ") ) || (" + - vmap_expr + ")"); - prev_neg += "~(" + cond_expr + ")&&"; - } // end for each condition map item - ILA_ERROR_IF(all_mappings.empty()) << "Conditional map is empty!"; - auto map_str = "(" + Join(all_mappings, " )&&( ") + ")"; - ADD_CONSTR(map_str); - } // end map type - - } else { - //TODO: to smt-lib2 - ILA_CHECK(is_pono) << "Only PONO/JG backend can handle array eq property"; + const auto & rfmap_rport = vmap.externmem_map.at(rfmap_node_idx); - rfmap::RfExpr mem_map; - if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::SINGLE) - mem_map = vmap.single_map.single_map; - else { - std::vector all_mappings; - rfmap::RfExpr prev_neg; // make sure it is a priority condition lists - for (const auto & cond_map_pair : vmap.single_map.cond_map) { - rfmap::RfExpr cond = cond_map_pair.first; - if (prev_neg != nullptr) - cond = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, prev_neg, cond); - rfmap::RfExpr single_mem_map = refinement_map.IsLastLevelBooleanOp(cond_map_pair.second) ? - cond_map_pair.second : ( - verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, - cond_map_pair.second, - verilog_expr::VExprAst::MakeVar("ILA."+ila_state_name)) - ); - all_mappings.push_back( - verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_OR, - verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, cond), - single_mem_map)); - if (prev_neg == nullptr) - prev_neg = verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, cond); - else - prev_neg = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, prev_neg, - verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, cond)); - } // end of for each cond_map pair - ILA_CHECK(!all_mappings.empty()); - mem_map = all_mappings.at(0); - for (size_t idx = 1; idx < all_mappings.size(); ++ idx) - mem_map = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, - mem_map, all_mappings.at(idx)); - } // end of else (if condmap) + // expect bit-vector rather than booleans + auto rtl_ren = singlemap_bv_to_rfexpr(rfmap_rport.ren_map); + auto rtl_raddr = singlemap_bv_to_rfexpr(rfmap_rport.raddr_map); + auto rtl_rdata = singlemap_bv_to_rfexpr(rfmap_rport.rdata_map); - rfmap::RfExpr start_or_end = true_for_assumpt_false_for_assert ? - verilog_expr::VExprAst::MakeSpecialName("decode") : - verilog_expr::VExprAst::MakeSpecialName("commit"); + auto constr = rfmap_imply( rfmap_and( + {ila_ren, rtl_ren, rfmap_eq(ila_raddr, rtl_raddr)}), + rfmap_eq(ila_rdata, rtl_rdata)); + + ADD_CONSTR(constr); + + ++ rfmap_node_idx; + + } // for each read port + + } else { + // assert : IEND |-> + // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> + // (ila.wdata_d1 == rtl.wdataexpr) && (ila.waddr_d1 == rtl.waddrexpr) ) ) + + // mem write assertion + // vlg_ila.ila_wports + const auto & write_ports = vlg_ila.ila_wports.at(ila_state_name); + unsigned rfmap_node_idx = 0; + + for(const auto & wport : write_ports) { + // the reason for _d1: see ConstructWrapper_get_ila_module_inst + // in single_target_connect.cc + auto ila_wen = rfmap_var(wport.second.wen + "_d1"); + auto ila_waddr = rfmap_var(wport.second.waddr + "_d1"); + auto ila_wdata = rfmap_var(wport.second.wdata + "_d1"); + + while(!(vmap.externmem_map.at(rfmap_node_idx).wport_mapped) + && rfmap_node_idx < vmap.externmem_map.size()) + ++ rfmap_node_idx; + + ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) + <<"#ila.write-port=" << write_ports.size() << " does not match #rfmap.write-port" + <<", and this is a mismatch for sname:" << ila_state_name; - mem_map = /* ~start_or_end || (mem_map) */ - verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_OR, - verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, start_or_end), - mem_map); - - auto var_replaced_mem_map = refinement_map.ReplacingRtlIlaVar(mem_map, is_pono /*true*/); - // get var/type - // convert to smt-lib2 - std::unordered_map vars_in_map; - refinement_map.GetVars(var_replaced_mem_map, vars_in_map); + const auto & rfmap_wport = vmap.externmem_map.at(rfmap_node_idx); - if(true_for_assumpt_false_for_assert) - add_smt_assumption(vars_in_map, mem_map, problem_name); - else - add_smt_assertion(vars_in_map, mem_map, problem_name); - } // end of is_jg / else - } // end of is_extmem / else - } // end for memory-case - + auto rtl_wen = singlemap_bv_to_rfexpr(rfmap_wport.wen_map); + auto rtl_waddr = singlemap_bv_to_rfexpr(rfmap_wport.waddr_map); + auto rtl_wdata = singlemap_bv_to_rfexpr(rfmap_wport.wdata_map); + + auto constr = + rfmap_and( + rfmap_eq(ila_wen , rtl_wen), + rfmap_imply(ila_wen, + rfmap_and( + rfmap_eq(ila_waddr, rtl_waddr), + rfmap_eq(ila_wdata, rtl_wdata)))); + + ADD_CONSTR(constr); + + ++ rfmap_node_idx; + } // for each write port + } // end of if assume else assert + } #undef ADD_CONSTR } // end of Gen_varmap_assumpt_assert void VlgSglTgtGen::handle_start_condition(const std::vector & dc) { for (const auto & c : dc) { - auto cond = ReplExpr(c); //cond = ReplaceAll(ReplaceAll(cond, "$decode", vlg_ila.decodeNames[0]), // "$valid", vlg_ila.validName); - add_an_assumption("(~ __START__) || (" + cond +")", "start_condition"); + add_an_assumption( + rfmap_imply(rfmap_var("__START__"), c), "start_condition"); } } // handle_start_condition + +/// register a reg in refinement_map.all_var_def_type +void VlgSglTgtGen::rfmap_add_internal_reg(const std::string &n, unsigned width) { + rfmap::TypedVerilogRefinementMap::VarDef def; + def.type = rfmap::TypedVerilogRefinementMap::VarDef::var_type::REG; + def.width = width; + refinement_map.all_var_def_types.emplace(n, def); +} + +/// register a wire in refinement_map.all_var_def_type +void VlgSglTgtGen::rfmap_add_internal_wire(const std::string &n, unsigned width) { + rfmap::TypedVerilogRefinementMap::VarDef def; + def.type = rfmap::TypedVerilogRefinementMap::VarDef::var_type::WIRE; + def.width = width; + refinement_map.all_var_def_types.emplace(n, def); +} + +/// register a replacement in refinement_map +/// this will affect ReplExpr's behavior +/// (Note 1: ReplExpr will also create replacement, but it will not use +/// this function. 2: will require that the new one has been registered +/// in refinement_map.all_var_def_type) +/// should only be used to add +/// decode -> __START__ +/// commit -> __IEND__ +/// $decode -> vlg_ila.decode_signal +/// $valid -> vlg_ila.valid_signal + +void VlgSglTgtGen::rfmap_add_replacement(const std::string &old, const std::string &n) { + auto def_pos = refinement_map.all_var_def_types.find(n); + ILA_CHECK(def_pos != refinement_map.all_var_def_types.end()); + auto oldexpr = rfmap_var(old); + auto newexpr = rfmap_var(n); + auto tp = std::make_shared(); + tp->type = rfmap::RfMapVarType(def_pos->second.width); + tp->var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::INTERNAL; + newexpr->set_annotation(tp); + refinement_map.RegisterInternalVariableWithMapping( + old, rfmap::VarReplacement(oldexpr, newexpr)); +} // rfmap_add_replacement + }; // namespace ilang diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index df9ed6adc..ff2bb1aea 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -84,9 +84,7 @@ VlgSglTgtGen::VlgSglTgtGen( // ref to refmaps refinement_map(refinement, /*type checker*/ [this](const std::string& n) -> rfmap::RfVarTypeOrig { - return this->VarTypeCheckForRfExprParsing(n); }, - vlg_ila.GetDecodeSignalName(instr_ptr), - vlg_ila.GetValidSignalName(instr_ptr)), + return this->VarTypeCheckForRfExprParsing(n); }), target_type(target_tp), // whether it is // invariant/instructions @@ -171,9 +169,9 @@ void VlgSglTgtGen::ConstructWrapper_add_inputmap_assumptions() { continue; } ila_input_names.erase(iname); - } - + Gen_input_map_assumpt(iname, iv_rfmap.second, "variable_map_assume_"); + } if(!ila_input_names.empty()) { ILA_ERROR << "Lack input var map for the following variables:"; @@ -211,12 +209,7 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assumptions() { std::string problem_name = "variable_map_assume_"; - if (_backend == backend_selector::RELCHC) { - Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, true, "", "" ); - // its signal reference will be replaced, but this should be fine - // because the names on any level is the same! - } else - Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, true, "(~ __START__ )|| (", ")" ); + Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, true ); } // end for each state variable ILA_DLOG("VtargetGen") << "STEP:" @@ -269,13 +262,6 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { << _instr_ptr->name().str() << " updating state:" << sname << " is not provided in rfmap!"; } - // ISSUE ==> vmap - std::string precondition = "(~ __IEND__) || "; - - if (IN(sname, vlg_ila.state_update_ite_unknown)) { - auto pos = vlg_ila.state_update_ite_unknown.find(sname); - precondition += "(~ " + pos->second.condition + ") ||"; - } std::string problem_name = "variable_map_assert"; // for Yosys, we must keep the name the same @@ -288,7 +274,7 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { // for Yosys inv-synthesis, we don't mind the precondition // that's part the assertions, so it should be fine - Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, false, "(~ __IEND__ )|| (", ")" ); + Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, false); } // end - for each state var } // ConstructWrapper_add_varmap_assertions @@ -315,8 +301,21 @@ void VlgSglTgtGen::ConstructWrapper() { ConstructWrapper_generate_header(); ILA_DLOG("VtargetGen") << "STEP:" << 2; + if (target_type != target_type_t::INSTRUCTIONS) + max_bound = _vtg_config.MaxBound; + + // if invariants, will do nothing + if (target_type == target_type_t::INSTRUCTIONS) { + // __CYCLE_CNT__, START RESETED and etc. + ConstructWrapper_add_cycle_count_moniter(); + // IEND ENDCOND and etc. (will use cycle count) + ConstructWrapper_add_condition_signals(); + } else + ConstructWrapper_inv_syn_cond_signals(); + + // 1. dealing with reset - ConstructWrapper_reset_setup(); + ConstructWrapper_reset_setup(); // will use __RESETED__ ILA_DLOG("VtargetGen") << "STEP:" << 3; // -- find out the inputs @@ -325,25 +324,8 @@ void VlgSglTgtGen::ConstructWrapper() { ConstructWrapper_add_ila_input(); ILA_DLOG("VtargetGen") << "STEP:" << 5; - // 2. add some monitors (bound cnt) - // 3. add assumptions & assertions - if (target_type == target_type_t::INSTRUCTIONS) { - - ILA_DLOG("VtargetGen") << "STEP:" << 5.1; - ConstructWrapper_add_cycle_count_moniter(); - ILA_DLOG("VtargetGen") << "STEP:" << 5.2; - ConstructWrapper_add_varmap_assumptions(); - ILA_DLOG("VtargetGen") << "STEP:" << 5.3; - ConstructWrapper_add_varmap_assertions(); - ILA_DLOG("VtargetGen") << "STEP:" << 5.4; - ConstructWrapper_add_inv_assumption_or_assertion_target_instruction(); - } else if (target_type == target_type_t::INVARIANTS) { - ConstructWrapper_add_inv_assumption_or_assertion_target_invariant(); - max_bound = _vtg_config.MaxBound; - } else if (target_type == target_type_t::INV_SYN_DESIGN_ONLY) { - ConstructWrapper_inv_syn_cond_signals(); + if (target_type == target_type_t::INV_SYN_DESIGN_ONLY) ConstructWrapper_add_inv_assumption_or_assertion_target_inv_syn_design_only(); - } ILA_DLOG("VtargetGen") << "STEP:" << 6; // 4. additional mapping if any @@ -352,17 +334,9 @@ void VlgSglTgtGen::ConstructWrapper() { ConstructWrapper_add_rf_assumptions(); - ILA_DLOG("VtargetGen") << "STEP:" << 7; - // if invariants, will do nothing - if (target_type == target_type_t::INSTRUCTIONS) - ConstructWrapper_add_condition_signals(); ILA_DLOG("VtargetGen") << "STEP:" << 8; - // 7. uni-functions - if (target_type == target_type_t::INSTRUCTIONS) - ConstructWrapper_add_uf_constraints(); - // post value holder --- ABC cannot work on this if (target_type == target_type_t::INSTRUCTIONS) { ConstructWrapper_add_post_value_holder(); @@ -381,7 +355,25 @@ void VlgSglTgtGen::ConstructWrapper() { ILA_DLOG("VtargetGen") << "STEP:" << 9; // 5. module instantiation ConstructWrapper_add_module_instantiation(); -} + + // 7. uni-functions + if (target_type == target_type_t::INSTRUCTIONS) + ConstructWrapper_add_uf_constraints(); + + // 2. add some monitors (bound cnt) + // 3. add assumptions & assertions + if (target_type == target_type_t::INSTRUCTIONS) { + + ILA_DLOG("VtargetGen") << "STEP:" << 5.2; + ConstructWrapper_add_varmap_assumptions(); + ILA_DLOG("VtargetGen") << "STEP:" << 5.3; + ConstructWrapper_add_varmap_assertions(); + ILA_DLOG("VtargetGen") << "STEP:" << 5.4; + ConstructWrapper_add_inv_assumption_or_assertion_target_instruction(); + } if (target_type == target_type_t::INVARIANTS) { + ConstructWrapper_add_inv_assumption_or_assertion_target_invariant(); + } +} // Construct_wrapper /// create the wrapper file void VlgSglTgtGen::Export_wrapper(const std::string& wrapper_name) { diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index f91b04c08..e9b27ee2f 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -16,48 +16,18 @@ #include #include #include +#include namespace ilang { -void VlgSglTgtGen::add_wire_assign_assumption(const std::string& varname, - const std::string& expression, - const std::string& dspt) { - //_problems.assumptions.push_back(varname + " = " + - // convert_expr_to_cosa(expression)); - vlg_wrapper.add_assign_stmt(varname, expression); - ILA_CHECK(_vtg_config.PonoDotReferenceNotify != - vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_PANIC || - expression.find(".") == std::string::npos) - << "expression:" << expression << " contains unfriendly dot."; - ILA_WARN_IF(_vtg_config.PonoDotReferenceNotify == - vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_WARNING && - expression.find(".") != std::string::npos) - << "expression:" << expression << " contains unfriendly dot."; -} +// NOTE: add_an_assumption, add_an_assertion are not defined in base class void VlgSglTgtGen::add_reg_cassign_assumption(const std::string& varname, - const std::string& expression, + const rfmap::RfExpr& expression, int width, - const std::string& cond, + const rfmap::RfExpr& cond, const std::string& dspt) { - // vlg_wrapper.add_always_stmt(varname + " <= " + varname + ";"); - // _problems.assumptions.push_back("(!( " + convert_expr_to_cosa(cond) + - // " ) | (" + varname + " = " + - // convert_expr_to_cosa(expression) + "))"); - - ILA_CHECK(_vtg_config.PonoDotReferenceNotify != - vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_PANIC || - expression.find(".") == std::string::npos) - << "expression:" << expression << " contains unfriendly dot."; - - ILA_WARN_IF(_vtg_config.PonoDotReferenceNotify == - vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_WARNING && - expression.find(".") != std::string::npos) - << "expression:" << expression << " contains unfriendly dot."; - - // vlg_wrapper.add_always_stmt("if (" + cond + ") " + varname + - // " <= " + expression + "; //" + dspt); - // we prefer the following way, as we get the value instantaneously + std::string rand_in_name = "__" + varname + "_init__"; vlg_wrapper.add_input(rand_in_name, width); vlg_wrapper.add_wire(rand_in_name, width); @@ -65,63 +35,17 @@ void VlgSglTgtGen::add_reg_cassign_assumption(const std::string& varname, vlg_wrapper.add_init_stmt(varname + " <= " + rand_in_name + ";"); vlg_wrapper.add_always_stmt(varname + " <= " + varname + ";"); add_an_assumption( - "(~(" + cond + ") || ((" + varname + ") == (" + expression + ")))", dspt); -} - -/// Add an assumption -void VlgSglTgtGen::add_an_assumption(const std::string& aspt, - const std::string& dspt) { - auto assumption_wire_name = vlg_wrapper.sanitizeName(dspt) + new_mapping_id(); - vlg_wrapper.add_wire(assumption_wire_name, 1, true); - vlg_wrapper.add_output(assumption_wire_name, - 1); // I find it is necessary to connect to the output - - ILA_CHECK(_vtg_config.PonoDotReferenceNotify != - vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_PANIC || - aspt.find(".") == std::string::npos) - << "aspt:" << aspt << " contains unfriendly dot."; - - ILA_WARN_IF(_vtg_config.PonoDotReferenceNotify == - vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_WARNING && - aspt.find(".") != std::string::npos) - << "aspt:" << aspt << " contains unfriendly dot."; - - vlg_wrapper.add_assign_stmt(assumption_wire_name, aspt); - add_a_direct_assumption( - assumption_wire_name, - dspt); -} // add_an_assumption - -/// Add an assertion -void VlgSglTgtGen::add_an_assertion(const std::string& asst, - const std::string& dspt) { - auto assrt_wire_name = vlg_wrapper.sanitizeName(dspt) + new_property_id(); - vlg_wrapper.add_wire(assrt_wire_name, 1, true); - vlg_wrapper.add_output(assrt_wire_name, - 1); // I find it is necessary to connect to the output - vlg_wrapper.add_assign_stmt(assrt_wire_name, asst); - add_a_direct_assertion( - assrt_wire_name, - dspt); - ILA_CHECK(_vtg_config.PonoDotReferenceNotify != - vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_PANIC || - asst.find(".") == std::string::npos) - << "asst:" << asst << " contains unfriendly dot."; - ILA_WARN_IF(_vtg_config.PonoDotReferenceNotify == - vtg_config_t::PonoDotReferenceNotify_t::NOTIFY_WARNING && - asst.find(".") != std::string::npos) - << "asst:" << asst << " contains unfriendly dot."; - - //_problems.probitem[dspt].assertions.push_back(convert_expr_to_cosa(asst)); -} // add_an_assertion - + rfmap_imply(cond, rfmap_eq(rfmap_var(varname), expression)), dspt); +} // add_reg_cassign_assumption void VlgSglTgtGen::add_smt_assumption( - const std::unordered_map & vars, const rfmap::RfExpr & body, const std::string & dspt) -{ +{ + std::unordered_map vars; + rfmap::RfExprAstUtility::GetVars(body, vars); + std::string body_smt2 = rfmap::RfExpr2Smt::to_smt2(body, rfmap::SmtType() /*Bool type*/ ); std::vector arg; @@ -137,10 +61,12 @@ void VlgSglTgtGen::add_smt_assumption( // Add SMT assertion (using rfexpr) void VlgSglTgtGen::add_smt_assertion( - const std::unordered_map & vars, const rfmap::RfExpr & body, const std::string & dspt) { + std::unordered_map vars; + rfmap::RfExprAstUtility::GetVars(body, vars); + std::string body_smt2 = rfmap::RfExpr2Smt::to_smt2(body, rfmap::SmtType() /*Bool type*/ ); std::vector arg; @@ -154,4 +80,5 @@ void VlgSglTgtGen::add_smt_assertion( "("+Join(arg, " ")+")", "Bool", body_smt2, dspt); } + }; // namespace ilang diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index 1d9ba22bf..b191c6e9d 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -14,6 +14,8 @@ #include #include +#include + namespace ilang { // ------------- CONFIGURATIONS -------------------- // @@ -41,8 +43,13 @@ void VlgSglTgtGen::ConstructWrapper_reset_setup() { if (target_type == target_type_t::INSTRUCTIONS) { vlg_wrapper.add_input("dummy_reset", 1); vlg_wrapper.add_wire("dummy_reset", 1, true); - if (_vtg_config.InstructionNoReset) - add_an_assumption(" (~__RESETED__) || (dummy_reset == 0) ", "noreset"); + rfmap_add_internal_wire("dummy_reset", 1); + if (_vtg_config.InstructionNoReset) { + add_an_assumption( + rfmap_imply( + rfmap_var("__RESETED__"), + rfmap_not(rfmap_var("dummy_reset"))), "noreset"); + } } else if (target_type == target_type_t::INVARIANTS || target_type == target_type_t::INV_SYN_DESIGN_ONLY) { if (_vtg_config.InvariantCheckNoReset) { @@ -73,6 +80,8 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { cnt_width = (int)std::ceil(std::log2(max_bound + 20)); vlg_wrapper.add_reg("__CYCLE_CNT__", cnt_width); // by default it will be an output reg + rfmap_add_internal_reg("__CYCLE_CNT__", cnt_width); + vlg_wrapper.add_stmt("always @(posedge clk) begin"); vlg_wrapper.add_stmt("if (rst) __CYCLE_CNT__ <= 0;"); vlg_wrapper.add_stmt( @@ -81,6 +90,8 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { vlg_wrapper.add_stmt("end"); vlg_wrapper.add_reg("__START__", 1); + rfmap_add_internal_reg("__START__", 1); + rfmap_add_replacement("decode", "__START__"); vlg_wrapper.add_stmt("always @(posedge clk) begin"); // how start is triggered @@ -90,6 +101,7 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { vlg_wrapper.add_stmt("end"); vlg_wrapper.add_reg("__STARTED__", 1); + rfmap_add_internal_reg("__STARTED__", 1); vlg_wrapper.add_stmt("always @(posedge clk) begin"); vlg_wrapper.add_stmt("if (rst) __STARTED__ <= 0;"); vlg_wrapper.add_stmt( @@ -97,6 +109,7 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { vlg_wrapper.add_stmt("end"); vlg_wrapper.add_reg("__ENDED__", 1); + rfmap_add_internal_reg("__ENDED__", 1); vlg_wrapper.add_stmt("always @(posedge clk) begin"); vlg_wrapper.add_stmt("if (rst) __ENDED__ <= 0;"); vlg_wrapper.add_stmt( @@ -104,6 +117,7 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { vlg_wrapper.add_stmt("end"); vlg_wrapper.add_reg("__2ndENDED__", 1); + rfmap_add_internal_reg("__2ndENDED__", 1); vlg_wrapper.add_stmt("always @(posedge clk) begin"); vlg_wrapper.add_stmt("if (rst) __2ndENDED__ <= 1'b0;"); vlg_wrapper.add_stmt("else if (__ENDED__ && __EDCOND__ && ~__2ndENDED__) " @@ -114,6 +128,7 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { "__ENDED__ && __EDCOND__ && ~__2ndENDED__"); vlg_wrapper.add_reg("__RESETED__", 1); + rfmap_add_internal_reg("__RESETED__", 1); vlg_wrapper.add_stmt("always @(posedge clk) begin"); vlg_wrapper.add_stmt("if (rst) __RESETED__ <= 1;"); vlg_wrapper.add_stmt("end"); @@ -140,61 +155,71 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { // find the instruction const auto& instr = get_current_instruction_rf(); - // __IEND__ - std::string iend_cond = VLG_FALSE; + rfmap::RfExpr iend_cond; // bool no_started_signal = false; if(instr.is_readysignal()) { - iend_cond += "|| (" + ReplExpr(instr.ready_signal) + ")"; + iend_cond = instr.ready_signal ; } else { ILA_ASSERT(instr.is_readybound()); unsigned bound = instr.ready_bound; ILA_ERROR_IF(bound == 0) << "Does not support bound : 0, please use a buffer to hold " "the signal."; - iend_cond += "|| ( __CYCLE_CNT__ == " + IntToStr(cnt_width) + "'d" - + IntToStr(bound) + ")"; + iend_cond = rfmap_eq( rfmap_var("__CYCLE_CNT__") , rfmap_const(10, cnt_width, bound)); + // "( __CYCLE_CNT__ == " + IntToStr(cnt_width) + "'d" + // + IntToStr(bound) + ")"; } // max bound for max checking range - std::string max_bound_constr; + rfmap::RfExpr max_bound_constr; if(instr.max_bound != 0) { max_bound_constr = - "&& ( __CYCLE_CNT__ <= " + IntToStr(instr.max_bound) + ")"; + rfmap_le( rfmap_var("__CYCLE_CNT__"), rfmap_const(10, cnt_width, instr.max_bound)); + // "&& ( __CYCLE_CNT__ <= " + IntToStr(instr.max_bound) + ")"; } vlg_wrapper.add_wire("__IEND__", 1, true); vlg_wrapper.add_wire("__EDCOND__", 1, true); - // if(no_started_signal) - // add_wire_assign_assumption("__IEND__", "(" + iend_cond + ")", - // "IEND"); - // else - auto end_no_recur = "(~ __ENDED__)"; + + rfmap_add_internal_wire("__IEND__", 1); + rfmap_add_internal_wire("__EDCOND__", 1); + rfmap_add_replacement("commit", "__IEND__"); + + auto end_no_recur = rfmap_not( rfmap_var("__ENDED__") ); add_wire_assign_assumption("__EDCOND__", - "(" + iend_cond + ") && __STARTED__ ", "EDCOND"); + rfmap_and(iend_cond, rfmap_var("__STARTED__")), "EDCOND"); add_wire_assign_assumption("__IEND__", - "(" + iend_cond + - ") && __STARTED__ && __RESETED__ && " + - end_no_recur + max_bound_constr, + rfmap_and( + {iend_cond, + rfmap_var("__STARTED__"), + rfmap_var("__RESETED__"), + end_no_recur, + max_bound_constr + }), "IEND"); // handle start decode if (!instr.start_condition.empty()) { handle_start_condition(instr.start_condition); } else { - add_an_assumption("(~ __START__) || (" + vlg_ila.decodeNames[0] + ")", - "issue_decode"); // __ISSUE__ |=> decode - add_an_assumption("(~ __START__) || (" + vlg_ila.validName + ")", - "issue_valid"); // __ISSUE__ |=> decode + add_an_assumption( + rfmap_imply(rfmap_var("__START__"), rfmap_var("$decode")), + "issue_decode"); // __ISSUE__ |-> decode + add_an_assumption( + rfmap_imply(rfmap_var("__START__"), rfmap_var("$valid")), + "issue_valid"); // __ISSUE__ |-> valid } vlg_wrapper.add_wire("__ISSUE__", 1, true); + rfmap_add_internal_wire("__ISSUE__", 1); + if (_vtg_config.ForceInstCheckReset) { vlg_wrapper.add_input("__ISSUE__", 1); } else - add_wire_assign_assumption("__ISSUE__", "1", "ISSUE"); // issue ASAP + vlg_wrapper.add_assign_stmt("__ISSUE__", "1"); // start decode -- issue enforce (e.g. valid, input) } // ConstructWrapper_add_condition_signals diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index 1112929e0..9a70ff396 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -57,10 +57,13 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { target_type == target_type_t::INV_SYN_DESIGN_ONLY) return ""; - ILA_CHECK(vlg_ila.decodeNames.size() == 1) - << "Implementation bug: decode condition."; - vlg_wrapper.add_wire(vlg_ila.validName, 1, true); - vlg_wrapper.add_wire(vlg_ila.decodeNames[0], 1, true); + vlg_wrapper.add_wire(vlg_ila.GetValidSignalName(_instr_ptr), 1, true); + vlg_wrapper.add_wire(vlg_ila.GetDecodeSignalName(_instr_ptr), 1, true); + + rfmap_add_internal_wire(vlg_ila.GetValidSignalName(_instr_ptr), 1); + rfmap_add_internal_wire(vlg_ila.GetDecodeSignalName(_instr_ptr), 1); + rfmap_add_replacement("$decode", vlg_ila.GetDecodeSignalName(_instr_ptr)); + rfmap_add_replacement("$valid", vlg_ila.GetValidSignalName(_instr_ptr)); // TODO: check whether all ports have been dealt with // TODO: check whether there are any extra ports we create @@ -81,6 +84,7 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { port_connected.insert(port_name); vlg_wrapper.add_wire(port_name, 1, true); vlg_wrapper.add_output(port_name, 1); + rfmap_add_internal_wire(port_name, 1); retStr += " ." + port_name + "(" + port_name + "),\n"; } @@ -97,6 +101,7 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { func_app.func_name + "_" + IntToStr(func_no) + "_result_wire"; vlg_wrapper.add_wire(func_reg_w, func_app.result.second, true); + rfmap_add_internal_wire(func_reg_w, func_app.result.second); // add as a module input, also vlg_wrapper.add_input(func_reg_w, func_app.result.second); @@ -111,6 +116,7 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { "_arg" + IntToStr(argNo) + "_wire"; // this should be module output vlg_wrapper.add_wire(func_arg_w, arg.second, true); + rfmap_add_internal_wire(func_arg_w, arg.second); // vlg_wrapper.add_always_stmt( "if( __START__ ) " + func_arg + " <= " + // func_arg_w + ";" ); @@ -189,6 +195,9 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { // auto rew = "__IMEM_" + ila_name + "_" + IntToStr(no) + "_ren"; no need, // r_en is the start signal + rfmap_add_internal_wire(rdw, dw); + rfmap_add_internal_wire(raw, aw); + vlg_wrapper.add_wire(rdw, dw, true); vlg_wrapper.add_wire(raw, aw, true); @@ -225,11 +234,17 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { vlg_wrapper.add_wire(wdw, dw, true); vlg_wrapper.add_wire(waw, aw, true); vlg_wrapper.add_wire(wew, 1, true); + rfmap_add_internal_wire(wdw, dw); + rfmap_add_internal_wire(waw, aw); + rfmap_add_internal_wire(wew, 1); // latch the write signal vlg_wrapper.add_reg(wdw_delay, dw); vlg_wrapper.add_reg(waw_delay, aw); vlg_wrapper.add_reg(wew_delay, 1); + rfmap_add_internal_reg(wdw_delay, dw); + rfmap_add_internal_reg(waw_delay, aw); + rfmap_add_internal_reg(wew_delay, 1); vlg_wrapper.add_always_stmt("if (__START__) " + wdw_delay + " <= " + wdw + ";"); vlg_wrapper.add_always_stmt("if (__START__) " + waw_delay + " <= " + waw + ";"); vlg_wrapper.add_always_stmt("if (__START__) " + wew_delay + " <= " + wew + ";"); @@ -328,7 +343,7 @@ void VlgSglTgtGen::ConstructWrapper_register_extra_io_wire() { auto old_name = refered_vlg_item.second.get_orig_name(); auto new_name = refered_vlg_item.second.get_new_name(); - if(StrStartsWith(new_name, "__ILA_")) + if(!StrStartsWith(refered_vlg_item.first, "RTL.")) continue; auto idx = old_name.find("["); diff --git a/src/vtarget-out/single_target_inv_syn_support.cc b/src/vtarget-out/single_target_inv_syn_support.cc index 235403489..10bbd9868 100644 --- a/src/vtarget-out/single_target_inv_syn_support.cc +++ b/src/vtarget-out/single_target_inv_syn_support.cc @@ -15,6 +15,8 @@ #include #include +#include + namespace ilang { // ------------- CONFIGURATIONS -------------------- // @@ -72,20 +74,19 @@ void VlgSglTgtGen::add_inv_obj_as_assertion(InvariantObject* inv_obj) { for (auto&& name_expr_pair : inv_obj->GetExtraVarDefs()) { vlg_wrapper.add_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair), true); - vlg_wrapper.add_assign_stmt(std::get<0>(name_expr_pair), - ReplExpr( - refinement_map.ParseRfExprFromString( - std::get<1>(name_expr_pair)))); + rfmap_add_internal_wire(std::get<0>(name_expr_pair), + std::get<2>(name_expr_pair)); + add_wire_assign_assumption(std::get<0>(name_expr_pair), + refinement_map.ParseRfExprFromString( + std::get<1>(name_expr_pair)), "invariant_aux_var"); } for (auto&& name_w_pair : inv_obj->GetExtraFreeVarDefs()) { vlg_wrapper.add_wire(name_w_pair.first, name_w_pair.second, true); vlg_wrapper.add_input(name_w_pair.first, name_w_pair.second); } for (auto&& inv_expr : inv_obj->GetVlgConstraints()) { - auto new_cond = ReplExpr( - refinement_map.ParseRfExprFromString(inv_expr)); - ILA_CHECK(!S_IN("][", new_cond)) - << "Inv translate error: ][ found in:" << new_cond; + auto new_cond = + refinement_map.ParseRfExprFromString(inv_expr); add_an_assertion(new_cond, "invariant_assert"); } } // add_inv_obj_as_assertion @@ -95,19 +96,19 @@ void VlgSglTgtGen::add_inv_obj_as_assumption(InvariantObject* inv_obj) { for (auto&& name_expr_pair : inv_obj->GetExtraVarDefs()) { vlg_wrapper.add_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair), true); - vlg_wrapper.add_assign_stmt(std::get<0>(name_expr_pair), - ReplExpr( - refinement_map.ParseRfExprFromString(std::get<1>(name_expr_pair)))); + rfmap_add_internal_wire(std::get<0>(name_expr_pair), + std::get<2>(name_expr_pair)); + add_wire_assign_assumption(std::get<0>(name_expr_pair), + refinement_map.ParseRfExprFromString(std::get<1>(name_expr_pair)), + "invariant_aux_var"); } for (auto&& name_w_pair : inv_obj->GetExtraFreeVarDefs()) { vlg_wrapper.add_wire(name_w_pair.first, name_w_pair.second, true); vlg_wrapper.add_input(name_w_pair.first, name_w_pair.second); } for (auto&& inv_expr : inv_obj->GetVlgConstraints()) { - auto new_cond = ReplExpr( - refinement_map.ParseRfExprFromString(inv_expr)); - ILA_CHECK(!S_IN("][", new_cond)) - << "Inv translate error: ][ found in:" << new_cond; + auto new_cond = + refinement_map.ParseRfExprFromString(inv_expr); add_an_assumption(new_cond, "invariant_assume"); } } // add_inv_obj_as_assumption @@ -115,8 +116,7 @@ void VlgSglTgtGen::add_inv_obj_as_assumption(InvariantObject* inv_obj) { void VlgSglTgtGen::add_rf_inv_as_assumption() { if (has_rf_invariant) { for (auto&& cond : refinement_map.global_invariants) { - auto new_cond = ReplExpr(cond); - add_an_assumption(new_cond, "invariant_assume"); // without new var added + add_an_assumption(cond, "invariant_assume"); // without new var added } // for inv in global invariants field } } // add_rf_inv_as_assumption @@ -125,9 +125,7 @@ void VlgSglTgtGen::add_rf_inv_as_assertion() { // the provided invariants if (has_rf_invariant) { for (auto& cond : refinement_map.global_invariants) { - auto new_cond = - ReplExpr(cond); // force vlg state - add_an_assertion("(" + new_cond + ")", "invariant_assert"); + add_an_assertion(cond, "invariant_assert"); } } // has_rf_invariant } // add_rf_inv_as_assertion @@ -210,10 +208,9 @@ void VlgSglTgtGen:: // this is cex reachability checking // -- assertions -- // auto new_cond = - ReplExpr( refinement_map.ParseRfExprFromString( - _advanced_param_ptr->_cex_obj_ptr->GenInvAssert(""))); // force vlg state - add_an_assertion("~(" + new_cond + ")", "cex_nonreachable_assert"); + _advanced_param_ptr->_cex_obj_ptr->GenInvAssert("")); // force vlg state + add_an_assertion(rfmap_not(new_cond), "cex_nonreachable_assert"); // -- assumption -- // if (_vtg_config.InvariantSynthesisReachableCheckKeepOldInvariant) { add_rf_inv_as_assumption(); @@ -247,6 +244,10 @@ void VlgSglTgtGen::ConstructWrapper_inv_syn_cond_signals() { target_type == target_type_t::INVARIANTS); vlg_wrapper.add_input("__START__", 1); vlg_wrapper.add_input("__STARTED__", 1); + + rfmap_add_internal_wire("__START__", 1); + rfmap_add_replacement("decode", "__START__"); + rfmap_add_internal_wire("__STARTED__", 1); } diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index f9183c85c..86fd94d46 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -31,7 +31,7 @@ bool VlgSglTgtGen::bad_state_return(void) { } // bad_state_return void VlgSglTgtGen::RfmapIlaStateSanityCheck() { -#define ERR_IF(cond,s) do { ILA_ERROR_IF(cond) << (s); _bad_state = true; return; } while(0) +#define ERR_IF(cond,s) do { ILA_ERROR_IF(cond) << (s); if(cond) { _bad_state = true; return;} } while(0) for(unsigned sidx = 0; sidx < _host->state_num(); ++ sidx) { const auto & s = _host->state(sidx); @@ -59,13 +59,13 @@ void VlgSglTgtGen::RfmapIlaStateSanityCheck() { void VlgSglTgtGen::ConstructWrapper_add_additional_mapping_control() { for(const auto & mapc : refinement_map.additional_mapping) { - add_an_assumption(ReplExpr(mapc), "additional_mapping_control_assume"); + add_an_assumption(mapc, "additional_mapping_control_assume"); } } // ConstructWrapper_add_additional_mapping_control void VlgSglTgtGen::ConstructWrapper_add_rf_assumptions() { for (const auto & assumpt : refinement_map.assumptions) { - add_an_assumption(ReplExpr(assumpt), "rfassumptions"); + add_an_assumption(assumpt, "rfassumptions"); } } // ConstructWrapper_add_rf_assumptions @@ -112,16 +112,19 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { const auto & result_apply = each_apply.result_map; std::string func_result_wire = funcName + "_" + IntToStr(idx - 1) + "_result_wire"; - auto res_map = "~( __START__ )||(" + func_result_wire + "==" + ReplExpr(result_apply) + ")"; + auto res_map = rfmap_imply(rfmap_var("decode"), + rfmap_eq(rfmap_var(func_result_wire), result_apply)); + std::vector prep; std::string prep = VLG_TRUE; size_t arg_idx = 0; for (const auto & each_arg : arg_apply) { std::string func_arg = funcName + "_" + IntToStr(idx - 1) + "_arg" + IntToStr(arg_idx++) + "_wire"; - - prep += "&&(~( __START__ )||((" + func_arg + ") == (" + ReplExpr(each_arg) + ")))"; + prep.push_back( + rfmap_imply(rfmap_var("decode"), + rfmap_eq(rfmap_var(func_arg), each_arg))); } // ( // (decode |-> arg0_output == ??@?? ) && (decode |-> arg1_output == ??@?? ) @@ -129,7 +132,8 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { // ) |-> ( // (decode |-> result_input == ??@??) // ) - add_an_assumption("~(" + prep + ") || (" + res_map + ")", "funcmap"); + add_an_assumption( + rfmap_imply(rfmap_and(prep), res_map), "funcmap"); } // for each apply in the list of apply name_to_fnapp_vec.erase(funcName); // remove from it @@ -145,27 +149,31 @@ void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { for(const auto & delay_unit : refinement_map.aux_delays) { const auto & name = delay_unit.first; const auto & du = delay_unit.second; + unsigned width = du.width; + auto rhs = du.signal; + if (du.delay_type != rfmap::SignalDelay::delay_typeT::SINGLE && du.width > 1) { + width = 1; + rhs = rfmap_reduce_or( rhs );; + } ILA_ERROR_IF(du.num_cycle == 0) << "Cannot delay 0 cycle"; std::string last_reg; for(size_t didx = 1; didx <= du.num_cycle; ++ didx) { auto curr_name = name+"_d_"+std::to_string(didx); auto prev_name = name+"_d_"+std::to_string(didx-1); - vlg_wrapper.add_reg(curr_name, delay_unit.second.width); + vlg_wrapper.add_reg(curr_name, width); if(didx == 1) { // delay from signal - auto rhs = ReplExpr(du.signal); - if (du.delay_type != rfmap::SignalDelay::delay_typeT::SINGLE && du.width > 1) - rhs = "|(" + rhs + ")"; - vlg_wrapper.add_always_stmt(curr_name + " <= " + rhs); - } else { - vlg_wrapper.add_always_stmt(curr_name + " <= " + prev_name + " ;"); + vlg_wrapper.add_wire(prev_name, width , true); + rfmap_add_internal_wire(prev_name, width); + add_wire_assign_assumption(prev_name, rhs, "delay_unit"); } + vlg_wrapper.add_always_stmt(curr_name + " <= " + prev_name + " ;"); if(didx == du.num_cycle) last_reg = curr_name; } // end - for each delay if(du.delay_type == rfmap::SignalDelay::delay_typeT::SINGLE) { - vlg_wrapper.add_wire(name, du.width); + vlg_wrapper.add_wire(name, width); vlg_wrapper.add_assign_stmt(name, last_reg); continue; } // else @@ -197,9 +205,11 @@ void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { for(const auto & n_tracker : refinement_map.phase_tracker) { - + const auto & tracker_name = n_tracker.first; const auto & tracker = n_tracker.second; + for (const auto & vardef : tracker.var_defs) { + // already in refinement_map.all_var_def_types const auto & vn = vardef.first; if ( vardef.second.type == rfmap::GeneralVerilogMonitor::VarDef::var_type::REG ) vlg_wrapper.add_reg(vn, vardef.second.width); @@ -208,20 +218,65 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { } for ( const auto & event_alias : tracker.event_alias) { vlg_wrapper.add_wire( event_alias.first, 1); - vlg_wrapper.add_assign_stmt(event_alias.first, ReplExpr(event_alias.second)); + rfmap_add_internal_wire( event_alias.first, 1); + // add_wire_assign_assumption + add_wire_assign_assumption(event_alias.first, event_alias.second, "stage_tracker"); } unsigned sidx = 0; for (const auto & stage : tracker.rules) { - std::string stage_name = stage.stage_name.empty() ? "stage" + std::to_string(sidx) : stage.stage_name; + std::string stage_name = tracker_name + "_" + + ( stage.stage_name.empty() ? + "stage" + std::to_string(sidx) : + stage.stage_name); vlg_wrapper.add_reg(stage_name , 1); + + std::string enter_cond_wire_name = stage_name + "_enter_cond"; + std::string exit_cond_wire_name = stage_name + "_exit_cond"; + std::string enter_action_wire_name = stage_name + "_enter_action"; + std::string exit_action_wire_name = stage_name + "_exit_action"; - vlg_wrapper.add_always_stmt("if(" + ReplExpr(stage.enter_rule) + ") begin " + stage_name + " <= 1'b1;" ); - for(const auto & action : stage.enter_action) - vlg_wrapper.add_always_stmt(action.LHS + " <= " + ReplExpr(action.RHS)); + vlg_wrapper.add_always_stmt("if(" + enter_cond_wire_name + ") begin " + stage_name + " <= 1'b1;" ); + vlg_wrapper.add_wire(enter_cond_wire_name, 1, true); + rfmap_add_internal_wire(enter_cond_wire_name, 1); + add_wire_assign_assumption(enter_cond_wire_name, stage.enter_rule, "phase_tracker" ); + + unsigned idx = 0; + for(const auto & action : stage.enter_action) { + auto pos_def_var = refinement_map.all_var_def_types.find(action.LHS); + ILA_ERROR_IF(pos_def_var == refinement_map.all_var_def_types.end()) + << "Cannot find var def for " << action.LHS << " used in LHS of phase tracker " + << tracker_name; + + std::string action_name = enter_action_wire_name+std::to_string(idx++); + vlg_wrapper.add_always_stmt(action.LHS + " <= " + action_name + ";"); + + + vlg_wrapper.add_wire(action_name, pos_def_var->second.width, true); + rfmap_add_internal_wire(action_name, pos_def_var->second.width); + add_wire_assign_assumption(action_name, action.RHS, "phase_tracker"); + } + vlg_wrapper.add_always_stmt("end"); - vlg_wrapper.add_always_stmt("else if(" + ReplExpr(stage.exit_rule) + ") begin " + stage_name + " <= 1'b0;"); - for(const auto & action : stage.exit_action) - vlg_wrapper.add_always_stmt(action.LHS + " <= " + ReplExpr(action.RHS)); + vlg_wrapper.add_always_stmt("else if(" + exit_cond_wire_name + ") begin " + stage_name + " <= 1'b0;"); + + vlg_wrapper.add_wire(exit_cond_wire_name, 1, true); + rfmap_add_internal_wire(exit_cond_wire_name, 1); + add_wire_assign_assumption(exit_cond_wire_name, stage.exit_rule, "phase_tracker" ); + + idx = 0; + for(const auto & action : stage.exit_action){ + auto pos_def_var = refinement_map.all_var_def_types.find(action.LHS); + ILA_ERROR_IF(pos_def_var == refinement_map.all_var_def_types.end()) + << "Cannot find var def for " << action.LHS << " used in LHS of phase tracker " + << tracker_name; + + std::string action_name = exit_action_wire_name+std::to_string(idx++); + vlg_wrapper.add_always_stmt(action.LHS + " <= " + action_name + ";"); + vlg_wrapper.add_wire(action_name, pos_def_var->second.width, true); + rfmap_add_internal_wire(action_name, pos_def_var->second.width); + add_wire_assign_assumption(action_name, action.RHS, "phase_tracker"); + } + vlg_wrapper.add_always_stmt("end"); sidx ++; @@ -233,10 +288,12 @@ void VlgSglTgtGen::ConstructWrapper_add_post_value_holder() { for(const auto & post_val_holder : refinement_map.value_recorder) { const auto & pv_name = post_val_holder.first; vlg_wrapper.add_reg(pv_name, post_val_holder.second.width); + rfmap_add_internal_reg(pv_name, post_val_holder.second.width); + add_reg_cassign_assumption(pv_name, - ReplExpr(post_val_holder.second.value), + post_val_holder.second.value, post_val_holder.second.width, - ReplExpr(post_val_holder.second.condition), + post_val_holder.second.condition, "post_value_holder"); } } // ConstructWrapper_add_post_value_holder @@ -249,6 +306,7 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { for (auto&& m_rec : monitor_rec) { + const auto& mname = m_rec.first; const auto& mdef = m_rec.second; // generalMonitor std::string vlg_expr; @@ -260,16 +318,28 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { continue; for (const auto & n_def : mdef.var_defs) { + // already in refinement_map.all_var_def if(n_def.second.type == rfmap::GeneralVerilogMonitor::VarDef::var_type::REG) vlg_wrapper.add_reg(n_def.first, n_def.second.width); else vlg_wrapper.add_wire(n_def.first, n_def.second.width); } + unsigned idx = 0; std::vector> replace_list; for (const auto & vref : mdef.var_uses) { auto vref_node = ::verilog_expr::VExprAst::MakeVar(vref); - auto new_name = ReplExpr(vref_node); + auto new_name = mname + "_auxvar" + std::to_string(idx ++); + + auto tp = VarTypeCheckForRfExprParsing(vref); + ILA_ERROR_IF(tp.type.is_unknown()) << "Cannot determine width of " + << vref << " in monitor " << mname; + + auto width = tp.type.unified_width(); + vlg_wrapper.add_wire(new_name, width, true); + rfmap_add_internal_wire(new_name, width); + add_wire_assign_assumption(new_name, vref_node, "monitor_auxvar"); + replace_list.push_back(std::make_pair(vref, new_name)); } diff --git a/src/vtarget-out/vlg_mod.cc b/src/vtarget-out/vlg_mod.cc index df3471ab9..d708607e1 100644 --- a/src/vtarget-out/vlg_mod.cc +++ b/src/vtarget-out/vlg_mod.cc @@ -289,7 +289,8 @@ VerilogModifier::RecordConnectSigName(const std::string& vlg_sig_name, auto vname = ReplaceAll(vlg_sig_name, ".", "__DOT__") + - "_"+ ReplaceAll(suffix,"'","") +"_"; // name for verilog + (suffix.empty() ? "" : ( + "_"+ ReplaceAll(suffix,"'","") +"_")); // name for verilog auto mod_hier_name = Split(vlg_sig_name, "."); auto hier = mod_hier_name.size(); auto last_level_name = mod_hier_name[hier - 1]; @@ -325,8 +326,9 @@ VerilogModifier::RecordConnectSigName(const std::string& vlg_sig_name, // use the special location (mod_decl to add wires and ...) loc = vlg_info_ptr->get_endmodule_loc(inst_name); // this the endmodule location + auto last_lv_signal_name = suffix.empty() ? short_name : (short_name + "["+ suffix+"]"); assign_map[loc.first].push_back( - assign_item_t(loc.second, vname, width, short_name + "["+ suffix+"]")); + assign_item_t(loc.second, vname, width, last_lv_signal_name)); return vlg_sig_t({vname, width}); } // RecordConnectSigName diff --git a/src/vtarget-out/vtarget_gen_impl.cc b/src/vtarget-out/vtarget_gen_impl.cc index c523685dc..a97fbb98a 100644 --- a/src/vtarget-out/vtarget_gen_impl.cc +++ b/src/vtarget-out/vtarget_gen_impl.cc @@ -121,7 +121,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INVARIANTS, _advanced_param_ptr); target.ConstructWrapper(); - target.ExportAll("wrapper.v", "ila.v", "run.sh", "problem.txt"); + target.ExportAll("wrapper.v", "ila.v", "run.sh", "gen_btor.ys"); target.do_not_instantiate(); // no use, just for coverage } else if (_backend == backend_selector::JASPERGOLD && invariantExists) { auto target = VlgSglTgtGen_Jasper( diff --git a/src/vtarget-out/vtarget_gen_jasper.cc b/src/vtarget-out/vtarget_gen_jasper.cc index 4b21b946f..28b9f7f9e 100644 --- a/src/vtarget-out/vtarget_gen_jasper.cc +++ b/src/vtarget-out/vtarget_gen_jasper.cc @@ -33,26 +33,12 @@ VlgSglTgtGen_Jasper::VlgSglTgtGen_Jasper( adv_ptr) {} void VlgSglTgtGen_Jasper::add_wire_assign_assumption( - const std::string& varname, const std::string& expression, + const std::string& varname, const rfmap::RfExpr& expression, const std::string& dspt) { // a plain assign vlg_wrapper.add_assign_stmt(varname, expression); } -void VlgSglTgtGen_Jasper::add_reg_cassign_assumption( - const std::string& varname, const std::string& expression, int width, - const std::string& cond, const std::string& dspt) { - - std::string rand_in_name = "__" + varname + "_init__"; - vlg_wrapper.add_input(rand_in_name, width); - vlg_wrapper.add_wire(rand_in_name, width); - - vlg_wrapper.add_init_stmt(varname + " <= " + rand_in_name + ";"); - vlg_wrapper.add_always_stmt(varname + " <= " + varname + ";"); - add_an_assumption( - "(~(" + cond + ") || ((" + varname + ") == (" + expression + ")))", dspt); -} - /// Add SMT-lib2 assumption void VlgSglTgtGen_Jasper::add_a_direct_smt_assumption(const std::string& arg, diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index 60ffe8dd9..f98cf247b 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -77,7 +77,7 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); // execute it - fout << yosys << " -s" << ys_script_name << " > __yosys_exec_result.txt\n"; + fout << yosys << " -s " << ys_script_name << " > __yosys_exec_result.txt\n"; } @@ -96,7 +96,7 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { pono = os_portable_append_dir(_vtg_config.PonoPath, pono); } - fout << pono << "problem.btor2" << std::endl; + fout << pono << " problem.btor2 " << std::endl; } @@ -252,13 +252,16 @@ void VlgSglTgtGen_Pono::Export_modify_verilog() { auto old_name = refered_vlg_item.second.get_orig_name(); auto new_name = refered_vlg_item.second.get_new_name(); - if(StrStartsWith(new_name, "__ILA_")) + if(!StrStartsWith(refered_vlg_item.first, "RTL.")) continue; auto idx = old_name.find("["); auto removed_range_name = old_name.substr(0, idx); vlg_mod.RecordKeepSignalName(removed_range_name); // auto sig = // no use, this is too late, vlg_wrapper already exported + ILA_CHECK(!S_IN("'", refered_vlg_item.second.range_o)) << "Not handling " + << old_name << ", ' in name is not handled"; + ILA_CHECK(refered_vlg_item.second.range_o.empty()) << "Let's see if this is correct"; vlg_mod.RecordConnectSigName(removed_range_name, refered_vlg_item.second.range_o); // vlg_wrapper.add_output(sig.first, sig.second); diff --git a/test/unit-data/vpipe/rfmap/cond.json b/test/unit-data/vpipe/rfmap/cond.json index 3b42d6ec7..5a8e5959d 100644 --- a/test/unit-data/vpipe/rfmap/cond.json +++ b/test/unit-data/vpipe/rfmap/cond.json @@ -1,45 +1,39 @@ { - "target ILA": "vlg-gen/pipe.v:simpePipe", - "target Verilog": "verilog/simple_pipe.v:pipeline_v", // this is a comment "global invariants": [ - "(! (m1.reg_0_w_stage == 2'b00 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd0) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd0) ) )", - "(! (m1.reg_1_w_stage == 2'b00 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd1) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd1) ) )", - "(! (m1.reg_2_w_stage == 2'b00 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd2) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd2) ) )", - "(! (m1.reg_3_w_stage == 2'b00 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd3) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd3) ) )", - "(! (m1.reg_0_w_stage == 2'b10 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd0) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd0) ) )", - "(! (m1.reg_1_w_stage == 2'b10 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd1) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd1) ) )", - "(! (m1.reg_2_w_stage == 2'b10 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd2) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd2) ) )", - "(! (m1.reg_3_w_stage == 2'b10 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd3) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd3) ) )", - "(! (m1.reg_0_w_stage == 2'b11 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd0) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd0) ) )", - "(! (m1.reg_1_w_stage == 2'b11 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd1) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd1) ) )", - "(! (m1.reg_2_w_stage == 2'b11 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd2) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd2) ) )", - "(! (m1.reg_3_w_stage == 2'b11 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd3) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd3) ) )", - "(! (m1.reg_0_w_stage == 2'b01 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd0) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd0) ) )", - "(! (m1.reg_1_w_stage == 2'b01 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd1) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd1) ) )", - "(! (m1.reg_2_w_stage == 2'b01 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd2) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd2) ) )", - "(! (m1.reg_3_w_stage == 2'b01 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd3) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd3) ) )" + " (RTL.reg_0_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd0) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd1) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd2) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd3) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd0) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd1) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd2) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd3) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd0) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd1) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd2) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd3) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd0) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd1) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd2) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd3) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd3) ) )" ], "instructions": [ { - "instruction": "NOP", - "ready signal": [], + "instruction": "NOP", "ready bound": 1 }, { "instruction": "ADD", - "ready signal": [], "ready bound": 1 }, { "instruction": "SUB", - "ready signal": [], "ready bound": 1 }, { "instruction": "AND", - "ready signal": [], "ready bound": 1 } ] diff --git a/test/unit-data/vpipe/rfmap/vmap.json b/test/unit-data/vpipe/rfmap/vmap.json index 52dbc555c..26f0744d2 100644 --- a/test/unit-data/vpipe/rfmap/vmap.json +++ b/test/unit-data/vpipe/rfmap/vmap.json @@ -1,36 +1,35 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, "instruction mapping": [], "state mapping": { "r0": - [ "~( m1.reg_0_w_stage == 2'b10 ) || (m1.ex_alu_result == m0.r0)", - "~( m1.reg_0_w_stage == 2'b11 ) || (m1.ex_alu_result == m0.r0)", - "~( m1.reg_0_w_stage == 2'b01 ) || (m1.ex_wb_val == m0.r0)", - "~( m1.reg_0_w_stage == 2'b00 ) || (m1.registers[0] == m0.r0)"] , + [ [" RTL.reg_0_w_stage == 2'b10 ", " RTL.ex_alu_result == ILA.r0"], + [" RTL.reg_0_w_stage == 2'b11 ", " RTL.ex_alu_result == ILA.r0"], + [" RTL.reg_0_w_stage == 2'b01 ", " RTL.ex_wb_val == ILA.r0"], + [" RTL.reg_0_w_stage == 2'b00 ", " RTL.registers[0] == ILA.r0"]] , "r1": - [ "~( m1.reg_1_w_stage == 2'b10 ) || (m1.ex_alu_result == m0.r1)", - "~( m1.reg_1_w_stage == 2'b11 ) || (m1.ex_alu_result == m0.r1)", - "~( m1.reg_1_w_stage == 2'b01 ) || (m1.ex_wb_val == m0.r1)", - "~( m1.reg_1_w_stage == 2'b00 ) || (m1.registers[1] == m0.r1)"], + [ [" RTL.reg_1_w_stage == 2'b10 ", "RTL.ex_alu_result == ILA.r1"], + [" RTL.reg_1_w_stage == 2'b11 ", "RTL.ex_alu_result == ILA.r1"], + [" RTL.reg_1_w_stage == 2'b01 ", "RTL.ex_wb_val == ILA.r1"], + [" RTL.reg_1_w_stage == 2'b00 ", "RTL.registers[1] == ILA.r1"]], "r2": - [ "~( m1.reg_2_w_stage == 2'b10 ) || (m1.ex_alu_result == m0.r2)", - "~( m1.reg_2_w_stage == 2'b11 ) || (m1.ex_alu_result == m0.r2)", - "~( m1.reg_2_w_stage == 2'b01 ) || (m1.ex_wb_val == m0.r2)", - "~( m1.reg_2_w_stage == 2'b00 ) || (m1.registers[2] == m0.r2)"], + [ ["RTL.reg_2_w_stage == 2'b10 ", "RTL.ex_alu_result == ILA.r2"], + ["RTL.reg_2_w_stage == 2'b11 ", "RTL.ex_alu_result == ILA.r2"], + ["RTL.reg_2_w_stage == 2'b01 ", "RTL.ex_wb_val == ILA.r2"], + ["RTL.reg_2_w_stage == 2'b00 ", "RTL.registers[2] == ILA.r2"]], "r3": - [ {"cond":" m1.reg_3_w_stage == 2'b10 " , "map":"m1.ex_alu_result"}, - {"cond":" m1.reg_3_w_stage == 2'b11 " , "map":"ex_alu_result"}, - {"cond":" m1.reg_3_w_stage == 2'b01 " , "map":" m1.ex_wb_val == m0.r3"}, - {"cond":" m1.reg_3_w_stage == 2'b00 " , "map":" m1.registers[3] == m0.r3"}]}, + [ ["RTL.reg_3_w_stage == 2'b10 " , "RTL.ex_alu_result"], + ["RTL.reg_3_w_stage == 2'b11 " , "RTL.ex_alu_result"], + ["RTL.reg_3_w_stage == 2'b01 " , " RTL.ex_wb_val == ILA.r3"], + ["RTL.reg_3_w_stage == 2'b00 " , " RTL.registers[3] == ILA.r3"]] + }, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "inst":"inst", - "dummy_read_rf":"**KEEP**", - "dummy_rf_data":"**SO**" + "input mapping": { + "inst":"RTL.inst" }, - // the following line has no use, it is just a case of finding wire - "mapping control" : ["m1.reg_0_w_stage_nxt != 2'b11"] + + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + } } From de5076595296e5b133611ee9b07e0a786dbebe8c Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sat, 14 Aug 2021 20:35:18 +0800 Subject: [PATCH 28/78] rfexpr array --- include/ilang/rfmap-in/rfmap_typecheck.h | 32 ++- include/ilang/vtarget-out/vlg_mod.h | 8 +- include/ilang/vtarget-out/vtarget_gen_impl.h | 61 ++++- .../ilang/vtarget-out/vtarget_gen_jasper.h | 13 +- src/rfmap-in/rfmap_typecheck.cc | 68 +++--- src/util/str_util.cc | 7 +- src/vtarget-out/gen_util.cc | 8 +- src/vtarget-out/single_target.cc | 40 ++-- src/vtarget-out/single_target_as.cc | 210 ++++++++++++++++++ src/vtarget-out/single_target_connect.cc | 26 +-- src/vtarget-out/single_target_misc.cc | 3 +- src/vtarget-out/vlg_mod.cc | 53 +++++ src/vtarget-out/vtarget_gen_jasper.cc | 19 -- src/vtarget-out/vtarget_gen_pono.cc | 24 +- 14 files changed, 436 insertions(+), 136 deletions(-) diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index ccdae444e..f12d7ca9d 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -40,10 +40,10 @@ struct VarReplacement { VarReplacement(const RfExpr & o, const RfExpr & n); - // returns v or v[range] + // returns v, there would not be `v[range]` at all std::string get_orig_name() const { - return std::dynamic_pointer_cast( - origvar)->get_name().first; + return std::dynamic_pointer_cast + (origvar)->get_name().first; } std::string get_new_name() const{ @@ -54,7 +54,6 @@ struct VarReplacement { return get_type_orig(); } -private: RfVarTypeOrig get_type_orig() const { auto annotation_ptr = newvar->get_annotation(); return annotation_ptr?*annotation_ptr:RfVarTypeOrig(); @@ -73,6 +72,7 @@ struct VarReplacement { bool is_orig_var_array() const { return get_type_orig().type.is_array(); } + }; // convert RfExpr constant -> out @@ -119,6 +119,10 @@ class RfExprAstUtility { static void GetVars(const RfExpr & in, std::unordered_map & vars_out); static RfVarTypeOrig GetType(const RfExpr & in); + /// will modify where the pointer is pointing to + /// because we will be creating new rfexpr + static void TraverseRfExpr(RfExpr & inout, std::function func) ; + }; @@ -175,22 +179,35 @@ struct TypedVerilogRefinementMap : const std::string & n, const VarReplacement & in) { var_replacement.emplace(n, in); } - VarReplacement * CheckReplacement(const std::string & origname) const { + VarReplacement * CheckReplacement(const std::string & origname) { auto pos = var_replacement.find(origname); if(pos != var_replacement.end()) - return &(pos->second); + return &(var_replacement.at(origname)); return NULL; } + const std::map & + GetVarReplacement() const { return var_replacement; } + protected: /// the replacement used for creating new wires std::map var_replacement; // including rtl/ilas/ilav void initialize(); + /// this function will not collect implicity vars + /// or those with 0/auto width + /// for the explicity vars + /// it will add them to the `all_var_def_types` + /// for the implicit ones, ComputeDelayValueHolderWidth will + /// compute the width and add them to `all_var_def_types` + + /// this will also create `all_var_def_types` + /// for 4 virtual vars: decode, commit, $decode, $valid + /// those replacement are added separately void CollectInternallyDefinedVars(); - void TraverseRfExpr(RfExpr & inout, std::function func) ; + /// deal with condition map void TraverseCondMap(SingleVarMap & inout, std::function func) ; @@ -203,6 +220,7 @@ struct TypedVerilogRefinementMap : // helper for AST traversal void collect_inline_value_recorder_func(RfExpr & inout); void collect_inline_delay_func(RfExpr & inout); + // this function uses the above two and the void CollectInlineDelayValueHolder(); // this function is used in value holder/delay : width determination diff --git a/include/ilang/vtarget-out/vlg_mod.h b/include/ilang/vtarget-out/vlg_mod.h index 04a6de47f..319707e39 100644 --- a/include/ilang/vtarget-out/vlg_mod.h +++ b/include/ilang/vtarget-out/vlg_mod.h @@ -101,8 +101,12 @@ class VerilogModifier { /// record the name to add a keep there void RecordKeepSignalName(const std::string& vname); /// record the name to add related wires - vlg_sig_t RecordConnectSigName(const std::string& vlg_sig_name, - const std::string& suffix = ""); + void RecordConnectSigName( + const std::string& vname, // wirename + const std::string& hierarchy, // + const std::string& last_level_name, + unsigned width); + /// record the stmt to be added to a module void RecordAdditionalVlgModuleStmt(const std::string& stmt, const std::string& mod_instance_name); diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 918b826a7..377f5274a 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -31,6 +31,26 @@ namespace ilang { +/// \brief What internal signal to pull out +/// for yosys +struct RtlExtraWire { + std::string wire_name; + std::string hierarchy; + std::string internal_name; + unsigned width; + RtlExtraWire(const std::string & wn, + const std::string & h, + const std::string & i, + unsigned _width) : + wire_name(wn), hierarchy(h), internal_name(i), + width(_width) { } + // for example: + // RTL.a.b.c[3] + // wire_name : RTL__DOT__a__DOT__b__DOT__c_3_ + // hierarchy RTL.a.b + // internal name c[3] +}; // end of struct RtlExtraWire + /// \brief Generating a target (just the invairant or for an instruction) class VlgSglTgtGen { public: @@ -268,6 +288,22 @@ class VlgSglTgtGen { void ConstructWrapper_add_stage_tracker(); /// Add Verilog inline monitor void ConstructWrapper_add_vlg_monitor(); + /// handle all_assumption/all_assertion + /// ReplExpr all assertion/assumptions + /// ReplExpr will know whether to create + /// `__DOT__`, but will anyway + // do the other replacement, and non-repl + /// for yosys: + /// 1. use var_replacement to create + /// extra wire + /// 2. check if contains array[const] + /// add extra wire and replacement + /// 3. if it still contain array + /// use add_smt_assumption/assertion + /// for the others, use add_a_direct ... + /// for jg: + /// 1. use add_a_direct_assertion/assumption ... + void ConstructWrapper_translate_property_and_collect_all_rtl_connection_var(); // ------------------------------------------------------------------------- /// Add invariants as assumption/assertion when target is inv_syn_design_only @@ -307,6 +343,19 @@ class VlgSglTgtGen { /// Store the selection of backend backend_selector _backend; +protected: + // ----------------------- MEMBERS for storing assumptions/assertions ------------------- // + /// assumptions : written by add_an_assumption, + /// consumed by ConstructWrapper_translate_property_and_collect_all_rtl_connection_var + std::map> all_assumptions; + /// assumptions : written by add_an_assertion, + /// consumed by ConstructWrapper_translate_property_and_collect_all_rtl_connection_var + std::map> all_assertions; + /// assign or assumptions : vector of (dspt, wire_name, rhs, wn == rhs) + std::vector> assign_or_assumptions; + /// map: wire_name -> (wire_name, hierarchy, internal name) + std::unordered_map rtl_extra_wire; + public: /// Call the separate construct functions to make a wrapper (not yet export /// it) @@ -354,15 +403,13 @@ class VlgSglTgtGen { const std::string& body, const std::string& dspt) = 0; - // helper function to be implemented by COSA, Yosys, invsyn, jasper is not - /// Add an assumption -- if aspt can be represented in vlg - // then will only use vlg (this is true for jg) - // but for those needs Yosys, array will be handled differently + // helper function to add assumption/assertions to internal data-strcture virtual void add_an_assumption(const rfmap::RfExpr& aspt, - const std::string& dspt) = 0; + const std::string& dspt); + /// Add an assertion -- JasperGold will override this virtual void add_an_assertion(const rfmap::RfExpr& asst, - const std::string& dspt) = 0; + const std::string& dspt); // Add SMT assumption (using rfexpr) // - will use add_a_direct_smt_assumption/assertion @@ -379,7 +426,7 @@ class VlgSglTgtGen { /// has to be an assumption virtual void add_wire_assign_assumption(const std::string& varname, const rfmap::RfExpr &aspt, - const std::string& dspt) = 0; + const std::string& dspt); /// Add an assignment, will always be an assumption /// will use add_an_assumption, and it is up to diff --git a/include/ilang/vtarget-out/vtarget_gen_jasper.h b/include/ilang/vtarget-out/vtarget_gen_jasper.h index c9094c9c9..994ccf428 100644 --- a/include/ilang/vtarget-out/vtarget_gen_jasper.h +++ b/include/ilang/vtarget-out/vtarget_gen_jasper.h @@ -68,12 +68,7 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { const std::string& ret, const std::string& body, const std::string& dspt) override; - /// Add an assumption - virtual void add_an_assumption(const rfmap::RfExpr& aspt, - const std::string& dspt) override; - /// Add an assertion - virtual void add_an_assertion(const rfmap::RfExpr& asst, - const std::string& dspt) override; + /// Add a direct assumption virtual void add_a_direct_assumption(const std::string& aspt, const std::string& dspt) override; @@ -81,12 +76,6 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { virtual void add_a_direct_assertion(const std::string& asst, const std::string& dspt) override; - /// Add an assignment which in JasperGold could be an assignment, but in CoSA - /// has to be an assumption - virtual void add_wire_assign_assumption(const std::string& varname, - const rfmap::RfExpr& expression, - const std::string& dspt) override; - /// Pre export work : nothing for cosa void virtual PreExportProcess() override {} /// export the script to run the verification diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 7cc153e15..33621c423 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -278,36 +278,6 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr(std::function func) { - // DFS -- Note: we need to call func on the parent's child - // and make sure it runs the first - std::vector> parent_stack; - parent_stack.push_back(std::make_pair(inout,0U)); - while(!parent_stack.empty()) { - auto & lastlv = parent_stack.back(); - auto cnt = lastlv.first->get_child_cnt(); - auto & idx = lastlv.second; - if(idx >= cnt) { - parent_stack.pop_back(); - if(!parent_stack.empty()) { - // refer to parent - func( parent_stack.back().first->child( parent_stack.back().second ) ); - ++ parent_stack.back().second; - } - continue; - } else { - // enter c[idx] - if(lastlv.first->get_child_cnt() == 0) { - func ( lastlv.first->child(idx) ); - ++idx; - } else { - parent_stack.push_back( std::make_pair(lastlv.first->child(idx), 0U )); - } - } - } // end of while - func(inout); -} // TraverseRfExpr - // ------------------------------------------------------------------------------ @@ -320,6 +290,8 @@ bool _compute_const(const RfExpr & in, unsigned & out) { return false; auto bws = cst_ast_ptr->get_constant(); auto base = std::get<0>(bws); + if(base == 0) + base = 10; // auto width = std::get<1>(bws); out = StrToLong(std::get<2>(bws), base); return true; @@ -581,6 +553,38 @@ bool RfExprAstUtility::HasArrayVar( return has_array; } + +void RfExprAstUtility::TraverseRfExpr(RfExpr & inout, std::function func) { + // DFS -- Note: we need to call func on the parent's child + // and make sure it runs the first + std::vector> parent_stack; + parent_stack.push_back(std::make_pair(inout,0U)); + while(!parent_stack.empty()) { + auto & lastlv = parent_stack.back(); + auto cnt = lastlv.first->get_child_cnt(); + auto & idx = lastlv.second; + if(idx >= cnt) { + parent_stack.pop_back(); + if(!parent_stack.empty()) { + // refer to parent + func( parent_stack.back().first->child( parent_stack.back().second ) ); + ++ parent_stack.back().second; + } + continue; + } else { + // enter c[idx] + if(lastlv.first->get_child_cnt() == 0) { + func ( lastlv.first->child(idx) ); + ++idx; + } else { + parent_stack.push_back( std::make_pair(lastlv.first->child(idx), 0U )); + } + } + } // end of while + func(inout); +} // TraverseRfExpr + + bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr & in) { std::set boolean_op = { verilog_expr::voperator::GTE, @@ -616,7 +620,9 @@ void TypeAnalysisUtility::AnnotateType(const RfExpr & inout) { auto tp_annotate = inout->get_annotation(); #error "modify smt expr out test" if(inout->is_var()) { - ILA_ASSERT(tp_annotate != nullptr && !tp_annotate->type.is_unknown()); + auto ptr = std::dynamic_pointer_cast (inout); + ILA_CHECK(tp_annotate != nullptr && !tp_annotate->type.is_unknown()) + << ptr->get_name().first << " has no type annotation" ; } else if (inout->is_constant()) { if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { RfVarTypeOrig tp; diff --git a/src/util/str_util.cc b/src/util/str_util.cc index ac732b1ee..049d33913 100644 --- a/src/util/str_util.cc +++ b/src/util/str_util.cc @@ -63,7 +63,8 @@ long long StrToLong(const std::string& str, int base) { try { return std::stoll(str, NULL, base); } catch (const std::exception& e) { - ILA_ERROR << "Converting non-numeric value " << str << " to long int."; + ILA_ERROR << "Cannot converting value " << str << " to long int." + << " base : " << base; return 0; } } @@ -72,8 +73,8 @@ unsigned long long StrToULongLong(const std::string& str, int base) { try { return std::stoull(str, NULL, base); } catch (const std::exception& e) { - ILA_ERROR << "Converting non-numeric value " << str - << " to unsigned long long"; + ILA_ERROR << "Cannot converting value " << str << " to unsigned long long." + << " base : " << base; return 0; } } diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 0c5910318..eac059616 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -218,15 +218,17 @@ rfmap::VarReplacement VlgSglTgtGen::CreateVarReplacement( } auto pos_def_var = refinement_map.all_var_def_types.find(n.first); - auto rtl_ila_tp = VarTypeCheckForRfExprParsing(n.first); + if(n.second) { // if it is special name if(pos_def_var != refinement_map.all_var_def_types.end()) { tp.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR; tp.type = rfmap::RfMapVarType(pos_def_var->second.width); } else { + auto rtl_ila_tp = VarTypeCheckForRfExprParsing(n.first); tp = rtl_ila_tp; } } else { // if it is not special name + auto rtl_ila_tp = VarTypeCheckForRfExprParsing(n.first); if(!rtl_ila_tp.type.is_unknown()) tp = rtl_ila_tp; else if(pos_def_var != refinement_map.all_var_def_types.end()) { @@ -304,6 +306,7 @@ rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr & in) { } auto new_node = refinement_map.ReplacingRtlIlaVar(in); + // AnnotateType requires all refinement_map.AnnotateType(new_node); return new_node; } @@ -533,11 +536,12 @@ void VlgSglTgtGen::rfmap_add_internal_wire(const std::string &n, unsigned width) /// (Note 1: ReplExpr will also create replacement, but it will not use /// this function. 2: will require that the new one has been registered /// in refinement_map.all_var_def_type) -/// should only be used to add +/// !!! should only be used to add /// decode -> __START__ /// commit -> __IEND__ /// $decode -> vlg_ila.decode_signal /// $valid -> vlg_ila.valid_signal +/// !!! whose var_def are include in refinement_map void VlgSglTgtGen::rfmap_add_replacement(const std::string &old, const std::string &n) { auto def_pos = refinement_map.all_var_def_types.find(n); diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index ff2bb1aea..f25113701 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -324,8 +324,18 @@ void VlgSglTgtGen::ConstructWrapper() { ConstructWrapper_add_ila_input(); ILA_DLOG("VtargetGen") << "STEP:" << 5; - if (target_type == target_type_t::INV_SYN_DESIGN_ONLY) + if (target_type == target_type_t::INSTRUCTIONS) { + ILA_DLOG("VtargetGen") << "STEP:" << 5.2; + ConstructWrapper_add_varmap_assumptions(); + ILA_DLOG("VtargetGen") << "STEP:" << 5.3; + ConstructWrapper_add_varmap_assertions(); + ILA_DLOG("VtargetGen") << "STEP:" << 5.4; + ConstructWrapper_add_inv_assumption_or_assertion_target_instruction(); + } else if (target_type == target_type_t::INVARIANTS) { + ConstructWrapper_add_inv_assumption_or_assertion_target_invariant(); + } else if (target_type == target_type_t::INV_SYN_DESIGN_ONLY) { ConstructWrapper_add_inv_assumption_or_assertion_target_inv_syn_design_only(); + } ILA_DLOG("VtargetGen") << "STEP:" << 6; // 4. additional mapping if any @@ -339,6 +349,8 @@ void VlgSglTgtGen::ConstructWrapper() { // post value holder --- ABC cannot work on this if (target_type == target_type_t::INSTRUCTIONS) { + // the vars defined here are already + // presented in refinement_map.all_var_def_type ConstructWrapper_add_post_value_holder(); ConstructWrapper_add_delay_unit(); ConstructWrapper_add_stage_tracker(); @@ -348,31 +360,29 @@ void VlgSglTgtGen::ConstructWrapper() { // add monitor -- inside the monitor, there will be // disable logic if it is for invariant type target + // 7. uni-functions + if (target_type == target_type_t::INSTRUCTIONS) + ConstructWrapper_add_uf_constraints(); + + // read assumption/assertion, decide where to put them rtl/smt + // perform the reg[n] optimize + // populate the RtlExtraWire data structure + ConstructWrapper_translate_property_and_collect_all_rtl_connection_var(); + // 1. varname 2. hierarchy 3. what to connect inside + // 5.0 add the extra wires to the top module wrapper + // will use var_replacement, and will set _idr if (VlgVerifTgtGenBase::backend_needs_yosys(_backend)) ConstructWrapper_register_extra_io_wire(); ILA_DLOG("VtargetGen") << "STEP:" << 9; // 5. module instantiation + // for the vlg inst: will use _idr ConstructWrapper_add_module_instantiation(); - // 7. uni-functions - if (target_type == target_type_t::INSTRUCTIONS) - ConstructWrapper_add_uf_constraints(); // 2. add some monitors (bound cnt) // 3. add assumptions & assertions - if (target_type == target_type_t::INSTRUCTIONS) { - - ILA_DLOG("VtargetGen") << "STEP:" << 5.2; - ConstructWrapper_add_varmap_assumptions(); - ILA_DLOG("VtargetGen") << "STEP:" << 5.3; - ConstructWrapper_add_varmap_assertions(); - ILA_DLOG("VtargetGen") << "STEP:" << 5.4; - ConstructWrapper_add_inv_assumption_or_assertion_target_instruction(); - } if (target_type == target_type_t::INVARIANTS) { - ConstructWrapper_add_inv_assumption_or_assertion_target_invariant(); - } } // Construct_wrapper /// create the wrapper file diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index e9b27ee2f..0684ee787 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -81,4 +81,214 @@ void VlgSglTgtGen::add_smt_assertion( } +void VlgSglTgtGen::add_an_assumption(const rfmap::RfExpr& aspt, + const std::string& dspt) { + all_assumptions[dspt].push_back(aspt); +} + +/// Add an assertion -- JasperGold will override this +void VlgSglTgtGen::add_an_assertion(const rfmap::RfExpr& asst, + const std::string& dspt) { + all_assertions[dspt].push_back(asst); +} + +static std::string const_to_unified_str(const rfmap::RfExpr & in) { + auto cnst = verilog_expr::VExprAstConstant::cast_ptr(in); + ILA_NOT_NULL(cnst); + auto b_w_lit = cnst->get_constant(); + auto base = std::get<0>(b_w_lit); + auto lit = std::get<2>(b_w_lit); + if(base == 10 || base == 0) + return lit; + // else other base + auto n = StrToULongLong(lit, base); + if(lit != "0" && n == 0) + return "error"; + return IntToStrCustomBase(n, 10, false); +} + +static void find_and_replace_array_const( + rfmap::RfExpr & expr, + std::map & array_const_set, // RTL.a.b.c[const] + std::unordered_map & extra_wire) { + auto fd_rp_array_const_func = [ + &array_const_set,&extra_wire + ](rfmap::RfExpr & inout) { + if(inout->get_op() == verilog_expr::voperator::INDEX && + inout->get_child_cnt() == 2 && + inout->child(0)->is_var() && + inout->child(1)->is_constant() && + rfmap::RfExprAstUtility::GetType(inout->child(0)).type.is_array() + ) { + auto hier_name = inout->to_verilog(); + auto cnst = const_to_unified_str(inout->child(1)); + if(cnst == "error" ) // if cannot convert + return; + + auto new_name = ReplaceAll(hier_name,".","__DOT__"); + new_name += "_"+cnst+"_"; + if(array_const_set.find(new_name) != array_const_set.end()) { + inout = array_const_set.at(new_name); + return; + } + + const auto last_dot_pos = hier_name.rfind("."); + ILA_CHECK(last_dot_pos != std::string::npos); + const auto hierarchy = hier_name.substr(0,last_dot_pos); + const auto internal = hier_name.substr(last_dot_pos+1) + "["+cnst+"]"; + ILA_CHECK(!IN(new_name, extra_wire)); + + + auto tp = rfmap::RfExprAstUtility::GetType(inout->child(0)).type; + auto w = tp.unified_width(); + + extra_wire.emplace(new_name, + RtlExtraWire(new_name, hierarchy, internal, w)); + // new_name is the wire name + + // replace var + auto repl = verilog_expr::VExprAst::MakeSpecialName(new_name); + auto new_tp = std::make_shared(); + new_tp->var_ref_type = rfmap::TypeAnnotation::VARTYPE::INTERNAL; + new_tp->type = rfmap::RfMapVarType(w); + repl->set_annotation(new_tp); + inout = repl; + + array_const_set.emplace(new_name,repl); + } + }; + rfmap::RfExprAstUtility::TraverseRfExpr(expr, fd_rp_array_const_func); +} // find_and_replace_array_const + +void VlgSglTgtGen::add_wire_assign_assumption(const std::string& varname, + const rfmap::RfExpr &aspt, + const std::string& dspt) { + assign_or_assumptions.push_back(std::make_tuple(dspt, varname, aspt, nullptr)); +} + + // read assumption/assertion, decide where to put them rtl/smt + // perform the reg[n] optimize + // populate the RtlExtraWire data structure +void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_connection_var() { + bool is_jg = _backend == VlgSglTgtGen::backend_selector::JASPERGOLD; + + for(auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { + const auto & vn = std::get<1>(dspt_vn_rfexpr_eq); + const auto & rfe = std::get<2>(dspt_vn_rfexpr_eq); + std::get<3>(dspt_vn_rfexpr_eq) = + ReplExpr(rfmap_eq( rfmap_var(vn), rfe)); + } // for each assign/assumption + + for(auto & dspt_aspt : all_assumptions) { + for(auto & aspt : dspt_aspt.second) + aspt = ReplExpr(aspt); + } + + for (auto & dspt_asst : all_assertions) { + for (auto & asst : dspt_asst.second) + asst = ReplExpr(asst); + } + + if(is_jg) { + for(auto & dspt_aspt : all_assumptions) { + for(auto & aspt : dspt_aspt.second) + add_a_direct_assumption( aspt->to_verilog(), dspt_aspt.first ); + } + for(auto & dspt_asst : all_assertions) { + for(auto & asst : dspt_asst.second) + add_a_direct_assumption( asst->to_verilog(), dspt_asst.first ); + } + for (auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { + const auto & vn = std::get<1>(dspt_vn_rfexpr_eq); + const auto & eq = std::get<3>(dspt_vn_rfexpr_eq); + // we know it is eq(vn, rhs); + vlg_wrapper.add_assign_stmt(vn, eq->child(1)->to_verilog()); + } + return; + } + + for(const auto & repl : refinement_map.GetVarReplacement()) { + ILA_CHECK( + StrStartsWith(repl.second.get_orig_name(), "RTL." ) == + repl.second.is_orig_rtlv() + ); + + if(!repl.second.is_orig_rtlv()) + continue; + + if(repl.second.is_orig_var_array()) + continue; // do not connect array + + ILA_CHECK(StrStartsWith(repl.second.get_new_name(), "RTL__DOT__")) + << repl.second.get_new_name() << "is not replaced"; + // jaspergold should not reach here + + const auto full_name = repl.second.get_orig_name(); + const auto last_dot_pos = full_name.rfind("."); + const auto hierarchy = full_name.substr(0,last_dot_pos); + const auto internal = full_name.substr(last_dot_pos+1); + unsigned width = repl.second.get_type_orig().type.unified_width(); + + rtl_extra_wire.emplace(repl.second.get_new_name(), + RtlExtraWire(repl.second.get_new_name(), hierarchy, internal, width)); + } + + std::map array_const_set; + // below will also update `rtl_extra_wire` + for(auto & dspt_aspt : all_assumptions) { + for(auto & aspt : dspt_aspt.second) { + find_and_replace_array_const(aspt, array_const_set, rtl_extra_wire); + } + } + + for(auto & dspt_asst : all_assertions) { + for(auto & asst : dspt_asst.second) { + find_and_replace_array_const(asst, array_const_set, rtl_extra_wire); + } + } + + for(auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { + auto & eq = std::get<3>(dspt_vn_rfexpr_eq); + find_and_replace_array_const(eq, array_const_set, rtl_extra_wire); + } + + // last step + // if a=b[c] contains array not handled, then we need to have + // smt assumptions + // otherwise, we can add it as an assign + for (const auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { + const auto & eq = std::get<3>(dspt_vn_rfexpr_eq); + const auto & dspt = std::get<0>(dspt_vn_rfexpr_eq); + const auto & wn = std::get<1>(dspt_vn_rfexpr_eq); + + std::map array_var; + if(rfmap::RfExprAstUtility::HasArrayVar(eq, array_var)) + add_smt_assumption(eq, dspt); + else + vlg_wrapper.add_assign_stmt(wn, eq->child(1)->to_verilog()); + } + + for(const auto & dspt_aspt : all_assumptions) { + for(const auto & aspt : dspt_aspt.second) { + std::map array_var; + if(rfmap::RfExprAstUtility::HasArrayVar(aspt, array_var)) + add_smt_assumption(aspt, dspt_aspt.first); + else + add_a_direct_assumption(aspt->to_verilog(), dspt_aspt.first); + } + } + + for(const auto & dspt_asst : all_assertions) { + for(const auto & asst : dspt_asst.second) { + std::map array_var; + if(rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) + add_smt_assertion(asst, dspt_asst.first); + else + add_a_direct_assertion(asst->to_verilog(), dspt_asst.first); + } + } + +} // ConstructWrapper_translate_property_and_collect_all_rtl_connection_var + + }; // namespace ilang diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index 9a70ff396..f98631705 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -339,27 +339,13 @@ void VlgSglTgtGen::ConstructWrapper_add_module_instantiation() { // ------------------------ OTERHS (refs) ----------------------------- // void VlgSglTgtGen::ConstructWrapper_register_extra_io_wire() { - for (auto&& refered_vlg_item : refinement_map.var_replacement) { + for (auto && extra_wire : rtl_extra_wire) { + const auto & wire_name = extra_wire.first; + unsigned width = extra_wire.second.width; - auto old_name = refered_vlg_item.second.get_orig_name(); - auto new_name = refered_vlg_item.second.get_new_name(); - if(!StrStartsWith(refered_vlg_item.first, "RTL.")) - continue; - - auto idx = old_name.find("["); - auto removed_range_name = old_name.substr(0, idx); - auto vlg_sig_info = vlg_info_ptr->get_signal(removed_range_name, - refinement_map.width_info); - - // + ReplaceAll(ReplaceAll(refered_vlg_item.second.range, "[","_"),"]","_"); - // // name for verilog - auto width = vlg_sig_info.get_width(); - - vlg_wrapper.add_wire(new_name, width, 1); // keep - vlg_wrapper.add_output(new_name, width); // add as output of the wrapper - _idr.RegisterExtraWire(new_name, new_name); - // these will be connected to the verilog module, so register as extra wires - // so, later they will be connected + vlg_wrapper.add_wire(wire_name, width, 1); // keep + vlg_wrapper.add_output(wire_name, width); // add as output of the wrapper + _idr.RegisterExtraWire(wire_name, wire_name); } } // ConstructWrapper_register_extra_io_wire diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 86fd94d46..3bfa8048d 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -13,6 +13,7 @@ #include #include #include +#include namespace ilang { @@ -153,7 +154,7 @@ void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { auto rhs = du.signal; if (du.delay_type != rfmap::SignalDelay::delay_typeT::SINGLE && du.width > 1) { width = 1; - rhs = rfmap_reduce_or( rhs );; + rhs = rfmap_reduce_or( rhs ); } ILA_ERROR_IF(du.num_cycle == 0) << "Cannot delay 0 cycle"; diff --git a/src/vtarget-out/vlg_mod.cc b/src/vtarget-out/vlg_mod.cc index d708607e1..33242a4eb 100644 --- a/src/vtarget-out/vlg_mod.cc +++ b/src/vtarget-out/vlg_mod.cc @@ -268,6 +268,58 @@ void VerilogModifier::RecordAdditionalVlgModuleStmt( add_stmt_map[loc.first].push_back(add_stmt_t(loc.second, stmt)); } + +// RTL.a.b.c[3] +// vname : RTL__DOT__a__DOT__b__DOT__c_3_ +// hiearchy RTL.a.b +// last_level_name c[3] +void VerilogModifier::RecordConnectSigName( + const std::string& vname, // wirename + const std::string& hierarchy, // + const std::string& last_level_name, + unsigned width) +{ + ILA_CHECK(width != 0); + + auto mod_hier_name = Split(hierarchy, "."); + auto hier = mod_hier_name.size(); + ILA_CHECK(hier >= 1); + + // add module decl mod + std::string inst_name = mod_hier_name[0]; + // add topmodule: + auto loc = vlg_info_ptr->name2loc(inst_name); + ILA_CHECK(loc.first != ""); // should be found + mod_decl_map[loc.first].push_back(mod_decl_item_t(loc.second, vname, width)); + + for (unsigned idx = 1; idx < hier; ++idx) { // exclude the last level name + inst_name += "." + mod_hier_name[idx]; + + auto loc = vlg_info_ptr->name2loc(inst_name); + ILA_CHECK(loc.first != ""); // should be found + mod_decl_map[loc.first].push_back( + mod_decl_item_t(loc.second, vname, width)); + } + + // add module inst mod: a.b.signal + inst_name = mod_hier_name[0]; + for (unsigned idx = 1; idx < hier; ++idx) { + inst_name += "." + mod_hier_name[idx]; + auto loc = vlg_info_ptr->get_module_inst_loc(inst_name); + ILA_CHECK(loc.first != ""); // should be found + mod_inst_map[loc.first].push_back( + mod_inst_item_t(loc.second, vname, width)); + } + + // use the special location (mod_decl to add wires and ...) + loc = + vlg_info_ptr->get_endmodule_loc(inst_name); // this the endmodule location + assign_map[loc.first].push_back( + assign_item_t(loc.second, vname, width, last_level_name)); + +} // RecordConnectSigName + +#if 0 // the old implementation /// record the name to add a keep there VerilogModifier::vlg_sig_t VerilogModifier::RecordConnectSigName(const std::string& vlg_sig_name, @@ -332,6 +384,7 @@ VerilogModifier::RecordConnectSigName(const std::string& vlg_sig_name, return vlg_sig_t({vname, width}); } // RecordConnectSigName +#endif // end of the old implementation std::string WidthToRange(unsigned w) { if (w > 1) diff --git a/src/vtarget-out/vtarget_gen_jasper.cc b/src/vtarget-out/vtarget_gen_jasper.cc index 28b9f7f9e..ccf5a8d91 100644 --- a/src/vtarget-out/vtarget_gen_jasper.cc +++ b/src/vtarget-out/vtarget_gen_jasper.cc @@ -32,14 +32,6 @@ VlgSglTgtGen_Jasper::VlgSglTgtGen_Jasper( implementation_include_path, vtg_config, backend, target_tp, adv_ptr) {} -void VlgSglTgtGen_Jasper::add_wire_assign_assumption( - const std::string& varname, const rfmap::RfExpr& expression, - const std::string& dspt) { - // a plain assign - vlg_wrapper.add_assign_stmt(varname, expression); -} - - /// Add SMT-lib2 assumption void VlgSglTgtGen_Jasper::add_a_direct_smt_assumption(const std::string& arg, const std::string& ret, @@ -56,17 +48,6 @@ void VlgSglTgtGen_Jasper::add_a_direct_smt_assertion(const std::string& arg, ILA_CHECK(false) << "SMT assertions should not be generated for JasperGold"; } -/// Add an assumption -void VlgSglTgtGen_Jasper::add_an_assumption(const std::string& aspt, - const std::string& dspt) { - assumptions.push_back(std::make_pair(aspt, dspt)); -} -/// Add an assertion -void VlgSglTgtGen_Jasper::add_an_assertion(const std::string& asst, - const std::string& dspt) { - assertions.push_back(std::make_pair(asst, dspt)); -} - /// Add an assumption void VlgSglTgtGen_Jasper::add_a_direct_assumption(const std::string& aspt, const std::string& dspt) { diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index f98cf247b..da2ebe648 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -248,23 +248,13 @@ void VlgSglTgtGen_Pono::Export_modify_verilog() { _vtg_config.PonoAddKeep, refinement_map.width_info); - for (auto&& refered_vlg_item : refinement_map.var_replacement) { - auto old_name = refered_vlg_item.second.get_orig_name(); - auto new_name = refered_vlg_item.second.get_new_name(); - - if(!StrStartsWith(refered_vlg_item.first, "RTL.")) - continue; - - auto idx = old_name.find("["); - auto removed_range_name = old_name.substr(0, idx); - vlg_mod.RecordKeepSignalName(removed_range_name); - // auto sig = // no use, this is too late, vlg_wrapper already exported - ILA_CHECK(!S_IN("'", refered_vlg_item.second.range_o)) << "Not handling " - << old_name << ", ' in name is not handled"; - ILA_CHECK(refered_vlg_item.second.range_o.empty()) << "Let's see if this is correct"; - vlg_mod.RecordConnectSigName(removed_range_name, - refered_vlg_item.second.range_o); - // vlg_wrapper.add_output(sig.first, sig.second); + for (auto && wn_extraw : rtl_extra_wire) { + ILA_CHECK(StrStartsWith(wn_extraw.first, "RTL__DOT__")); + vlg_mod.RecordConnectSigName(wn_extraw.second.wire_name, + wn_extraw.second.hierarchy, + wn_extraw.second.internal_name, + wn_extraw.second.width); + // will not record keep } vlg_mod.FinishRecording(); From b2cf2bcc1f53c52d370d51e8b6fdc5272414b2a3 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 18 Aug 2021 12:07:36 +0800 Subject: [PATCH 29/78] vexp ref update --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index efe2ea43b..9af671ca0 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit efe2ea43b48f2be0ae923232ce4157b76605f76c +Subproject commit 9af671ca0bf4f17a9929bd09b98fe6eec4fbcfbf From 85ac6c743a015e8ef35eb607270e0ec85aec2ed4 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 18 Aug 2021 13:50:33 +0800 Subject: [PATCH 30/78] update vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 9af671ca0..951e3c34e 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 9af671ca0bf4f17a9929bd09b98fe6eec4fbcfbf +Subproject commit 951e3c34ee07ebe1a0a77a8e1ae88b73a598dfbb From 750ad5af40fa97a735b66752f2c8263e2750b3f8 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 18 Aug 2021 14:10:03 +0800 Subject: [PATCH 31/78] rfexpr to smt --- include/ilang/rfmap-in/rfexpr_shortcut.h | 2 + include/ilang/rfmap-in/rfmap_typecheck.h | 62 +++++++++++++----------- include/ilang/rfmap-in/rfvar_type.h | 2 +- src/rfmap-in/rfexpr_shortcut.cc | 10 ++-- src/rfmap-in/rfexpr_to_smt.cc | 9 +++- src/rfmap-in/rfmap_typecheck.cc | 20 ++++---- src/vtarget-out/single_target_misc.cc | 1 - test/t_rfexpr_smt_out.cc | 22 ++++++++- test/t_verilog_mod.cc | 9 ++-- 9 files changed, 87 insertions(+), 50 deletions(-) diff --git a/include/ilang/rfmap-in/rfexpr_shortcut.h b/include/ilang/rfmap-in/rfexpr_shortcut.h index 9f7d0d22b..c940bfce9 100644 --- a/include/ilang/rfmap-in/rfexpr_shortcut.h +++ b/include/ilang/rfmap-in/rfexpr_shortcut.h @@ -10,6 +10,8 @@ namespace ilang { + +rfmap::RfExpr rfmap_reduce_or(const rfmap::RfExpr & in); rfmap::RfExpr rfmap_imply(const rfmap::RfExpr &l, const rfmap::RfExpr &r); rfmap::RfExpr rfmap_and(const rfmap::RfExpr &l, const rfmap::RfExpr &r); rfmap::RfExpr rfmap_or(const rfmap::RfExpr &l, const rfmap::RfExpr &r); diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index f12d7ca9d..91087d918 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -91,18 +91,13 @@ class TypeAnalysisUtility { public: typedef std::function var_typecheck_t; - TypeAnalysisUtility(var_typecheck_t type_checker) : typechecker(type_checker) { } public: /// Annotate the type of a refinement expression /// and this process will be recursive - // this function is to help with unit testing - void AnnotateType(const RfExpr & inout); - + static void AnnotateType(const RfExpr & inout); + protected: - var_typecheck_t typechecker; - // used in TypedVerilogRefinementMap::TypeInferTravserRfExpr - // this is only used in the first stage : aux var width determination // internal use only, does not do recursion itself // therefore, an order of invocation is needed @@ -125,11 +120,38 @@ class RfExprAstUtility { }; +struct RfExprVarReplUtility { + +public: + /// used by vtarget_gen to replace rtl/ila vars + RfExpr ReplacingRtlIlaVar(const RfExpr & in); + + /// Register internal variables and also the mapping + void RegisterInternalVariableWithMapping( + const std::string & n, + const VarReplacement & in) { var_replacement.emplace(n, in); } + + VarReplacement * CheckReplacement(const std::string & origname) { + auto pos = var_replacement.find(origname); + if(pos != var_replacement.end()) + return &(var_replacement.at(origname)); + return NULL; + } + + const std::map & + GetVarReplacement() const { return var_replacement; } + +protected: + /// the replacement used for creating new wires + std::map var_replacement; // including rtl/ilas/ilav + +}; struct TypedVerilogRefinementMap : public VerilogRefinementMap, public TypeAnalysisUtility, - public RfExprAstUtility { + public RfExprAstUtility, + public RfExprVarReplUtility { // type definitions using var_typecheck_t = TypeAnalysisUtility::var_typecheck_t; @@ -171,28 +193,12 @@ struct TypedVerilogRefinementMap : // ... ? void TraverseAllRfExpr(std::function func); - /// used by vtarget_gen to replace rtl/ila vars - RfExpr ReplacingRtlIlaVar(const RfExpr & in); - - /// Register internal variables and also the mapping - void RegisterInternalVariableWithMapping( - const std::string & n, - const VarReplacement & in) { var_replacement.emplace(n, in); } - - VarReplacement * CheckReplacement(const std::string & origname) { - auto pos = var_replacement.find(origname); - if(pos != var_replacement.end()) - return &(var_replacement.at(origname)); - return NULL; - } - - const std::map & - GetVarReplacement() const { return var_replacement; } - protected: - /// the replacement used for creating new wires - std::map var_replacement; // including rtl/ilas/ilav + // used in TypedVerilogRefinementMap::TypeInferTravserRfExpr + // this is only used in the first stage : aux var width determination + var_typecheck_t typechecker; + void initialize(); /// this function will not collect implicity vars diff --git a/include/ilang/rfmap-in/rfvar_type.h b/include/ilang/rfmap-in/rfvar_type.h index 0926eb07b..0a291c289 100644 --- a/include/ilang/rfmap-in/rfvar_type.h +++ b/include/ilang/rfmap-in/rfvar_type.h @@ -33,7 +33,7 @@ struct RfMapVarType { std::string to_string() const { if(is_unknown()) return "(unknown)"; - if(is_bv) + if(is_bv()) return "(_ BitVec " + std::to_string(width)+")"; return "(Array (_ BitVec " + std::to_string(addr_width)+") (_ BitVec " + std::to_string(data_width)+"))"; } diff --git a/src/rfmap-in/rfexpr_shortcut.cc b/src/rfmap-in/rfexpr_shortcut.cc index 68b633cff..f256295f1 100644 --- a/src/rfmap-in/rfexpr_shortcut.cc +++ b/src/rfmap-in/rfexpr_shortcut.cc @@ -7,6 +7,10 @@ namespace ilang { +rfmap::RfExpr rfmap_reduce_or(const rfmap::RfExpr & in) { + return verilog_expr::VExprAst::MakeUnaryAst(verilog_expr::voperator::B_OR, in); +} + rfmap::RfExpr rfmap_imply(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { return rfmap_or(rfmap_not(l), r); } @@ -39,7 +43,7 @@ rfmap::RfExpr rfmap_or(const std::vector &v) { rfmap::RfExpr rfmap_ite(const rfmap::RfExpr &c, const rfmap::RfExpr &l, const rfmap::RfExpr &r) { - return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::ITE, + return verilog_expr::VExprAst::MakeTernaryAst(verilog_expr::voperator::TERNARY, c, l, r); } @@ -48,7 +52,7 @@ rfmap::RfExpr rfmap_eq(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { } rfmap::RfExpr rfmap_le(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { - return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_LE, l, r); + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::LTE, l, r); } rfmap::RfExpr rfmap_not(const rfmap::RfExpr &l) { @@ -65,7 +69,7 @@ rfmap::RfExpr rfmap_const(unsigned b, unsigned w, unsigned v) { rfmap::RfExpr rfmap_var(const std::string &v) { if(StrStartsWith(v, "RTL.") || StrStartsWith(v, "ILA.")) return verilog_expr::VExprAst::MakeVar(v); - return verilog_expr::VExprAst::MakeSpecial(v); + return verilog_expr::VExprAst::MakeSpecialName(v); } diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc index 18a78963c..49551f287 100644 --- a/src/rfmap-in/rfexpr_to_smt.cc +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -77,8 +77,10 @@ static RfMapVarType get_type(const RfExpr & in) { static std::string smt_const(unsigned value, unsigned width) { auto ret = IntToStrCustomBase(value, 2, false); - if(ret.length() > width) + if(ret.length() > width) { + ILA_ERROR << "Creating SMT constant with value " << value << " width: " << width; throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + } std::string zero; if(width > ret.length()) @@ -174,6 +176,8 @@ std::string RfExpr2Smt::to_smt2_const(const std::shared_ptrget_constant(); auto width = std::get<1>(b_w_l); + if(width == 0) + width = expected_type.unified_width(); return type_convert(expected_type, SmtType(width), smt_const(out, width) ); } // to_smt2_const @@ -183,7 +187,8 @@ std::string RfExpr2Smt::to_smt2_var(const std::shared_ptrget_name().first+"|"; if(!tp.is_array()) ret = type_convert(expected_type, SmtType(tp.unified_width()), ret); - ILA_ASSERT(expected_type == SmtType(tp,false)); + else + ILA_ASSERT(expected_type == SmtType(tp,false)); return ret; } // to_smt2_var diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 33621c423..af1e9176b 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -21,7 +21,7 @@ std::string TypedVerilogRefinementMap::new_id() { TypedVerilogRefinementMap::TypedVerilogRefinementMap( const VerilogRefinementMap & refinement, var_typecheck_t type_checker - ) : VerilogRefinementMap(refinement), TypeAnalysisUtility(type_checker), + ) : VerilogRefinementMap(refinement), typechecker(type_checker), counter(0) { initialize(); } @@ -31,7 +31,7 @@ TypedVerilogRefinementMap::TypedVerilogRefinementMap( const std::string & instcond_json_file, var_typecheck_t type_checker ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), - TypeAnalysisUtility(type_checker), counter(0) { + typechecker(type_checker), counter(0) { initialize(); } // TypedVerilogRefinementMap::TypedVerilogRefinementMap @@ -54,10 +54,10 @@ void TypedVerilogRefinementMap::initialize() { // this function will iteratively make a new copy of the whole AST. -RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( +RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar( const RfExpr & in) { -#error "modify ReplExpr" + // skip state memory mapped // provide a function to ReplExpr... auto tp_annotate = in->get_annotation(); @@ -81,6 +81,7 @@ RfExpr TypedVerilogRefinementMap::ReplacingRtlIlaVar( ReplacingRtlIlaVar( ret_copy->get_child().at(idx)); } // for each child + return ret_copy; } // AnnotateSignalsAndCollectRtlVars @@ -511,18 +512,19 @@ void RfExprAstUtility::GetVars(const RfExpr & in, stack.push_back(std::make_pair(in, false)); while(!stack.empty()) { auto & back = stack.back(); + auto backvar = back.first; if(back.second) { stack.pop_back(); continue; } // back.second == false back.second = true; - for(const auto & c : back.first->get_child()) + for(const auto & c : backvar->get_child()) stack.push_back(std::make_pair(c, false)); - if(back.first->is_var()) { - ILA_ASSERT(back.first->get_child().size() == 0); + if(backvar->is_var()) { + ILA_ASSERT(backvar->get_child().size() == 0); verilog_expr::VExprAstVar::VExprAstVarPtr varptr = - std::dynamic_pointer_cast(back.first); + std::dynamic_pointer_cast(backvar); ILA_NOT_NULL(varptr); vars_out.emplace(varptr->get_name().first, varptr); } @@ -618,7 +620,7 @@ bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr & in) { // 3. this is used only in unit test void TypeAnalysisUtility::AnnotateType(const RfExpr & inout) { auto tp_annotate = inout->get_annotation(); -#error "modify smt expr out test" + if(inout->is_var()) { auto ptr = std::dynamic_pointer_cast (inout); ILA_CHECK(tp_annotate != nullptr && !tp_annotate->type.is_unknown()) diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 3bfa8048d..903ece37b 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -117,7 +117,6 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { rfmap_eq(rfmap_var(func_result_wire), result_apply)); std::vector prep; - std::string prep = VLG_TRUE; size_t arg_idx = 0; for (const auto & each_arg : arg_apply) { diff --git a/test/t_rfexpr_smt_out.cc b/test/t_rfexpr_smt_out.cc index 8928ac089..a5614eb17 100644 --- a/test/t_rfexpr_smt_out.cc +++ b/test/t_rfexpr_smt_out.cc @@ -14,12 +14,30 @@ namespace ilang { +class TypeVars { +public: + static rfmap::RfExpr GiveVarTheirTypes(const rfmap::RfExpr & inout, rfmap::TypeAnalysisUtility::var_typecheck_t checker) { + rfmap::RfExprVarReplUtility repl; + + std::unordered_map vars; + rfmap::RfExprAstUtility::GetVars(inout, vars); + for(const auto & v : vars ) { + auto tp = checker(v.first); + auto newv = verilog_expr::VExprAst::MakeSpecialName(v.first); + auto newtp_ptr = std::make_shared(tp); + newv->set_annotation(newtp_ptr); + repl.RegisterInternalVariableWithMapping(v.first, rfmap::VarReplacement(v.second, newv)); + } + return repl.ReplacingRtlIlaVar(inout); + } +}; #define PRINT_SMT(s, b) do { \ std::string rfstr = (s); \ auto rfexpr = rfmap::VerilogRefinementMap::ParseRfExprFromString(rfstr); \ + rfexpr = TypeVars::GiveVarTheirTypes(rfexpr, check_var_type); \ annotator.AnnotateType(rfexpr); \ - std::cout << rfmap::RfExpr2Smt::to_smt2(rfexpr, \ + ILA_DLOG("SMTOUT.TEST") << rfmap::RfExpr2Smt::to_smt2(rfexpr, \ (b) ? rfmap::SmtType() : \ rfmap::SmtType( (rfexpr->get_annotation())->type, false )) \ << std::endl; \ @@ -49,7 +67,7 @@ TEST(TestRfexpr, ToSmt) { return ret; }; - rfmap::TypeAnalysisUtility annotator(check_var_type); + rfmap::TypeAnalysisUtility annotator; PRINT_SMT("a[4] == b[4]" , true); // should be (extract) diff --git a/test/t_verilog_mod.cc b/test/t_verilog_mod.cc index 633dd3731..0aea8217c 100644 --- a/test/t_verilog_mod.cc +++ b/test/t_verilog_mod.cc @@ -42,9 +42,9 @@ TEST(TestVerilogMod, Modify) { vm.RecordKeepSignalName("m1.__COUNTER_start__n3"); vm.RecordKeepSignalName("m1.__ILA_proc_decode_of_Add__"); vm.RecordKeepSignalName("m1.subm4.a"); - vm.RecordConnectSigName("m1.subm4.b"); - vm.RecordConnectSigName("m1.n27"); - vm.RecordConnectSigName("m1.ir"); + vm.RecordConnectSigName("m1__DOTz__subm4__DOTz__b", "m1.subm4","b",1); + vm.RecordConnectSigName("m1__DOTz__n27z","m1","n27",1); + vm.RecordConnectSigName("m1__DOT__orz_ir_0_","m1","ir[0]", 8); vm.RecordAdditionalVlgModuleStmt("wire abcd; assign abcd = 1'b1;", "m1"); vm.FinishRecording(); @@ -57,7 +57,7 @@ TEST(TestVerilogMod, Modify) { } if (!fout.is_open()) { - ILA_ERROR << ofn << " is not readable"; + ILA_ERROR << ofn << " is not write-able"; return; } @@ -65,6 +65,7 @@ TEST(TestVerilogMod, Modify) { fin.close(); fout.close(); + os_portable_remove_file(ofn); } From 6d597aadad2e29740d14abfb1d5deeeafa00c2dd Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 20 Aug 2021 14:08:05 +0800 Subject: [PATCH 32/78] vpipe test debug --- include/ilang/rfmap-in/rfexpr_shortcut.h | 4 +- include/ilang/rfmap-in/rfmap_typecheck.h | 13 ++- include/ilang/vtarget-out/vtarget_gen.h | 9 +- src/rfmap-in/rfexpr_shortcut.cc | 10 +- src/rfmap-in/rfmap_typecheck.cc | 12 +++ src/rfmap-in/verilog_rfmap.cc | 20 ++-- src/verilog-out/verilog_gen.cc | 1 + src/vtarget-out/gen_util.cc | 13 ++- src/vtarget-out/single_target.cc | 19 +++- src/vtarget-out/single_target_as.cc | 19 +++- src/vtarget-out/single_target_cond.cc | 2 +- src/vtarget-out/single_target_connect.cc | 6 -- src/vtarget-out/single_target_misc.cc | 20 ++-- src/vtarget-out/vtarget_gen_pono.cc | 20 +++- test/t_vtarget_gen.cc | 1 - test/unit-data/vpipe/rfmap/cond-noinv.json | 8 -- .../vpipe/rfmap/cond-rfmap-pvholder.json | 42 ++++---- test/unit-data/vpipe/rfmap/cond.note | 2 - .../vpipe/rfmap/vmap-rfmap-pvholder.json | 97 ++++++++++--------- test/unit-data/vpipe/rfmap/vmap.json | 1 - test/unit-data/vpipe/rfmap/vmap.note | 24 ----- 21 files changed, 193 insertions(+), 150 deletions(-) delete mode 100644 test/unit-data/vpipe/rfmap/cond.note delete mode 100644 test/unit-data/vpipe/rfmap/vmap.note diff --git a/include/ilang/rfmap-in/rfexpr_shortcut.h b/include/ilang/rfmap-in/rfexpr_shortcut.h index c940bfce9..4f86d49c8 100644 --- a/include/ilang/rfmap-in/rfexpr_shortcut.h +++ b/include/ilang/rfmap-in/rfexpr_shortcut.h @@ -26,7 +26,9 @@ rfmap::RfExpr rfmap_le(const rfmap::RfExpr &l, const rfmap::RfExpr &r); rfmap::RfExpr rfmap_not(const rfmap::RfExpr &l); -rfmap::RfExpr rfmap_const(unsigned w, unsigned b, unsigned v); +rfmap::RfExpr rfmap_true(); +rfmap::RfExpr rfmap_false(); +rfmap::RfExpr rfmap_const(unsigned b, unsigned w, unsigned v); /// if it is RTL. or ILA. then will use MakeVar /// otherwise will use MakeSpecial /// will not determine its type diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index 91087d918..301badfab 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -117,7 +117,8 @@ class RfExprAstUtility { /// will modify where the pointer is pointing to /// because we will be creating new rfexpr static void TraverseRfExpr(RfExpr & inout, std::function func) ; - + /// check to make sure no null ptr + static void RfMapNoNullNode(const RfExpr & in); }; struct RfExprVarReplUtility { @@ -193,6 +194,12 @@ struct TypedVerilogRefinementMap : // ... ? void TraverseAllRfExpr(std::function func); + // this function is used in + // (1) value holder/delay : width determination + // will use all_var_def_types & typechecker + // (2) vlg-monitor replace-var + RfMapVarType TypeInferTravserRfExpr(const RfExpr & in); + protected: // used in TypedVerilogRefinementMap::TypeInferTravserRfExpr @@ -228,10 +235,6 @@ struct TypedVerilogRefinementMap : void collect_inline_delay_func(RfExpr & inout); // this function uses the above two and the void CollectInlineDelayValueHolder(); - - // this function is used in value holder/delay : width determination - // will use all_var_def_types - RfMapVarType TypeInferTravserRfExpr(const RfExpr & in); void ComputeDelayValueHolderWidth(); diff --git a/include/ilang/vtarget-out/vtarget_gen.h b/include/ilang/vtarget-out/vtarget_gen.h index 9c9ccaf49..5dee2e372 100644 --- a/include/ilang/vtarget-out/vtarget_gen.h +++ b/include/ilang/vtarget-out/vtarget_gen.h @@ -103,6 +103,10 @@ class VlgVerifTgtGenBase { /// For Pono backend: do we add (* keep *)? default true, however, it can be /// buggy, so you can disable it if you want bool PonoAddKeep; + /// For Pono backend: the default engine (ind by default) + /// other options: like bmc, bmc-sp, ind, interp, mbic3, + /// ic3bits, ic3ia, msat-ic3ia, ic3sa, sygus-pdr + std::string PonoEngine; /// For Pono backend: what more options to add std::string PonoOtherOptions; /// whether to force dot reference check in the generation @@ -221,8 +225,9 @@ class VlgVerifTgtGenBase { // ----------- Options for Pono settings -------------- // ForceInstCheckReset(false), PortDeclStyle(PortDeclStyleT::AUTO), - PonoGenJgTesterScript(false), PonoAddKeep(false), - PonoOtherOptions(""), + PonoGenJgTesterScript(false), PonoVcdOutputName("cex.vcd"), + PonoAddKeep(false), + PonoEngine("ind"), PonoOtherOptions(""), PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), MaxBound(127), OnlyAssumeUpdatedVarsEq(false), diff --git a/src/rfmap-in/rfexpr_shortcut.cc b/src/rfmap-in/rfexpr_shortcut.cc index f256295f1..59de905af 100644 --- a/src/rfmap-in/rfexpr_shortcut.cc +++ b/src/rfmap-in/rfexpr_shortcut.cc @@ -59,8 +59,16 @@ rfmap::RfExpr rfmap_not(const rfmap::RfExpr &l) { return verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, l); } +rfmap::RfExpr rfmap_true() { + return verilog_expr::VExprAst::MakeConstant(2,1,"1"); +} + +rfmap::RfExpr rfmap_false() { + return verilog_expr::VExprAst::MakeConstant(2,1,"0"); +} + rfmap::RfExpr rfmap_const(unsigned b, unsigned w, unsigned v) { - return verilog_expr::VExprAst::MakeConstant(w, b, IntToStrCustomBase(v, b, false)); + return verilog_expr::VExprAst::MakeConstant(b, w, IntToStrCustomBase(v, b, false)); } /// if it is RTL. or ILA. then will use MakeVar /// otherwise will use MakeSpecial diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index af1e9176b..645bff79e 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -163,6 +163,12 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { for (const auto & var_def : n_st.second.var_defs ) { all_var_def_types.emplace(var_def.first, var_def.second); } + for (const auto & stage : n_st.second.rules) { + VarDef tmp; + tmp.type = VarDef::var_type::REG; + tmp.width = 1; + all_var_def_types.emplace(stage.stage_name, tmp); + } } for (const auto & n_st : value_recorder) { VarDef tmp; @@ -555,6 +561,12 @@ bool RfExprAstUtility::HasArrayVar( return has_array; } +void RfExprAstUtility::RfMapNoNullNode(const RfExpr & in) { + ILA_NOT_NULL(in); + size_t cnt = in->get_child_cnt(); + for(size_t idx = 0; idx < cnt; ++idx) + RfMapNoNullNode(in->child(idx)); +} void RfExprAstUtility::TraverseRfExpr(RfExpr & inout, std::function func) { // DFS -- Note: we need to call func on the parent's child diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index f5e58cab3..d2d7ff18f 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -380,7 +380,9 @@ std::string JsonRfMapParseVarDefs(std::mapis_array(), "`rules` field should be list of objects"); + size_t sidx = 0; for(auto & stage : *rules) { - ENSURE(rules->is_object(), "`rules` field should be list of objects"); + ENSURE(stage.is_object(), "`rules` field should be list of objects"); auto * enter = GetJsonSection(stage, {"enter"}); auto * exit = GetJsonSection(stage, {"exit"}); auto * stage_name = GetJsonSection(stage, {"name"}); @@ -423,7 +426,9 @@ std::string JsonRfmapParsePhaseTracker(PhaseTracker & tracker, nlohmann::json & auto & ws = tracker.rules.back(); if(stage_name) { ENSURE(stage_name->is_string(), "`name` of a phase should be string"); - ws.stage_name = stage_name->get(); + ws.stage_name = tracker_name+"_"+stage_name->get(); + } else { + ws.stage_name = tracker_name + "_stage" + std::to_string(sidx++); } ws.enter_rule = ParseRfMapExprJson(*enter_event); ws.exit_rule = ParseRfMapExprJson(*exit_event); @@ -735,7 +740,7 @@ VerilogRefinementMap::VerilogRefinementMap for (auto & elem : invocations) { ENSURE(elem.is_object(), "Expect `functions` to be map:name->list of invocation(object)"); auto * result = GetJsonSection(elem,{"result"}); - auto * arg = GetJsonSection(elem, {"arg"}); + auto * arg = GetJsonSection(elem, {"arg","args"}); ENSURE(result && arg, "Expect invocation object has `result` and `arg` field"); ENSURE(result->is_string(), "Expect type string in `result` field of invocation object"); ENSURE(arg->is_array(), "Expect type list(string) in `arg` field of invocation object"); @@ -787,7 +792,8 @@ VerilogRefinementMap::VerilogRefinementMap auto template_name = template_field->get(); if(SectionNameRelaxedMatch(template_name,"phase tracker")) { phase_tracker.emplace(name, PhaseTracker()); - std::string errmsg = JsonRfmapParsePhaseTracker(phase_tracker.at(name), monitor); + std::string errmsg = JsonRfmapParsePhaseTracker( + phase_tracker.at(name), monitor, name); ENSURE(errmsg.empty(), errmsg); } else if (SectionNameRelaxedMatch(template_name,"value recorder")) { value_recorder.emplace(name, ValueRecorder()); @@ -844,7 +850,7 @@ VerilogRefinementMap::VerilogRefinementMap if(verilog_field) { if( verilog_field->is_string() ) { - mnt_ref.verilog_append = verilog_field->get(); + mnt_ref.verilog_append = verilog_field->get() + "\n"; } else { ENSURE(verilog_field->is_array() , "`append-verilog` field should be a list of string" ); for (auto & ps : *verilog_field) { @@ -860,7 +866,7 @@ VerilogRefinementMap::VerilogRefinementMap { std::stringstream buffer; buffer << fin.rdbuf(); - mnt_ref.verilog_append = buffer.str(); + mnt_ref.verilog_append = buffer.str() + "\n"; } } // append-verilog_file_field : from file } // verilog_append verilog diff --git a/src/verilog-out/verilog_gen.cc b/src/verilog-out/verilog_gen.cc index d08894462..6751c58ec 100644 --- a/src/verilog-out/verilog_gen.cc +++ b/src/verilog-out/verilog_gen.cc @@ -213,6 +213,7 @@ int VerilogGeneratorBase::get_width(const ExprPtr& n) { } /// convert a widith to a verilog string std::string VerilogGeneratorBase::WidthToRange(int w) { + ILA_ERROR_IF(w==0) << "Width should be > 0 !"; if (w > 1) return std::string("[") + toStr(w - 1) + ":0]"; return ""; diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index eac059616..f57c5fa90 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -274,6 +274,10 @@ rfmap::VarReplacement VlgSglTgtGen::CreateVarReplacement( tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::INTERNAL || tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR ) { + ILA_ERROR_IF(StrStartsWith(n.first,"$")) << "Creating non replace-able var " << n.first; + if(var->get_annotation() == nullptr) { + var->set_annotation(std::make_shared(tp)); + } return rfmap::VarReplacement(var, var); } @@ -301,7 +305,7 @@ rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr & in) { repl = refinement_map.CheckReplacement(v.first); } ILA_NOT_NULL(repl); - ILA_DLOG("gen_util.create_var_replacement") << repl->origvar->to_verilog() + ILA_DLOG("gen_util.use_var_replacement") << repl->origvar->to_verilog() << " --> " << repl->newvar->to_verilog(); } @@ -408,9 +412,7 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, }while(0) bool is_mem = _host->state(ila_state_name)->is_mem(); - if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { - ILA_ERROR_IF(!is_mem) - << "ila sv " << ila_state_name << " is not memory!"; + if(vmap.type != rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { auto map_str = singlemap_to_rfexpr(vmap.single_map, ila_state_name); ADD_CONSTR(map_str); } else { @@ -420,6 +422,9 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, // ( ila.ren && rtl.renexpr && (ila.raddr == rtl.raddrexpr) |-> // (ila.rdata === rtl.rdataexpr) ) + ILA_ERROR_IF(!is_mem) + << "ila sv " << ila_state_name << " is not memory!"; + if(true_for_assumpt_false_for_assert) { // mem read assumption const auto & read_ports = vlg_ila.ila_rports.at(ila_state_name); diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index f25113701..462b66991 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -164,13 +164,13 @@ void VlgSglTgtGen::ConstructWrapper_add_inputmap_assumptions() { for (const auto & iv_rfmap : refinement_map.ila_input_var_map) { const auto & iname = iv_rfmap.first; - if(ila_input_names.find(iname) != ila_input_names.end()) { + if(ila_input_names.find(iname) == ila_input_names.end()) { ILA_ERROR << "Cannot find ILA input with name: " << iname; continue; } ila_input_names.erase(iname); - Gen_input_map_assumpt(iname, iv_rfmap.second, "variable_map_assume_"); + Gen_input_map_assumpt(iname, iv_rfmap.second, "input_map_assume_"); } if(!ila_input_names.empty()) { @@ -325,6 +325,8 @@ void VlgSglTgtGen::ConstructWrapper() { ILA_DLOG("VtargetGen") << "STEP:" << 5; if (target_type == target_type_t::INSTRUCTIONS) { + ILA_DLOG("VtargetGen") << "STEP:" << 5.1; + ConstructWrapper_add_inputmap_assumptions(); ILA_DLOG("VtargetGen") << "STEP:" << 5.2; ConstructWrapper_add_varmap_assumptions(); ILA_DLOG("VtargetGen") << "STEP:" << 5.3; @@ -364,6 +366,12 @@ void VlgSglTgtGen::ConstructWrapper() { if (target_type == target_type_t::INSTRUCTIONS) ConstructWrapper_add_uf_constraints(); + // instantiate ila module + if (target_type == target_type_t::INSTRUCTIONS) { + auto ila_mod_inst = ConstructWrapper_get_ila_module_inst(); + vlg_wrapper.add_stmt(ila_mod_inst); + } + // read assumption/assertion, decide where to put them rtl/smt // perform the reg[n] optimize // populate the RtlExtraWire data structure @@ -400,8 +408,13 @@ void VlgSglTgtGen::Export_wrapper(const std::string& wrapper_name) { for(const auto & vlg_monitor : refinement_map.customized_monitor) { if(vlg_monitor.second.verilog_append.empty()) continue; - fout << "/***** Monitor for " << vlg_monitor.first << " *****/\n"; + if(!vlg_monitor.second.keep_for_invariant && + target_type != target_type_t::INSTRUCTIONS) + continue; + + fout << "/***** BEGIN of Monitor for " << vlg_monitor.first << " *****/\n"; fout << vlg_monitor.second.verilog_append; + fout << "/***** END of Monitor for " << vlg_monitor.first << " *****/\n"; } } diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index 0684ee787..c7c521c81 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -27,7 +27,9 @@ void VlgSglTgtGen::add_reg_cassign_assumption(const std::string& varname, int width, const rfmap::RfExpr& cond, const std::string& dspt) { - + rfmap::RfExprAstUtility::RfMapNoNullNode(expression); + rfmap::RfExprAstUtility::RfMapNoNullNode(cond); + std::string rand_in_name = "__" + varname + "_init__"; vlg_wrapper.add_input(rand_in_name, width); vlg_wrapper.add_wire(rand_in_name, width); @@ -43,6 +45,8 @@ void VlgSglTgtGen::add_smt_assumption( const rfmap::RfExpr & body, const std::string & dspt) { + rfmap::RfExprAstUtility::RfMapNoNullNode(body); + std::unordered_map vars; rfmap::RfExprAstUtility::GetVars(body, vars); @@ -64,6 +68,8 @@ void VlgSglTgtGen::add_smt_assertion( const rfmap::RfExpr & body, const std::string & dspt) { + rfmap::RfExprAstUtility::RfMapNoNullNode(body); + std::unordered_map vars; rfmap::RfExprAstUtility::GetVars(body, vars); @@ -83,12 +89,15 @@ void VlgSglTgtGen::add_smt_assertion( void VlgSglTgtGen::add_an_assumption(const rfmap::RfExpr& aspt, const std::string& dspt) { + + rfmap::RfExprAstUtility::RfMapNoNullNode(aspt); all_assumptions[dspt].push_back(aspt); } /// Add an assertion -- JasperGold will override this void VlgSglTgtGen::add_an_assertion(const rfmap::RfExpr& asst, const std::string& dspt) { + rfmap::RfExprAstUtility::RfMapNoNullNode(asst); all_assertions[dspt].push_back(asst); } @@ -120,7 +129,7 @@ static void find_and_replace_array_const( inout->child(1)->is_constant() && rfmap::RfExprAstUtility::GetType(inout->child(0)).type.is_array() ) { - auto hier_name = inout->to_verilog(); + auto hier_name = inout->child(0)->to_verilog(); auto cnst = const_to_unified_str(inout->child(1)); if(cnst == "error" ) // if cannot convert return; @@ -163,6 +172,8 @@ static void find_and_replace_array_const( void VlgSglTgtGen::add_wire_assign_assumption(const std::string& varname, const rfmap::RfExpr &aspt, const std::string& dspt) { + + rfmap::RfExprAstUtility::RfMapNoNullNode(aspt); assign_or_assumptions.push_back(std::make_tuple(dspt, varname, aspt, nullptr)); } @@ -180,8 +191,10 @@ void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_conne } // for each assign/assumption for(auto & dspt_aspt : all_assumptions) { - for(auto & aspt : dspt_aspt.second) + for(auto & aspt : dspt_aspt.second) { + aspt = ReplExpr(aspt); + } } for (auto & dspt_asst : all_assertions) { diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index b191c6e9d..abd065033 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -172,7 +172,7 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { } // max bound for max checking range - rfmap::RfExpr max_bound_constr; + rfmap::RfExpr max_bound_constr = rfmap_true(); if(instr.max_bound != 0) { max_bound_constr = rfmap_le( rfmap_var("__CYCLE_CNT__"), rfmap_const(10, cnt_width, instr.max_bound)); diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index f98631705..dc27d37a4 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -319,12 +319,6 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_input_output() { // ------------------------ ALL instantiation ----------------------------- // void VlgSglTgtGen::ConstructWrapper_add_module_instantiation() { - // instantiate ila module - if (target_type == target_type_t::INSTRUCTIONS) { - auto ila_mod_inst = ConstructWrapper_get_ila_module_inst(); - vlg_wrapper.add_stmt(ila_mod_inst); - } - // instantiate verilog module std::string verilog_inst_str = vlg_info_ptr->get_top_module_name() + " " + _vlg_mod_inst_name + "(\n"; diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 903ece37b..74e4407fc 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -169,6 +169,7 @@ void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { add_wire_assign_assumption(prev_name, rhs, "delay_unit"); } vlg_wrapper.add_always_stmt(curr_name + " <= " + prev_name + " ;"); + vlg_wrapper.add_init_stmt(curr_name + "<= 0;"); if(didx == du.num_cycle) last_reg = curr_name; } // end - for each delay @@ -194,6 +195,7 @@ void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { auto curr_name = name+"_d_"+std::to_string(didx); auto prev_name = name+"_d_"+std::to_string(didx-1); vlg_wrapper.add_reg(curr_name, 1); + vlg_wrapper.add_init_stmt(curr_name + " <= 0;"); vlg_wrapper.add_always_stmt(curr_name + " <= " + prev_name + " ;"); or_reduce += " || " + curr_name; @@ -224,10 +226,8 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { } unsigned sidx = 0; for (const auto & stage : tracker.rules) { - std::string stage_name = tracker_name + "_" + - ( stage.stage_name.empty() ? - "stage" + std::to_string(sidx) : - stage.stage_name); + const std::string & stage_name = stage.stage_name; + ILA_CHECK(!stage_name.empty()) << "stage name is empty for " << tracker_name; vlg_wrapper.add_reg(stage_name , 1); std::string enter_cond_wire_name = stage_name + "_enter_cond"; @@ -235,6 +235,7 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { std::string enter_action_wire_name = stage_name + "_enter_action"; std::string exit_action_wire_name = stage_name + "_exit_action"; + vlg_wrapper.add_init_stmt(stage_name + "<= 1'b0;"); vlg_wrapper.add_always_stmt("if(" + enter_cond_wire_name + ") begin " + stage_name + " <= 1'b1;" ); vlg_wrapper.add_wire(enter_cond_wire_name, 1, true); rfmap_add_internal_wire(enter_cond_wire_name, 1); @@ -328,14 +329,17 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { unsigned idx = 0; std::vector> replace_list; for (const auto & vref : mdef.var_uses) { - auto vref_node = ::verilog_expr::VExprAst::MakeVar(vref); + + auto vref_node = rfmap::VerilogRefinementMap::ParseRfExprFromString(vref); auto new_name = mname + "_auxvar" + std::to_string(idx ++); - auto tp = VarTypeCheckForRfExprParsing(vref); - ILA_ERROR_IF(tp.type.is_unknown()) << "Cannot determine width of " + + auto tp = refinement_map.TypeInferTravserRfExpr(vref_node); + + ILA_ERROR_IF(tp.is_unknown()) << "Cannot determine width of " << vref << " in monitor " << mname; - auto width = tp.type.unified_width(); + auto width = tp.unified_width(); vlg_wrapper.add_wire(new_name, width, true); rfmap_add_internal_wire(new_name, width); add_wire_assign_assumption(new_name, vref_node, "monitor_auxvar"); diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index da2ebe648..107f7f107 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -51,12 +51,20 @@ VlgSglTgtGen_Pono::VlgSglTgtGen_Pono( /// Add an assumption void VlgSglTgtGen_Pono::add_a_direct_assumption(const std::string& aspt, const std::string& dspt) { - _problems.assumptions[dspt].exprs.push_back(aspt); + auto wire_name = dspt + new_property_id(); + vlg_wrapper.add_wire(wire_name,1); + vlg_wrapper.add_output(wire_name,1); + vlg_wrapper.add_assign_stmt(wire_name, aspt); + _problems.assumptions[dspt].exprs.push_back(wire_name); } /// Add an assertion void VlgSglTgtGen_Pono::add_a_direct_assertion(const std::string& asst, const std::string& dspt) { - _problems.assertions[dspt].exprs.push_back(asst); + auto wire_name = dspt + new_property_id(); + vlg_wrapper.add_wire(wire_name,1); + vlg_wrapper.add_output(wire_name,1); + vlg_wrapper.add_assign_stmt(wire_name, asst); + _problems.assertions[dspt].exprs.push_back(wire_name); } /// export the script to run the verification @@ -86,6 +94,8 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { if (!_vtg_config.PonoVcdOutputName.empty()) options += " --vcd " + _vtg_config.PonoVcdOutputName; + if (!_vtg_config.PonoEngine.empty()) + options += " -e " + _vtg_config.PonoEngine; options += " " + _vtg_config.PonoOtherOptions; // no need, copy is good enough @@ -96,7 +106,7 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { pono = os_portable_append_dir(_vtg_config.PonoPath, pono); } - fout << pono << " problem.btor2 " << std::endl; + fout << pono << options << " problem.btor2 " << std::endl; } @@ -211,9 +221,9 @@ void VlgSglTgtGen_Pono::PreExportProcess() { // there should be only one expression (for cex target) // ILA_CHECK(all_assert_wire_content.empty()); if (all_assert_wire_content.empty()) - all_assert_wire_content = p; + all_assert_wire_content = "(" + p + ")"; else - all_assert_wire_content += " && " + p; + all_assert_wire_content += " && (" + p + ")"; } // for expr } // for problem // add assert wire (though no use : make sure will not optimized away) diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index 8c8f850d7..feba97bcc 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -34,7 +34,6 @@ TEST(TestVlgTargetGen, PipeExample) { vtg_config); EXPECT_FALSE(vg.in_bad_state()); - vg.GenerateTargets(); } diff --git a/test/unit-data/vpipe/rfmap/cond-noinv.json b/test/unit-data/vpipe/rfmap/cond-noinv.json index b3f4464f9..ea6e9afea 100644 --- a/test/unit-data/vpipe/rfmap/cond-noinv.json +++ b/test/unit-data/vpipe/rfmap/cond-noinv.json @@ -1,28 +1,20 @@ { - "target ILA": "vlg-gen/pipe.v:simpePipe", - "target Verilog": "verilog/simple_pipe.v:pipeline_v", - - "global invariants": [], "instructions": [ { "instruction": "NOP", - "ready signal": [], "ready bound": 1 }, { "instruction": "ADD", - "ready signal": [], "ready bound": 1 }, { "instruction": "SUB", - "ready signal": [], "ready bound": 1 }, { "instruction": "AND", - "ready signal": [], "ready bound": 1 } ] diff --git a/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder.json b/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder.json index a3c5b6353..8a2f1bcf6 100644 --- a/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder.json +++ b/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder.json @@ -1,42 +1,40 @@ { - "target ILA": "vlg-gen/pipe.v:simpePipe", - "target Verilog": "verilog/simple_pipe.v:pipeline_v", // this is a comment "global invariants": [ - "(! (m1.reg_0_w_stage == 2'b00 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd0) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd0) ) )", - "(! (m1.reg_1_w_stage == 2'b00 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd1) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd1) ) )", - "(! (m1.reg_2_w_stage == 2'b00 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd2) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd2) ) )", - "(! (m1.reg_3_w_stage == 2'b00 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd3) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd3) ) )", - "(! (m1.reg_0_w_stage == 2'b10 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd0) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd0) ) )", - "(! (m1.reg_1_w_stage == 2'b10 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd1) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd1) ) )", - "(! (m1.reg_2_w_stage == 2'b10 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd2) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd2) ) )", - "(! (m1.reg_3_w_stage == 2'b10 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd3) ) && ( (m1.ex_wb_reg_wen == 0) || (m1.ex_wb_rd != 2'd3) ) )", - "(! (m1.reg_0_w_stage == 2'b11 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd0) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd0) ) )", - "(! (m1.reg_1_w_stage == 2'b11 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd1) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd1) ) )", - "(! (m1.reg_2_w_stage == 2'b11 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd2) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd2) ) )", - "(! (m1.reg_3_w_stage == 2'b11 ) ) || ( ( (m1.id_ex_reg_wen == 1) && (m1.id_ex_rd == 2'd3) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd3) ) )", - "(! (m1.reg_0_w_stage == 2'b01 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd0) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd0) ) )", - "(! (m1.reg_1_w_stage == 2'b01 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd1) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd1) ) )", - "(! (m1.reg_2_w_stage == 2'b01 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd2) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd2) ) )", - "(! (m1.reg_3_w_stage == 2'b01 ) ) || ( ( (m1.id_ex_reg_wen == 0) || (m1.id_ex_rd != 2'd3) ) && ( (m1.ex_wb_reg_wen == 1) && (m1.ex_wb_rd == 2'd3) ) )" + " (RTL.reg_0_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd0) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd1) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd2) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd3) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd0) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd1) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd2) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd3) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd0) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd1) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd2) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd3) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd0) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd1) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd2) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd3) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd3) ) )" ], "instructions": [ { "instruction": "NOP", - "ready signal": ["#stage_tracker# == 2"] + "ready signal": "#stage_tracker# == 2" }, { "instruction": "ADD", - "ready signal": ["#stage_tracker# == 2"] + "ready signal": "#stage_tracker# == 2" }, { "instruction": "SUB", - "ready signal": ["#stage_tracker# == 2"] + "ready signal": "#stage_tracker# == 2" }, { "instruction": "AND", - "ready signal": ["#stage_tracker# == 2"] + "ready signal": "#ppl_stage_wb# ## 1" } ] } diff --git a/test/unit-data/vpipe/rfmap/cond.note b/test/unit-data/vpipe/rfmap/cond.note deleted file mode 100644 index 92ffbbc38..000000000 --- a/test/unit-data/vpipe/rfmap/cond.note +++ /dev/null @@ -1,2 +0,0 @@ - - "monitor" : "monitor1", diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json index 975c912d9..5a5e410f4 100644 --- a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json @@ -1,79 +1,84 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, - "instruction mapping": [], "state mapping": { - "r0":[ ["__START__", "#r0_pvholder#"] , ["1'b1", "m1.registers[0]"] ] , - "r1":[ ["__START__", "#r1_pvholder#"] , ["1'b1", "m1.registers[1]"] ] , - "r2":[ ["__START__", "#r2_pvholder#"] , ["1'b1", "m1.registers[2]"] ] , - "r3":[ ["__START__", "#r3_pvholder#"] , ["1'b1", "m1.registers[3]"] ] }, + "r0":[ ["__START__", "#r0_pvholder#"] , ["1'b1", "RTL.registers[0]"] ] , + "r1":[ ["__START__", "RTL.registers[1] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[1]"] ] , + "r2":[ ["__START__", "RTL.registers[2] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[2]"] ] , + "r3":[ ["__START__", "RTL.registers[3] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[3]"] ] }, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "inst":"inst", - "dummy_read_rf":"**KEEP**", - "dummy_rf_data":"**KEEP**" + + "input mapping": { + "inst":"RTL.inst" }, - "value-holder": { - "r0_pvholder" : [ { - "cond": "#stage_tracker# == 1 && 1 == 0", - "val":"m1.registers[0]", - "width":"auto" - }, - { - "cond": "#stage_tracker# == 1 && 1 == 1", - "val":"m1.registers[0]" - } - ], - "r1_pvholder" : { - "cond": "#stage_tracker# == 1", - "val":"m1.registers[1]", - "width":8 - }, - "r2_pvholder" : { - "cond": "#stage_tracker# == 1", - "val":"m1.registers[2]", - "width":8 - }, - "r3_pvholder" : { - "cond": "#stage_tracker# == 1", - "val":"m1.registers[3]", - "width":8 - } + "rtl-interface-connection" : { + "CLOCK" : "clk", + "RESET" : "rst" }, - "verilog-inline-monitors" : { + + "monitor" :{ + // monitor 1 : value recorder + "r0_pvholder" : { // this is just a name + "template" : "value recorder", + "cond": "#stage_tracker# == 1", + "val":"RTL.registers[0]" + }, + + // monitor 2 : arb verilog - stage tracker and append verilog "stage_tracker" : { "verilog": ["always @(posedge clk) begin", " if (__START__) stage_tracker <= 0;", " else if (__STARTED__ && !__ENDED__) stage_tracker <= stage_tracker + 1;", "end"], + "append-verilog" : "module nouse2(input wire a, output wire b); assign b=a; endmodule", "defs" :[ ["stage_tracker", 2, "reg"] ], "refs" :[] }, + // monitor 3 : ref/def test "ref_test" : { "verilog": ["always @(posedge clk) begin", " if (__START__) ref_test <= 0;", - " else if (__STARTED__ && !__ENDED__ && stage_tracker == 1) ref_test <= m1.registers[0] + 1;", + " else if (__STARTED__ && !__ENDED__ && stage_tracker == 1) ref_test <= RTL.registers[0] + 1;", "end"], "defs" :[ ["ref_test", 2, "reg"] ], - "refs" :[ "m1.registers[0]" ] + "refs" :[ "RTL.registers[0]" ] }, - + // a monitor that always exists "delay_wb_write" : { "verilog": [ "always @(posedge clk) begin", - " delay_wb_write <= m1.ex_wb_val;", + " delay_wb_write <= RTL.ex_wb_val;", "end" ], + "append-verilog" : [ + "module nouse(input wire aa, output wire bb);", + " /*keep-for-invariants*/ assign bb=aa;", + " endmodule"], "defs" :[ ["delay_wb_write", 8, "reg"] ], - "refs" :[ "m1.ex_wb_val" ], + "refs" :[ "RTL.ex_wb_val" ], "keep-for-invariants" : true - } + }, + + // pipeline tracker + "ppl_stage" : { + "template" : "phase tracker", + "rules" : [ + { // + "name" : "ex", + "enter" : {"event" : "#decode#"}, + "exit" : {"event" : "1"} + }, + + { // + "name" : "wb", + "enter" : {"event" : "#ppl_stage_ex#"}, + "exit" : {"event" : "1"} + } + ] - }// end of monitor + } + } } diff --git a/test/unit-data/vpipe/rfmap/vmap.json b/test/unit-data/vpipe/rfmap/vmap.json index 26f0744d2..b05df3daa 100644 --- a/test/unit-data/vpipe/rfmap/vmap.json +++ b/test/unit-data/vpipe/rfmap/vmap.json @@ -1,5 +1,4 @@ { - "instruction mapping": [], "state mapping": { "r0": [ [" RTL.reg_0_w_stage == 2'b10 ", " RTL.ex_alu_result == ILA.r0"], diff --git a/test/unit-data/vpipe/rfmap/vmap.note b/test/unit-data/vpipe/rfmap/vmap.note deleted file mode 100644 index f430c23f9..000000000 --- a/test/unit-data/vpipe/rfmap/vmap.note +++ /dev/null @@ -1,24 +0,0 @@ - -// additional mapping -"wr" : "**KEEP**" // by default -"addr": "cmd_addr" -"data_in": "cmd_data" -"data_out": "**SO**" -"ack": "**KEEP**" -"stb": "**KEEP**" - -"xram_ack":"**KEEP**" -"xram_data_out":"**MEM**xram.wdata" -"xram_addr":"**MEM**xram.waddr" -"xram_wr":"**KEEP**" -"xram_stb":"**KEEP**" -// add invariant: (xram_wr&xram_stb) == xram.w_en -// you need to create memory -"xram_addr": "**MEM**xram.raddr.0" -"xram_data_in": "**MEM**xram.rdata.0" - - -"aes_state":"**SO**" -"aes_addr":"**SO**" - -"mapping control" :["(xram_wr&xram_stb) == MEM_xram.wen"] From ec80c096fbf0230d92bbcb0ee86bb49f3dbb638f Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sat, 28 Aug 2021 18:07:41 +0800 Subject: [PATCH 33/78] im smt property WIP --- include/ilang/rfmap-in/verilog_rfmap.h | 2 +- .../verilog-in/verilog_analysis_wrapper.h | 8 +- include/ilang/verilog-out/verilog_gen.h | 8 +- include/ilang/vtarget-out/vtarget_gen.h | 23 ++- include/ilang/vtarget-out/vtarget_gen_impl.h | 11 +- .../ilang/vtarget-out/vtarget_gen_jasper.h | 5 + include/ilang/vtarget-out/vtarget_gen_pono.h | 5 + src/rfmap-in/verilog_rfmap.cc | 35 +++- src/verilog-in/verilog_analysis.cc | 2 +- src/verilog-out/verilog_gen.cc | 2 + src/vtarget-out/gen_util.cc | 38 ++-- src/vtarget-out/single_target.cc | 7 + src/vtarget-out/single_target_as.cc | 56 +++++- src/vtarget-out/single_target_misc.cc | 55 +++++- src/vtarget-out/vtarget_gen_impl.cc | 2 +- src/vtarget-out/vtarget_gen_pono.cc | 163 +++++++++++++++--- test/t_verilog_analysis.cc | 12 +- test/t_vtarget_gen.cc | 13 +- .../vpipe/rfmap/vmap-rfmap-pvholder.json | 3 +- test/unit-data/vpipe/vmem/cond.json | 2 +- test/unit-data/vpipe/vmem/swap_im.v | 12 +- test/unit-data/vpipe/vmem/vmap-expand.json | 21 ++- test/unit-data/vpipe/vmem/vmap.json | 53 +++--- 23 files changed, 419 insertions(+), 119 deletions(-) diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 0b09bc864..c16b01bf8 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -41,7 +41,7 @@ typedef verilog_expr::VExprAstVar::VExprAstVarPtr RfVar; */ struct SingleVarMap{ - /// a single refinement string + /// a single refinement string, will be initialized to NULL RfExpr single_map; /// a list of pair of string std::vector> cond_map; diff --git a/include/ilang/verilog-in/verilog_analysis_wrapper.h b/include/ilang/verilog-in/verilog_analysis_wrapper.h index 089ae2349..8eac4915e 100644 --- a/include/ilang/verilog-in/verilog_analysis_wrapper.h +++ b/include/ilang/verilog-in/verilog_analysis_wrapper.h @@ -122,15 +122,15 @@ class SignalInfoBase { const VerilogAnalyzerBase::hierarchical_name_type _type; /// its location of definition const VerilogAnalyzerBase::vlg_loc_t _loc; - /// addr width of the array, 0 if not array - const unsigned _addr_width; + /// addr range size of the array, 0 if not array + const unsigned _addr_range_size; public: /// --------------------- ACCESSORS ------------------- /// /// Return the width of the signal virtual unsigned get_width() const { return _width; } /// Return the addrwidth of the signal - virtual unsigned get_addr_width() const {return _addr_width; } + virtual unsigned get_addr_range_size() const {return _addr_range_size; } /// Whether is a IO signal virtual bool is_io_sig() const { return VerilogAnalyzerBase::is_io_sig(_type); @@ -170,7 +170,7 @@ class SignalInfoBase { const VerilogAnalyzerBase::hierarchical_name_type& typ, const VerilogAnalyzerBase::vlg_loc_t& loc, unsigned aw) - : _name(n), _hierarchical_name(h), _width(w), _type(typ), _loc(loc), _addr_width(aw) {} + : _name(n), _hierarchical_name(h), _width(w), _type(typ), _loc(loc), _addr_range_size(aw) {} /// implicit copy constructor }; // class SignalInfoBase diff --git a/include/ilang/verilog-out/verilog_gen.h b/include/ilang/verilog-out/verilog_gen.h index 1be78d3c1..28c181e2c 100644 --- a/include/ilang/verilog-out/verilog_gen.h +++ b/include/ilang/verilog-out/verilog_gen.h @@ -164,16 +164,20 @@ class VerilogGeneratorBase { bool expand_mem; /// whether to collect the ite(c, v, unknown) thing bool collect_ite_unknown_update; + /// add (* keep *) before the internal mem? + bool add_keep_for_internal_mem; /// Constructor, set default value, ExternalMem : false, function: internal /// module VlgGenConfig( // provide the default settings bool ExternalMem = true, funcOption funcOpt = funcOption::Internal, bool gen_start = false, bool pass_name = false, bool rand_init = false, - bool ExpandMem = false, bool CollectIteUnknownUpdate = false) + bool ExpandMem = false, bool CollectIteUnknownUpdate = false, + bool AddKeepForInternalMem = true) : extMem(ExternalMem), fcOpt(funcOpt), start_signal(gen_start), pass_node_name(pass_name), reg_random_init(rand_init), - expand_mem(ExpandMem), collect_ite_unknown_update(CollectIteUnknownUpdate) {} + expand_mem(ExpandMem), collect_ite_unknown_update(CollectIteUnknownUpdate), + add_keep_for_internal_mem(AddKeepForInternalMem) {} // set other fields if there are such need (?) }; // end of struct VlgGenConfig diff --git a/include/ilang/vtarget-out/vtarget_gen.h b/include/ilang/vtarget-out/vtarget_gen.h index 5dee2e372..15cd67e45 100644 --- a/include/ilang/vtarget-out/vtarget_gen.h +++ b/include/ilang/vtarget-out/vtarget_gen.h @@ -78,6 +78,11 @@ class VlgVerifTgtGenBase { /// Whether to pass Verilog node name in reference /// generation bool VerilogGenPassNodeName; + /// if false : assume (cond |-> reg == value) + /// if true : assume ((START || STARTED) && cond && not_triggered) + /// |-> reg == value + bool EnforcingValueRecorderForOnlyOneCycle; + /// Configure the behavior of INV target, if false, /// will not check synthesized invariants by default (unless call @@ -94,8 +99,8 @@ class VlgVerifTgtGenBase { bool ForceInstCheckReset; /// For Pono target generator : whether to force NEW/OLD port declaration enum class PortDeclStyleT { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; - /// Generate a jg script to help validate Pono? - bool PonoGenJgTesterScript; + + /// Pono VCD output std::string PonoVcdOutputName; /// Binary location of Pono @@ -156,6 +161,9 @@ class VlgVerifTgtGenBase { /// It seems for Z3, setting this to be false is faster (I don't know why) /// For grain-enhance, this will be (internally) overwritten to be true bool InvariantSynthesisReachableCheckKeepOldInvariant; + /// Whether to set undriven net in yosys as 0. In general this should not + /// be needed, but for some reason, PONO is unhappy sometimes. + bool YosysSetUndrivenZero; // ----------- Options for CHC Solver -------------- // /// CHC, whether to turn array into individual registers @@ -215,17 +223,21 @@ class VlgVerifTgtGenBase { // ----------- Extended Options for Grain -------------- // + // ----------- Refinement Sanity Check Options-------------- // + bool SanityCheck_ValueRecorderOverlyConstrained; + /// The default constructor for default values _vtg_config() : target_select(BOTH), CheckThisInstructionOnly(""), InstructionNoReset(true), InvariantCheckNoReset(false), OnlyCheckInstUpdatedVars(true), VerilogGenPassNodeName(false), + EnforcingValueRecorderForOnlyOneCycle(true), ValidateSynthesizedInvariant(_validate_synthesized_inv::ALL), // ----------- Options for Pono settings -------------- // ForceInstCheckReset(false), PortDeclStyle(PortDeclStyleT::AUTO), - PonoGenJgTesterScript(false), PonoVcdOutputName("cex.vcd"), + PonoVcdOutputName("cex.vcd"), PonoAddKeep(false), PonoEngine("ind"), PonoOtherOptions(""), PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), @@ -241,6 +253,7 @@ class VlgVerifTgtGenBase { YosysSmtStateSort(YosysStateSortT::Datatypes), InvariantSynthesisKeepMemory(true), InvariantCheckKeepMemory(true), InvariantSynthesisReachableCheckKeepOldInvariant(false), + YosysSetUndrivenZero(false), // ----------- Options for CHCs -------------- // ChcWordBlastArray(true), ChcAssumptionsReset(false), @@ -258,8 +271,10 @@ class VlgVerifTgtGenBase { // ----------- Options for ABC -------------- // AbcUseGla(false), AbcGlaTimeLimit(500), AbcGlaFrameLimit(200), AbcUseCorr(false), AbcUseAiger(true), AbcMinimizeInv(false), - AbcAssumptionStyle(AbcAssumptionStyle_t::AigMiterExtraOutput) + AbcAssumptionStyle(AbcAssumptionStyle_t::AigMiterExtraOutput), + // ----------- Options for Refinement Sanity Checks -------------- // + SanityCheck_ValueRecorderOverlyConstrained(true) {} } vtg_config_t; diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 377f5274a..682350958 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -351,6 +351,8 @@ class VlgSglTgtGen { /// assumptions : written by add_an_assertion, /// consumed by ConstructWrapper_translate_property_and_collect_all_rtl_connection_var std::map> all_assertions; + /// consumed by ConstructWrapper_translate_property_and_collect_all_rtl_connection_var + std::map> all_sanity_assertions; /// assign or assumptions : vector of (dspt, wire_name, rhs, wn == rhs) std::vector> assign_or_assumptions; /// map: wire_name -> (wire_name, hierarchy, internal name) @@ -391,6 +393,9 @@ class VlgSglTgtGen { /// Add an assertion virtual void add_a_direct_assertion(const std::string& aspt, const std::string& dspt) = 0; + /// Add a sanity assertion + virtual void add_a_direct_sanity_assertion(const std::string& aspt, + const std::string& dspt) = 0; /// Add SMT-lib2 assumption virtual void add_a_direct_smt_assumption(const std::string& arg, @@ -407,10 +412,14 @@ class VlgSglTgtGen { virtual void add_an_assumption(const rfmap::RfExpr& aspt, const std::string& dspt); - /// Add an assertion -- JasperGold will override this + /// Add an assertion -- simply put in record virtual void add_an_assertion(const rfmap::RfExpr& asst, const std::string& dspt); + /// Add an assertion for sanity checking -- simply put in record + void add_a_santiy_assertion(const rfmap::RfExpr& aspt, + const std::string& dspt); + // Add SMT assumption (using rfexpr) // - will use add_a_direct_smt_assumption/assertion virtual void add_smt_assumption( diff --git a/include/ilang/vtarget-out/vtarget_gen_jasper.h b/include/ilang/vtarget-out/vtarget_gen_jasper.h index 994ccf428..2ba31bae8 100644 --- a/include/ilang/vtarget-out/vtarget_gen_jasper.h +++ b/include/ilang/vtarget-out/vtarget_gen_jasper.h @@ -75,6 +75,11 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { /// Add a direct assertion virtual void add_a_direct_assertion(const std::string& asst, const std::string& dspt) override; + /// Add a direct assertion + virtual void add_a_direct_sanity_assertion(const std::string& asst, + const std::string& dspt) override { + add_a_direct_assertion(asst,dspt); } + /// Pre export work : nothing for cosa void virtual PreExportProcess() override {} diff --git a/include/ilang/vtarget-out/vtarget_gen_pono.h b/include/ilang/vtarget-out/vtarget_gen_pono.h index 665e69a56..e9221955d 100644 --- a/include/ilang/vtarget-out/vtarget_gen_pono.h +++ b/include/ilang/vtarget-out/vtarget_gen_pono.h @@ -40,6 +40,8 @@ class Pono_problem { problemset_t assumptions; /// problems are splitted into items problemset_t assertions; + /// problems are splitted into items + problemset_t sanity_assertions; /// SMT-LIB2 assumptions prop_t smt_assumptions; @@ -100,6 +102,9 @@ class VlgSglTgtGen_Pono : public VlgSglTgtGen { /// Add a direct assertion virtual void add_a_direct_assertion(const std::string& asst, const std::string& dspt) override; + /// Add a direct assertion + virtual void add_a_direct_sanity_assertion(const std::string& asst, + const std::string& dspt) override; /// Add SMT-lib2 assumption virtual void add_a_direct_smt_assumption(const std::string& arg, diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index d2d7ff18f..75b179d00 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -127,23 +127,31 @@ bool JsonRfmapParseCond(SingleVarMap & cond_map, nlohmann::json & json_array) { return succ; } // JsonRfmapParseCond +bool JsonRfmapParseSingleOrCond(SingleVarMap & sc_map, nlohmann::json & json_single_or_array) { + if(json_single_or_array.is_array()) + return JsonRfmapParseCond(sc_map, json_single_or_array); + assert(json_single_or_array.is_string()); + sc_map.single_map = ParseRfMapExprJson(json_single_or_array); + return sc_map.single_map != nullptr; +} + bool JsonRfmapParseMem(ExternalMemPortMap & mem_rfmap , nlohmann::json & json_obj) { assert(json_obj.is_object()); bool succ = true; if (json_obj.contains("wen")) - succ = succ && JsonRfmapParseCond(mem_rfmap.wen_map, json_obj["wen"]); + succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.wen_map, json_obj["wen"]); if (json_obj.contains("waddr")) - succ = succ && JsonRfmapParseCond(mem_rfmap.waddr_map, json_obj["waddr"]); + succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.waddr_map, json_obj["waddr"]); if (json_obj.contains("wdata")) - succ = succ && JsonRfmapParseCond(mem_rfmap.wdata_map, json_obj["wdata"]); + succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.wdata_map, json_obj["wdata"]); if (json_obj.contains("ren")) - succ = succ && JsonRfmapParseCond(mem_rfmap.ren_map, json_obj["ren"]); + succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.ren_map, json_obj["ren"]); if (json_obj.contains("raddr")) - succ = succ && JsonRfmapParseCond(mem_rfmap.raddr_map, json_obj["raddr"]); + succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.raddr_map, json_obj["raddr"]); if (json_obj.contains("rdata")) - succ = succ && JsonRfmapParseCond(mem_rfmap.rdata_map, json_obj["rdata"]); + succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.rdata_map, json_obj["rdata"]); mem_rfmap.rport_mapped = json_obj.contains("ren"); mem_rfmap.wport_mapped = json_obj.contains("wen"); @@ -514,9 +522,18 @@ VerilogRefinementMap::VerilogRefinementMap nlohmann::json rf_cond; load_json(varmap_json_file, rf_vmap); load_json(instcond_json_file, rf_cond); + { // deprecated warning messages + nlohmann::json * model_name = GetJsonSection(rf_vmap, {"model", "models","model name","model names"}); + ERRIF(model_name != NULL, "model names are not supported. Use `ILA` and `RTL`."); + nlohmann::json * instmap = GetJsonSection(rf_vmap, {"instruction mapping", "instruction map"}); + ERRIF(instmap != NULL, "instruction mapping is no longer supported"); + nlohmann::json * interface = GetJsonSection(rf_vmap, {"interface mapping", "interface map"}); + ERRIF(interface != NULL, "interface mapping is no longer supported. Use `input mapping` and `RTL interface connection`"); + } + // now json to -> Rfmap { // state mapping - nlohmann::json * state_mapping = GetJsonSection(rf_vmap,{"state mapping"}); + nlohmann::json * state_mapping = GetJsonSection(rf_vmap,{"state mapping", "state map"}); ERRIF(state_mapping == NULL , "state var mapping is duplicated or missing"); for (auto& i : state_mapping->items()) { IlaVarMapping svmp; @@ -567,7 +584,7 @@ VerilogRefinementMap::VerilogRefinementMap { // input mapping // TODO: add things here - nlohmann::json * input_mapping = GetJsonSection(rf_vmap,{"input mapping"}); + nlohmann::json * input_mapping = GetJsonSection(rf_vmap,{"input mapping", "input map"}); if(input_mapping) { for (auto& i : input_mapping->items()) { IlaVarMapping ivmp; @@ -590,7 +607,7 @@ VerilogRefinementMap::VerilogRefinementMap } // input mapping { // interface map - nlohmann::json * rtl_if_map = GetJsonSection(rf_vmap,{"RTL interface connection"}); + nlohmann::json * rtl_if_map = GetJsonSection(rf_vmap,{"RTL interface connection", "RTL interface connect"}); ERRIF(rtl_if_map == nullptr, "`RTL interface connection` is duplicated or missing" ); nlohmann::json * clock_domains = GetJsonSection(*rtl_if_map,{"CLOCK"},true); nlohmann::json * reset_list = GetJsonSection(*rtl_if_map,{"RESET"},true); diff --git a/src/verilog-in/verilog_analysis.cc b/src/verilog-in/verilog_analysis.cc index c8094ddeb..b66c88bf9 100644 --- a/src/verilog-in/verilog_analysis.cc +++ b/src/verilog-in/verilog_analysis.cc @@ -866,7 +866,7 @@ unsigned range_to_width(ast_range* range, const std::string& full_name, return analyzed_width; } - +// this returns: from [0:15] 15-0+1 == 16 unsigned addr_range_to_width(ast_identifier id, const std::string& full_name, const VerilogAnalyzer* _ana, int width) { if(id->range_or_idx == ID_HAS_RANGES && id->ranges && id->ranges->items > 0) { diff --git a/src/verilog-out/verilog_gen.cc b/src/verilog-out/verilog_gen.cc index 6751c58ec..3c317cd02 100644 --- a/src/verilog-out/verilog_gen.cc +++ b/src/verilog-out/verilog_gen.cc @@ -389,6 +389,8 @@ void VerilogGeneratorBase::DumpToFile(std::ostream& fout) const { << "the maximum allowed entry count: " << n_elem_allowed; if (entry_num_specified != 0 && entry_num_specified <= n_elem_allowed) n_elem = entry_num_specified; + if(cfg_.add_keep_for_internal_mem) + fout << "(* keep *) "; // sometimes these regs will be optimized always fout << "reg " << std::setw(10) << WidthToRange(data_width) << " " << (std::get<0>(mem.second)) << WidthToRange(n_elem) << ";\n"; } diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index f57c5fa90..86674cbe8 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -189,15 +189,18 @@ rfmap::RfVarTypeOrig VlgSglTgtGen::VarTypeCheckForRfExprParsing(const std::strin if (StrStartsWith(vname,"RTL.")) { ILA_ERROR_IF(!TryFindVlgState(vname)) << "Cannot find rtl var: " << vname; auto sig_info = vlg_info_ptr->get_signal(vname); - auto aw = sig_info.get_addr_width(); + auto aw_range = sig_info.get_addr_range_size(); auto dw = sig_info.get_width(); rfmap::RfVarTypeOrig ret; ret.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::RTLV; - if(aw == 0) // not an array + if(aw_range == 0) // not an array ret.type = rfmap::RfMapVarType(dw); - else + else { + unsigned aw = (unsigned)(std::ceil(std::log2(aw_range))); + // [15:0] -> aw_range == 16 -> 4 -> ceil (4) == 4 ret.type = rfmap::RfMapVarType(aw,dw); + } return ret; } @@ -257,6 +260,10 @@ rfmap::VarReplacement VlgSglTgtGen::CreateVarReplacement( auto dotpos = ila_sn.find('.'); ILA_ASSERT(ila_sn.substr(0,dotpos+1) == "ILA."); + bool is_array = tp.type.is_array(); // you can never connect an array out + ILA_CHECK(!is_array) << "Implementation bug: currently does not support array as input"; + + auto new_name = "__ILA_I_" + ila_sn.substr(dotpos+1); auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); new_node->set_annotation(std::make_shared(tp)); @@ -266,6 +273,14 @@ rfmap::VarReplacement VlgSglTgtGen::CreateVarReplacement( auto dotpos = ila_sn.find('.'); ILA_ASSERT(ila_sn.substr(0,dotpos+1) == "ILA."); + bool is_array = tp.type.is_array(); // you can never connect an array out + // so there should not be such things like: __ILA_SO_array + if(is_array) { // basically no replacement + auto ret_copy = std::make_shared(*var); + ret_copy->set_annotation(std::make_shared(tp)); + return rfmap::VarReplacement(var, ret_copy); + } + auto new_name = "__ILA_SO_" + ila_sn.substr(dotpos+1); auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); new_node->set_annotation(std::make_shared(tp)); @@ -431,9 +446,10 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, unsigned rfmap_node_idx = 0; for(const auto & rport : read_ports) { - auto ila_ren = rfmap_var(rport.second.ren); - auto ila_raddr = rfmap_var(rport.second.raddr); - auto ila_rdata = rfmap_var(rport.second.rdata); + size_t no = rport.first; + + auto ila_raddr = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_raddr"); + auto ila_rdata = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_rdata"); while(!(vmap.externmem_map.at(rfmap_node_idx).rport_mapped) && rfmap_node_idx < vmap.externmem_map.size()) @@ -451,7 +467,7 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, auto rtl_rdata = singlemap_bv_to_rfexpr(rfmap_rport.rdata_map); auto constr = rfmap_imply( rfmap_and( - {ila_ren, rtl_ren, rfmap_eq(ila_raddr, rtl_raddr)}), + {rtl_ren, rfmap_eq(ila_raddr, rtl_raddr)}), rfmap_eq(ila_rdata, rtl_rdata)); ADD_CONSTR(constr); @@ -473,9 +489,10 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, for(const auto & wport : write_ports) { // the reason for _d1: see ConstructWrapper_get_ila_module_inst // in single_target_connect.cc - auto ila_wen = rfmap_var(wport.second.wen + "_d1"); - auto ila_waddr = rfmap_var(wport.second.waddr + "_d1"); - auto ila_wdata = rfmap_var(wport.second.wdata + "_d1"); + size_t no = wport.first; + auto ila_wen = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_wen" + "_d1"); + auto ila_waddr = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_waddr" + "_d1"); + auto ila_wdata = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_wdata" + "_d1"); while(!(vmap.externmem_map.at(rfmap_node_idx).wport_mapped) && rfmap_node_idx < vmap.externmem_map.size()) @@ -561,4 +578,5 @@ void VlgSglTgtGen::rfmap_add_replacement(const std::string &old, const std::stri old, rfmap::VarReplacement(oldexpr, newexpr)); } // rfmap_add_replacement + }; // namespace ilang diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index 462b66991..1a5f38326 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -140,6 +140,13 @@ VlgSglTgtGen::VlgSglTgtGen( ILA_ERROR << "Implementation bug btw. vlg gen and vtarget-gen"; _bad_state = true; } + + // vlg_ila.ila_rports/ila_wports -> internal wire + // register_ila_memory_wires(); + // no this is not needed + // the ports are connected to wires with names like + // __IMEM_xxx_... + // this is in single_target_connect.cc } // END of target_type == INSTRUCTION else if (target_type == target_type_t::INVARIANTS) { diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index c7c521c81..18a065348 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -57,7 +57,7 @@ void VlgSglTgtGen::add_smt_assumption( auto tp = refinement_map.GetType( n_expr_pair.second ); auto smt_tp = rfmap::SmtType(tp.type, false); const auto & n = n_expr_pair.first; - arg.push_back("("+n + " " + smt_tp.type_to_smt2() + ")"); + arg.push_back("(|"+n + "| " + smt_tp.type_to_smt2() + ")"); } add_a_direct_smt_assumption( "("+Join(arg, " ")+")", "Bool", body_smt2, dspt); @@ -80,7 +80,7 @@ void VlgSglTgtGen::add_smt_assertion( auto tp = refinement_map.GetType( n_expr_pair.second ); auto smt_tp = rfmap::SmtType(tp.type, false); const auto & n = n_expr_pair.first; - arg.push_back("("+n + " " + smt_tp.type_to_smt2() + ")"); + arg.push_back("(|"+n + "| " + smt_tp.type_to_smt2() + ")"); } add_a_direct_smt_assertion( "("+Join(arg, " ")+")", "Bool", body_smt2, dspt); @@ -94,13 +94,22 @@ void VlgSglTgtGen::add_an_assumption(const rfmap::RfExpr& aspt, all_assumptions[dspt].push_back(aspt); } -/// Add an assertion -- JasperGold will override this void VlgSglTgtGen::add_an_assertion(const rfmap::RfExpr& asst, const std::string& dspt) { rfmap::RfExprAstUtility::RfMapNoNullNode(asst); all_assertions[dspt].push_back(asst); } +void VlgSglTgtGen::add_a_santiy_assertion(const rfmap::RfExpr& asst, + const std::string& dspt) { + if(dspt == "post_value_holder" && + !_vtg_config.SanityCheck_ValueRecorderOverlyConstrained) + return; + + rfmap::RfExprAstUtility::RfMapNoNullNode( asst ); + all_sanity_assertions[dspt].push_back(asst); +} + static std::string const_to_unified_str(const rfmap::RfExpr & in) { auto cnst = verilog_expr::VExprAstConstant::cast_ptr(in); ILA_NOT_NULL(cnst); @@ -186,20 +195,31 @@ void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_conne for(auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { const auto & vn = std::get<1>(dspt_vn_rfexpr_eq); const auto & rfe = std::get<2>(dspt_vn_rfexpr_eq); + + ILA_DLOG("VTG.ReplWireEq") << vn << " := " << rfe->to_verilog(); std::get<3>(dspt_vn_rfexpr_eq) = ReplExpr(rfmap_eq( rfmap_var(vn), rfe)); } // for each assign/assumption for(auto & dspt_aspt : all_assumptions) { for(auto & aspt : dspt_aspt.second) { - + ILA_DLOG("VTG.ReplAssume") << aspt->to_verilog() ; aspt = ReplExpr(aspt); } } for (auto & dspt_asst : all_assertions) { - for (auto & asst : dspt_asst.second) + for (auto & asst : dspt_asst.second) { + ILA_DLOG("VTG.ReplAssert") << asst->to_verilog() ; asst = ReplExpr(asst); + } + } + + for (auto & dspt_asst : all_sanity_assertions) { + for (auto & asst : dspt_asst.second) { + ILA_DLOG("VTG.ReplAssert") << asst->to_verilog() ; + asst = ReplExpr(asst); + } } if(is_jg) { @@ -209,8 +229,15 @@ void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_conne } for(auto & dspt_asst : all_assertions) { for(auto & asst : dspt_asst.second) - add_a_direct_assumption( asst->to_verilog(), dspt_asst.first ); + add_a_direct_assertion( asst->to_verilog(), dspt_asst.first ); + } + for(auto & dspt_asst : all_sanity_assertions) { + for(auto & asst : dspt_asst.second) + add_a_direct_sanity_assertion( asst->to_verilog(), dspt_asst.first ); } + + + for (auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { const auto & vn = std::get<1>(dspt_vn_rfexpr_eq); const auto & eq = std::get<3>(dspt_vn_rfexpr_eq); @@ -274,6 +301,8 @@ void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_conne const auto & dspt = std::get<0>(dspt_vn_rfexpr_eq); const auto & wn = std::get<1>(dspt_vn_rfexpr_eq); + ILA_DLOG("VTG.AddWireEq") << eq->to_verilog(); + std::map array_var; if(rfmap::RfExprAstUtility::HasArrayVar(eq, array_var)) add_smt_assumption(eq, dspt); @@ -283,6 +312,8 @@ void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_conne for(const auto & dspt_aspt : all_assumptions) { for(const auto & aspt : dspt_aspt.second) { + ILA_DLOG("VTG.AddAssume") << aspt->to_verilog(); + std::map array_var; if(rfmap::RfExprAstUtility::HasArrayVar(aspt, array_var)) add_smt_assumption(aspt, dspt_aspt.first); @@ -293,6 +324,8 @@ void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_conne for(const auto & dspt_asst : all_assertions) { for(const auto & asst : dspt_asst.second) { + ILA_DLOG("VTG.AddAssert") << asst->to_verilog(); + std::map array_var; if(rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) add_smt_assertion(asst, dspt_asst.first); @@ -300,6 +333,17 @@ void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_conne add_a_direct_assertion(asst->to_verilog(), dspt_asst.first); } } + + for(const auto & dspt_asst : all_sanity_assertions) { + for(const auto & asst : dspt_asst.second) { + std::map array_var; + ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) + << "Implementation bug: sanity checking assertion should not contain arrays"; + + add_a_direct_sanity_assertion(asst->to_verilog(), dspt_asst.first); + } + } + } // ConstructWrapper_translate_property_and_collect_all_rtl_connection_var diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 74e4407fc..a11fd9442 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -291,11 +291,62 @@ void VlgSglTgtGen::ConstructWrapper_add_post_value_holder() { vlg_wrapper.add_reg(pv_name, post_val_holder.second.width); rfmap_add_internal_reg(pv_name, post_val_holder.second.width); + auto eq_cond = _vtg_config.EnforcingValueRecorderForOnlyOneCycle ? + rfmap_and({ + rfmap_or( rfmap_var("__START__"), rfmap_var("__STARTED__") ), + rfmap_not(rfmap_var(pv_name+"_sn_condmet")), + post_val_holder.second.condition + }) + : + post_val_holder.second.condition; + add_reg_cassign_assumption(pv_name, post_val_holder.second.value, post_val_holder.second.width, - post_val_holder.second.condition, + eq_cond, "post_value_holder"); + + // for sanity check + vlg_wrapper.add_reg(pv_name+"_sn_vhold", post_val_holder.second.width); + rfmap_add_internal_reg(pv_name+"_sn_vhold", post_val_holder.second.width); + vlg_wrapper.add_reg(pv_name+"_sn_value", post_val_holder.second.width); + rfmap_add_internal_reg(pv_name+"_sn_value", post_val_holder.second.width); + + vlg_wrapper.add_reg(pv_name+"_sn_condmet", 1); + rfmap_add_internal_reg(pv_name+"_sn_condmet", 1); + vlg_wrapper.add_reg(pv_name+"_sn_cond", 1); + rfmap_add_internal_reg(pv_name+"_sn_cond", 1); + vlg_wrapper.add_init_stmt(pv_name+"_sn_condmet <= 1'b0;"); + vlg_wrapper.add_always_stmt("if (" + pv_name+"_sn_cond ) begin " + + pv_name+"_sn_condmet <= 1'b1; " + + pv_name+"_sn_vhold <= " + pv_name+ "_sn_value; end" + ); + + // pv_sn_cond = && ( __START__ || __STARTED__ ) + add_wire_assign_assumption(pv_name+"_sn_cond", + rfmap_and( + post_val_holder.second.condition, + rfmap_or( rfmap_var("__START__"), rfmap_var("__STARTED__") )), + "pvholder_cond_assign"); + + // pv_sn_value = + add_wire_assign_assumption(pv_name+"_sn_value", + post_val_holder.second.value, + "pvholder_cond_assign"); + + add_a_santiy_assertion( + // cond && cond_met |-> value == value_stored + rfmap_imply( + rfmap_and(rfmap_var(pv_name+"_sn_condmet"), + rfmap_var(pv_name+"_sn_cond")), + rfmap_eq( rfmap_var(pv_name+"_sn_value"), + rfmap_var(pv_name+"_sn_vhold"))), + "post_value_holder"); + + + // you need to add checker + + // check no } } // ConstructWrapper_add_post_value_holder @@ -359,7 +410,7 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { const rfmap::InstructionCompleteCondition & VlgSglTgtGen::get_current_instruction_rf() { ILA_NOT_NULL(_instr_ptr); - const auto & inst_name = _instr_ptr->name().c_str(); + const auto & inst_name = _instr_ptr->name().str(); auto pos = refinement_map.inst_complete_cond.find(inst_name); ILA_ERROR_IF(pos == refinement_map.inst_complete_cond.end()) << "Cannot find the completion condition for " << inst_name; diff --git a/src/vtarget-out/vtarget_gen_impl.cc b/src/vtarget-out/vtarget_gen_impl.cc index a97fbb98a..b834023cb 100644 --- a/src/vtarget-out/vtarget_gen_impl.cc +++ b/src/vtarget-out/vtarget_gen_impl.cc @@ -210,7 +210,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INSTRUCTIONS, _advanced_param_ptr); target.ConstructWrapper(); - target.ExportAll("wrapper.v", "ila.v", "run.sh", "problem.txt"); + target.ExportAll("wrapper.v", "ila.v", "run.sh", "gen_btor.ys"); target.do_not_instantiate(); } else if (_backend == backend_selector::JASPERGOLD) { auto target = VlgSglTgtGen_Jasper( diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index 107f7f107..2637dad8e 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -23,10 +23,12 @@ static std::string yosysGenerateBtor = R"***( hierarchy -check proc chformal -assume -early; +%propselect% memory -nomap; flatten sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% )***"; +// %propselect% is for VlgSglTgtGen_Pono::VlgSglTgtGen_Pono( @@ -67,6 +69,17 @@ void VlgSglTgtGen_Pono::add_a_direct_assertion(const std::string& asst, _problems.assertions[dspt].exprs.push_back(wire_name); } + +/// Add an assertion +void VlgSglTgtGen_Pono::add_a_direct_sanity_assertion(const std::string& asst, + const std::string& dspt) { + auto wire_name = dspt + new_property_id(); + vlg_wrapper.add_wire(wire_name,1); + vlg_wrapper.add_output(wire_name,1); + vlg_wrapper.add_assign_stmt(wire_name, asst); + _problems.sanity_assertions[dspt].exprs.push_back(wire_name); +} + /// export the script to run the verification void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { @@ -78,16 +91,15 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { } fout << "#!/bin/bash" << std::endl; - { - std::string yosys = "yosys"; + + std::string yosys = "yosys"; - if (!_vtg_config.YosysPath.empty()) - yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); - - // execute it - fout << yosys << " -s " << ys_script_name << " > __yosys_exec_result.txt\n"; - } + if (!_vtg_config.YosysPath.empty()) + yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); + // execute it + fout << yosys << " -s " << ys_script_name << " > __yosys_exec_result.txt\n"; + std::string pono = "pono"; std::string options; @@ -108,7 +120,12 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { fout << pono << options << " problem.btor2 " << std::endl; -} + if(!_problems.sanity_assertions.empty()) { + fout << yosys << " -s gen_sanity_prop.ys > __yosys_exec_result.sanity.txt\n"; + + fout << pono << options << " sanity.btor2 " << std::endl; + } +} // Export_script /// Add SMT-lib2 assumption @@ -134,7 +151,7 @@ void VlgSglTgtGen_Pono::add_a_direct_smt_assertion(const std::string& arg, /// export the yosys script void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { - if (_problems.assertions.empty()) { + if (_problems.assertions.empty() && _problems.smt_assertions.empty() && _problems.sanity_assertions.empty()) { ILA_ERROR << "Nothing to prove, no assertions inserted!"; return; } @@ -154,25 +171,37 @@ void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { << std::endl; ys_script_fout << "prep -top " << top_mod_name << std::endl; + std::string property_selection_cmd; + if(!_problems.sanity_assertions.empty()) { + property_selection_cmd = "\n" + "select wrapper/sanitycheck\n" + "chformal -remove\n" + "select *\n"; + } + ys_script_fout << ReplaceAll( ReplaceAll( - ReplaceAll(yosysGenerateBtor, - "%rstlen%", - std::to_string( - refinement_map.reset_specification.reset_cycle)), - "%cycle%", - std::to_string( - refinement_map.reset_specification.reset_cycle)), - "%module%", top_mod_name); + ReplaceAll( + ReplaceAll(yosysGenerateBtor, + "%rstlen%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%cycle%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%module%", top_mod_name), + "%propselect%", property_selection_cmd); // this is for pono, I don't know why it is unhappy, but we need fix this // in the long run - ys_script_fout << "setundef -undriven -zero\n"; + if(_vtg_config.YosysSetUndrivenZero) + ys_script_fout << "setundef -undriven -zero\n"; + + ys_script_fout << "write_btor " << write_btor_options << " problem.btor2" << std::endl; } // finish writing - auto smt_property_fname = os_portable_append_dir(_output_path, "property.smt2"); { @@ -183,6 +212,49 @@ void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { for(const auto & prop : _problems.smt_assertions) smt_fout << prop << std::endl; } + + // sanity checks + if(!_problems.sanity_assertions.empty()) + { // export to ys_script_name + std::string ys_script_name_path = os_portable_append_dir(_output_path, "gen_sanity_prop.ys"); + std::ofstream ys_script_fout(ys_script_name_path); + + std::string write_btor_options; + write_btor_options += _vtg_config.BtorAddCommentsInOutputs ? " -v" : ""; + write_btor_options += _vtg_config.BtorSingleProperty ? " -s" : ""; + + ys_script_fout << "read_verilog -sv " + << os_portable_append_dir(_output_path, top_file_name) + << std::endl; + ys_script_fout << "prep -top " << top_mod_name << std::endl; + + std::string property_selection_cmd = "\n" + "select wrapper/normalassert\n" + "chformal -remove\n" + "select *\n"; + + ys_script_fout << + ReplaceAll( + ReplaceAll( + ReplaceAll( + ReplaceAll(yosysGenerateBtor, + "%rstlen%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%cycle%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%module%", top_mod_name), + "%propselect%", property_selection_cmd); + + // this is for pono, I don't know why it is unhappy, but we need fix this + // in the long run + if(_vtg_config.YosysSetUndrivenZero) + ys_script_fout << "setundef -undriven -zero\n"; + + + ys_script_fout << "write_btor " << write_btor_options << " sanity.btor2" << std::endl; + } // finish writing } // only for Pono @@ -191,6 +263,8 @@ void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { void VlgSglTgtGen_Pono::PreExportProcess() { std::string all_assert_wire_content; + std::string all_sanity_assert_wire_content; + std::string all_assume_wire_content; // you need to add assumptions as well @@ -208,7 +282,7 @@ void VlgSglTgtGen_Pono::PreExportProcess() { } // for prob.exprs } // for _problems.assumption - // this is to check given invariants + // this is to check given assertions for (auto&& pbname_prob_pair : _problems.assertions) { // const auto& prbname = pbname_prob_pair.first; const auto& prob = pbname_prob_pair.second; @@ -227,23 +301,58 @@ void VlgSglTgtGen_Pono::PreExportProcess() { } // for expr } // for problem // add assert wire (though no use : make sure will not optimized away) - ILA_CHECK(!all_assert_wire_content.empty()) << "no property to check!"; + if(_problems.smt_assertions.empty()) + ILA_CHECK(!all_assert_wire_content.empty()) << "no property to check!"; + + if(all_assert_wire_content.empty()) + { // in case all_assert_wire_content is empty + all_assert_wire_content = "1'b1"; // (assert true) + } + + + // this is to check given sanity assertions + for (auto&& pbname_prob_pair : _problems.sanity_assertions) { + // const auto& prbname = pbname_prob_pair.first; + const auto& prob = pbname_prob_pair.second; + + // ILA_CHECK(prbname == "cex_nonreachable_assert") + // << "BUG: assertion can only be cex reachability queries."; + // sanity check, should only be invariant's related asserts + + for (auto&& p : prob.exprs) { + // there should be only one expression (for cex target) + // ILA_CHECK(all_assert_wire_content.empty()); + if (all_sanity_assert_wire_content.empty()) + all_sanity_assert_wire_content = "(" + p + ")"; + else + all_sanity_assert_wire_content += " && (" + p + ")"; + } // for expr + } vlg_wrapper.add_wire("__all_assert_wire__", 1, true); vlg_wrapper.add_output("__all_assert_wire__", 1); vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); - + vlg_wrapper.add_stmt( + "normalassert: assert property ( __all_assert_wire__ ); // the only assertion \n"); + if (!all_assume_wire_content.empty()) { vlg_wrapper.add_wire("__all_assume_wire__", 1, true); vlg_wrapper.add_output("__all_assume_wire__", 1); vlg_wrapper.add_assign_stmt("__all_assume_wire__", all_assume_wire_content); + + vlg_wrapper.add_stmt( + "all_assume: assume property ( __all_assume_wire__ ); // the only sanity assertion \n"); } - vlg_wrapper.add_stmt( - "assert property ( __all_assert_wire__ ); // the only assertion \n"); - if (!all_assume_wire_content.empty()) + if (!all_sanity_assert_wire_content.empty()) { + vlg_wrapper.add_wire("__sanitycheck_wire__", 1, true); + vlg_wrapper.add_output("__sanitycheck_wire__", 1); + vlg_wrapper.add_assign_stmt("__sanitycheck_wire__", all_sanity_assert_wire_content); + vlg_wrapper.add_stmt( - "assume property ( __all_assume_wire__ ); // the only assumption \n"); + "sanitycheck: assert property ( __sanitycheck_wire__ ); // the only assumption \n"); + + } } // PreExportProcess /// For jasper, this means do nothing, for yosys, you need to add (*keep*) diff --git a/test/t_verilog_analysis.cc b/test/t_verilog_analysis.cc index 61d3b0cd2..cdfe18adb 100644 --- a/test/t_verilog_analysis.cc +++ b/test/t_verilog_analysis.cc @@ -82,7 +82,7 @@ TEST(TestVerilogAnalysis, Include) { } TEST(TestVerilogAnalysis, RangeAnalysisArray) { -#define IS_ARRAY_WIDTH(n, w) EXPECT_EQ(va.get_signal("m1." n).get_addr_width(), w) +#define IS_ARRAY_RANGE_SIZE(n, w) EXPECT_EQ(va.get_signal("m1." n).get_addr_range_size(), w) { VerilogInfo va( VerilogInfo::path_vec_t( @@ -90,17 +90,17 @@ TEST(TestVerilogAnalysis, RangeAnalysisArray) { VerilogInfo::path_vec_t({std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/verilog_sample/range-array.v"}), "m1"); - IS_ARRAY_WIDTH("r12", 8-1); - IS_ARRAY_WIDTH("r22", 8-1); - IS_ARRAY_WIDTH("r14", 9-1); - IS_ARRAY_WIDTH("r24", 7-1); + IS_ARRAY_RANGE_SIZE("r12", 8-1); + IS_ARRAY_RANGE_SIZE("r22", 8-1); + IS_ARRAY_RANGE_SIZE("r14", 9-1); + IS_ARRAY_RANGE_SIZE("r24", 7-1); } } TEST(TestVerilogAnalysis, RangeAnalysis) { #define IS_WIDTH(n, w) EXPECT_EQ(va.get_signal("m1." n).get_width(), w) -#define NOT_ARRAY(n) EXPECT_EQ(va.get_signal("m1." n).get_addr_width(), 0) +#define NOT_ARRAY(n) EXPECT_EQ(va.get_signal("m1." n).get_addr_range_size(), 0) { // test 1 VerilogInfo va( diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index feba97bcc..e1a1c8497 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -254,7 +254,7 @@ TEST(TestVlgTargetGen, PipeExampleJasperGold) { TEST(TestVlgTargetGen, PipeExampleNotEqu) { auto ila_model = SimplePipe::BuildModel(); - + auto dirName = os_portable_join_dir({ILANG_TEST_SRC_ROOT, "unit-data", "vpipe"}); VerilogVerificationTargetGenerator vg( @@ -272,6 +272,8 @@ TEST(TestVlgTargetGen, PipeExampleNotEqu) { vg.GenerateTargets(); } +// #warning "Continue your test from here" + TEST(TestVlgTargetGen, Memory) { auto ila_model = MemorySwap::BuildModel(); @@ -294,6 +296,15 @@ TEST(TestVlgTargetGen, Memory) { TEST(TestVlgTargetGen, MemoryInternal) { // test the expansion of memory + + DebugLog::Enable("VTG.ReplWireEq"); + DebugLog::Enable("VTG.ReplAssert"); + DebugLog::Enable("VTG.ReplAssume"); + + DebugLog::Enable("VTG.AddWireEq"); + DebugLog::Enable("VTG.AddAssert"); + DebugLog::Enable("VTG.AddAssume"); + auto ila_model = MemorySwap::BuildSimpleSwapModel(); VerilogVerificationTargetGenerator::vtg_config_t diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json index 5a5e410f4..ffa0d77d2 100644 --- a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json @@ -27,7 +27,8 @@ "stage_tracker" : { "verilog": ["always @(posedge clk) begin", - " if (__START__) stage_tracker <= 0;", + " if (rst ) stage_tracker <= 0;", + " else if ( __START__ ) stage_tracker <= 0;", " else if (__STARTED__ && !__ENDED__) stage_tracker <= stage_tracker + 1;", "end"], "append-verilog" : "module nouse2(input wire a, output wire b); assign b=a; endmodule", diff --git a/test/unit-data/vpipe/vmem/cond.json b/test/unit-data/vpipe/vmem/cond.json index 01feac63b..950e5019e 100644 --- a/test/unit-data/vpipe/vmem/cond.json +++ b/test/unit-data/vpipe/vmem/cond.json @@ -4,7 +4,7 @@ "instructions": [ { "instruction": "SWAP", - "start condition":["m1.state == 0" , "$valid", "$decode" ], + "start condition":["RTL.state == 0" , "$valid", "$decode" ], "ready bound": 3 } ] diff --git a/test/unit-data/vpipe/vmem/swap_im.v b/test/unit-data/vpipe/vmem/swap_im.v index 9703d12ac..8e1adde76 100644 --- a/test/unit-data/vpipe/vmem/swap_im.v +++ b/test/unit-data/vpipe/vmem/swap_im.v @@ -5,10 +5,12 @@ module swap ( input rst, // Synchronous reset active high input [3:0] addra, input [3:0] addrb, - input start); + input start, + output [3:0] dummyrd, + output reg [7:0] dummyv); -reg [7:0] mema[0:15]; -reg [7:0] memb[0:15]; +(* keep *) reg [7:0] mema[0:15]; +(* keep *) reg [7:0] memb[0:15]; always @(posedge clk) begin @@ -18,4 +20,8 @@ always @(posedge clk) begin end end +always @(posedge clk) begin + dummyv <= (^dummyrd) ? mema[dummyrd] : memb[dummyrd]; +end + endmodule \ No newline at end of file diff --git a/test/unit-data/vpipe/vmem/vmap-expand.json b/test/unit-data/vpipe/vmem/vmap-expand.json index d11d0a6a0..d72edea22 100644 --- a/test/unit-data/vpipe/vmem/vmap-expand.json +++ b/test/unit-data/vpipe/vmem/vmap-expand.json @@ -1,17 +1,16 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, - "instruction mapping": [], "state mapping": { - "mema":"mema", - "memb":"memb"}, + "mema":"RTL.mema", + "memb":"RTL.memb"}, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "addra":"addra", - "addrb":"addrb", - "start":"start" + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" }, - "mapping control" : [] + "input mapping": { + "addra":"RTL.addra", + "addrb":"RTL.addrb", + "start":"RTL.start" + } } diff --git a/test/unit-data/vpipe/vmem/vmap.json b/test/unit-data/vpipe/vmem/vmap.json index c07bfddee..8b6c64225 100644 --- a/test/unit-data/vpipe/vmem/vmap.json +++ b/test/unit-data/vpipe/vmem/vmap.json @@ -1,34 +1,31 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, - "instruction mapping": [], "state mapping": { - "mema":"**MEM**mema", - "memb":"**MEM**memb"}, - - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "addra":"addra", - "addrb":"addrb", - "start":"start", - "mem_a_raddr":"**MEM**mema.raddr", - "mem_a_rdata":"**MEM**mema.rdata", - "mem_a_waddr":"**MEM**mema.waddr", - "mem_a_wdata":"**MEM**mema.wdata", - "mem_a_wen":"**MEM**mema.wen", - "mem_b_raddr":"**MEM**memb.raddr", - "mem_b_rdata":"**MEM**memb.rdata", - "mem_b_waddr":"**MEM**memb.waddr", - "mem_b_wdata":"**MEM**memb.wdata", - "mem_b_wen":"**MEM**memb.wen" + "mema": { + "ren" : "1'b1" , + "raddr" : "RTL.mem_a_raddr @ (RTL.state == 1)", + "rdata" : "RTL.mem_a_rdata @ (RTL.state == 1)", + "wen" : "1'b1 " , + "waddr" : "RTL.mem_a_waddr @ (RTL.state == 2)", + "wdata" : "RTL.mem_a_wdata @ (RTL.state == 2)" + }, + "memb": { + "ren" : "1'b1" , + "raddr" : "RTL.mem_b_raddr @ (RTL.state == 1)", + "rdata" : "RTL.mem_b_rdata @ (RTL.state == 1)", + "wen" : "1'b1 " , + "waddr" : "RTL.mem_b_waddr @ (RTL.state == 2)", + "wdata" : "RTL.mem_b_wdata @ (RTL.state == 2)" + } }, - // "mapping control" : ["__MEM_mema_0_ren == ((m1.state == 1)?1'b1:1'b0)", "__MEM_memb_0_ren == ((m1.state == 1)?1'b1:1'b0)"], + "input mapping": { + "addra":"RTL.addra", + "addrb":"RTL.addrb", + "start":"RTL.start" + }, - "annotation": { - "memory-ports" : { - "mema.ren":"((m1.state == 1)?1'b1:1'b0)", // you can use arbitrary verilog expression here - "memb.ren":"m1.state == 1" - } - } + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + } } From f107da4c26a9d130f8357f18de5545cf70faca2c Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 2 Sep 2021 20:25:25 +0800 Subject: [PATCH 34/78] smt property-interface --- src/vtarget-out/vtarget_gen_pono.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index 2637dad8e..39bbb2839 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -118,11 +118,16 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { pono = os_portable_append_dir(_vtg_config.PonoPath, pono); } - fout << pono << options << " problem.btor2 " << std::endl; + std::string extra_smt_properties; + if(!_problems.smt_assertions.empty()) { + extra_smt_properties += " --property-file property.smt2 "; + } + + fout << pono << options << extra_smt_properties << " problem.btor2 " << std::endl; if(!_problems.sanity_assertions.empty()) { fout << yosys << " -s gen_sanity_prop.ys > __yosys_exec_result.sanity.txt\n"; - + // here we intentionally leave out the property interface file. fout << pono << options << " sanity.btor2 " << std::endl; } } // Export_script From 26d0c3bab0673e8327293dfe7b718918f8966fd4 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 7 Sep 2021 11:27:07 +0800 Subject: [PATCH 35/78] add stall vpipe --- src/rfmap-in/verilog_rfmap.cc | 5 + test/t_vtarget_gen.cc | 46 ++- .../rfmap/cond-rfmap-pvholder-stall.json | 33 ++ .../rfmap/vmap-rfmap-pvholder-stall.json | 68 ++++ test/unit-data/vpipe/simple_pipe_stall.v | 304 ++++++++++++++++++ test/unit-data/vpipe/verify_stall/.gitignore | 5 + test/unit-include/pipe_ila.h | 1 + test/unit-src/pipe_ila.cc | 54 ++++ 8 files changed, 506 insertions(+), 10 deletions(-) create mode 100644 test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-stall.json create mode 100644 test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-stall.json create mode 100644 test/unit-data/vpipe/simple_pipe_stall.v create mode 100644 test/unit-data/vpipe/verify_stall/.gitignore diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 75b179d00..e3eae1992 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -772,6 +772,11 @@ VerilogRefinementMap::VerilogRefinementMap } // if func_section } // uf section { // additional mapping & assumptions + { + nlohmann::json * mapping_control = GetJsonSection(rf_vmap,{"mapping control"}); + ERRIF(mapping_control!=NULL, "please rename `mapping control` to `additional mapping`"); + } + nlohmann::json * additonal_section = GetJsonSection(rf_vmap,{"additional mapping"}); if(additonal_section) { ENSURE(additonal_section->is_array(), "`additional mapping` section should be a list of string"); diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index e1a1c8497..901829115 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -229,6 +229,32 @@ TEST(TestVlgTargetGen, PipeExampleRfmapPost) { vg.GenerateTargets(); } + + +TEST(TestVlgTargetGen, PipeStallRfmap) { + auto ila_model = SimplePipe::BuildStallModel(); + + auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); + auto rfDir = os_portable_append_dir(dirName, "rfmap"); + + VerilogVerificationTargetGenerator vg( + {}, // no include + {os_portable_append_dir(dirName, "simple_pipe_stall.v")}, // vlog files + "pipeline_v", // top_module_name + os_portable_append_dir(rfDir, + "vmap-rfmap-pvholder-stall.json"), // variable mapping + os_portable_append_dir(rfDir, + "cond-rfmap-pvholder-stall.json"), // instruction-mapping + os_portable_append_dir(dirName, "verify_stall"), // verification dir + ila_model.get(), // ILA model + VerilogVerificationTargetGenerator::backend_selector::PONO // engine + ); + + EXPECT_FALSE(vg.in_bad_state()); + + vg.GenerateTargets(); +} + // test all kinds of rfmap issue // test bad states @@ -296,15 +322,6 @@ TEST(TestVlgTargetGen, Memory) { TEST(TestVlgTargetGen, MemoryInternal) { // test the expansion of memory - - DebugLog::Enable("VTG.ReplWireEq"); - DebugLog::Enable("VTG.ReplAssert"); - DebugLog::Enable("VTG.ReplAssume"); - - DebugLog::Enable("VTG.AddWireEq"); - DebugLog::Enable("VTG.AddAssert"); - DebugLog::Enable("VTG.AddAssume"); - auto ila_model = MemorySwap::BuildSimpleSwapModel(); VerilogVerificationTargetGenerator::vtg_config_t @@ -332,6 +349,15 @@ TEST(TestVlgTargetGen, MemoryInternal) { // test the expansion of memory TEST(TestVlgTargetGen, MemoryInternalExternal) { auto ila_model = MemorySwap::BuildRfAsMemModel(); + DebugLog::Enable("VTG.ReplWireEq"); + DebugLog::Enable("VTG.ReplAssert"); + DebugLog::Enable("VTG.ReplAssume"); + + DebugLog::Enable("VTG.AddWireEq"); + DebugLog::Enable("VTG.AddAssert"); + DebugLog::Enable("VTG.AddAssume"); + + auto dirName = os_portable_join_dir({ILANG_TEST_SRC_ROOT, "unit-data", "vpipe", "vmem"}); @@ -360,7 +386,7 @@ TEST(TestVlgTargetGen, MemoryInternalExternalEntry6) { {}, // no include {dirName + "rf_as_mem_6rf.v"}, // vlog files "proc", // top_module_name - dirName + "vmap-rfarray.json", // variable mapping + dirName + "vmap-rfarray6.json", // variable mapping dirName + "cond-rfarray.json", // cond path dirName + "rfarray_rf6/", // output path ila_model.get(), diff --git a/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-stall.json b/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-stall.json new file mode 100644 index 000000000..9bc36068b --- /dev/null +++ b/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-stall.json @@ -0,0 +1,33 @@ +{ + // this is a comment + "global invariants": [ + "RTL.scoreboard[0][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd0)", + "RTL.scoreboard[0][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd0)", + "RTL.scoreboard[1][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd1)", + "RTL.scoreboard[1][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd1)", + "RTL.scoreboard[2][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd2)", + "RTL.scoreboard[2][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd2)", + "RTL.scoreboard[3][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd3)", + "RTL.scoreboard[3][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd3)" + ], + + "instructions": [ + { + "instruction": "NOP", + "ready signal": "#wb_iuv# == 1" + }, + { + "instruction": "ADD", + "ready signal": "#wb_iuv# == 1" + }, + { + "instruction": "SET", + "ready signal": "#wb_iuv# == 1" + }, + { + "instruction": "NAND", + "ready signal": "#wb_iuv# == 1" + } + ] +} + diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-stall.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-stall.json new file mode 100644 index 000000000..adf2d5649 --- /dev/null +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-stall.json @@ -0,0 +1,68 @@ +{ + "state mapping": { + "r0":[ ["__START__", "RTL.registers[0] @ (#ex_wb_iuv# && RTL.wb_go)"] , ["1'b1", "RTL.registers[0]"] ] , + "r1":[ ["__START__", "RTL.registers[1] @ (#ex_wb_iuv# && RTL.wb_go)"] , ["1'b1", "RTL.registers[1]"] ] , + "r2":[ ["__START__", "RTL.registers[2] @ (#ex_wb_iuv# && RTL.wb_go)"] , ["1'b1", "RTL.registers[2]"] ] , + "r3":[ ["__START__", "RTL.registers[3] @ (#ex_wb_iuv# && RTL.wb_go)"] , ["1'b1", "RTL.registers[3]"] ] }, + + "input mapping": { + "inst":"RTL.inst" + }, + + "rtl-interface-connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + }, + + "monitor" : { + "stage_tracker" : { + "verilog": + [ "always @(posedge clk) begin", + " if(rst)", + " if_id_iuv <= 0;", + " else if(__START__)", + " if_id_iuv <= 1;", + " else if(if_id_iuv && RTL.id_go)", + " if_id_iuv <= 0;", + "end", + "", + "always @(posedge clk) begin", + " if(rst)", + " id_ex_iuv <= 0;", + " else if(if_id_iuv && RTL.id_go)", + " id_ex_iuv <= 1;", + " else if(id_ex_iuv && RTL.ex_go)", + " id_ex_iuv <= 0;", + "end", + "", + "always @(posedge clk) begin", + " if(rst)", + " ex_wb_iuv <= 0;", + " else if(id_ex_iuv && RTL.ex_go)", + " ex_wb_iuv <= 1;", + " else if(ex_wb_iuv && RTL.wb_go)", + " ex_wb_iuv <= 0;", + "end", + "", + "always @(posedge clk) begin", + " if(rst)", + " wb_iuv <= 0;", + " else if(ex_wb_iuv && RTL.wb_go)", + " wb_iuv <= 1;", + " else if(wb_iuv )", + " wb_iuv <= 0; // just last for one cycle", + "end"], + "defs" :[ + ["if_id_iuv", 1, "reg"], + ["id_ex_iuv", 1, "reg"], + ["ex_wb_iuv", 1, "reg"], + ["wb_iuv", 1, "reg"] + ], + "refs" :["RTL.if_go", "RTL.id_go", "RTL.ex_go", "RTL.wb_go"] + } + }, // end of monitor + "additional mapping" : [ + "#decode# |-> ( RTL.inst_ready && RTL.inst_valid)", + "#decode# |-> ( RTL.inst == ILA.inst ) " // for the other time, there is no guarantee + ] +} diff --git a/test/unit-data/vpipe/simple_pipe_stall.v b/test/unit-data/vpipe/simple_pipe_stall.v new file mode 100644 index 000000000..8bc9c1605 --- /dev/null +++ b/test/unit-data/vpipe/simple_pipe_stall.v @@ -0,0 +1,304 @@ +`default_nettype none + +// Hongce Zhang @ Princeton +// A simple pipelined processor +// that can only do add/sub/nop/and +// with only 4 registers +// for simplicity, we even make the instruction part +// as input +// ADD/SUB/AND 2-bit op, 2-bit rs1, 2-bit rs2, 2-bit rd +// SET 2-bit op, 4bit imm 2-bit rd + +// -- ID --|-- EX --|-- WB +// ^ | | +// | | | +// ------------------- +// forwarding + +`define OP_NOP 2'b00 +`define OP_ADD 2'b01 +`define OP_SET 2'b10 +`define OP_NAND 2'b11 + +module pipeline_v( + input wire clk, input wire rst, + input wire [7:0] inst, input wire inst_valid, output wire inst_ready, + input wire stallex, input wire stallwb, + input wire [1:0] dummy_read_rf, output wire [7:0] dummy_rf_data +); + +// TODO: finish this +// check invariant +// run inst sim + + +// main pipeline +reg [7:0] if_id_inst; +// can be removed +reg [7:0] id_ex_inst; +reg [7:0] ex_wb_inst; + +reg [7:0] id_ex_operand1; +reg [7:0] id_ex_operand2; +reg [1:0] id_ex_op; +reg [1:0] id_ex_rd; +reg id_ex_reg_wen; + +reg [7:0] ex_wb_val; +reg [1:0] ex_wb_rd; +reg ex_wb_reg_wen; + +reg [7:0] registers[3:0]; + + +// interlocking +// using ready valid signal + +wire stallif = 0; +wire if_go; + +reg if_id_valid; +wire id_if_ready; +wire id_go; +wire stallid = 0; + +reg id_ex_valid; +wire ex_id_ready; +wire ex_go; + +reg ex_wb_valid; +wire wb_ex_ready; +wire wb_go; + + +// +// IF --|-- ID --|-- EX --|-- WB +// ^ | | +// | | | +// ------------------- +// forwarding logic + +wire [1:0] forwarding_id_wdst; +wire forwarding_id_wen; +wire [1:0] forwarding_ex_wdst; +wire forwarding_ex_wen; + + +// plus ex_go +wire [7:0] ex_forwarding_val; + +// plus wb_go +wire [7:0] wb_forwarding_val; + +reg [1:0] scoreboard[0:3]; // for reg 0-3 + +// -------------------------------------- +// scoreboard +wire [1:0] scoreboard_nxt[0:3]; + +assign scoreboard_nxt[0][1] = + id_go ? forwarding_id_wen && forwarding_id_wdst == 2'd0 : + ex_go ? 1'b0 : scoreboard[0][1]; + +assign scoreboard_nxt[0][0] = + ex_go ? forwarding_ex_wen && forwarding_ex_wdst == 2'd0 : + wb_go ? 1'b0 : scoreboard[0][0]; + +assign scoreboard_nxt[1][1] = + id_go ? forwarding_id_wen && forwarding_id_wdst == 2'd1 : + ex_go ? 1'b0 : scoreboard[1][1]; + +assign scoreboard_nxt[1][0] = + ex_go ? forwarding_ex_wen && forwarding_ex_wdst == 2'd1 : + wb_go ? 1'b0 : scoreboard[1][0]; + +assign scoreboard_nxt[2][1] = + id_go ? forwarding_id_wen && forwarding_id_wdst == 2'd2 : + ex_go ? 1'b0 : scoreboard[2][1]; + +assign scoreboard_nxt[2][0] = + ex_go ? forwarding_ex_wen && forwarding_ex_wdst == 2'd2 : + wb_go ? 1'b0 : scoreboard[2][0]; + +assign scoreboard_nxt[3][1] = + id_go ? forwarding_id_wen && forwarding_id_wdst == 2'd3 : + ex_go ? 1'b0 : scoreboard[3][1]; + +assign scoreboard_nxt[3][0] = + ex_go ? forwarding_ex_wen && forwarding_ex_wdst == 2'd3 : + wb_go ? 1'b0 : scoreboard[3][0]; + +// in reality, this will be generate +always @(posedge clk) begin + if (rst) begin + scoreboard[0] <= 0; + scoreboard[1] <= 0; + scoreboard[2] <= 0; + scoreboard[3] <= 0; + end else begin + scoreboard[0] <= scoreboard_nxt[0]; + scoreboard[1] <= scoreboard_nxt[1]; + scoreboard[2] <= scoreboard_nxt[2]; + scoreboard[3] <= scoreboard_nxt[3]; + end +end + +// -------------------------------------- +// IF + +assign inst_ready = ~stallif && (id_if_ready || ~if_id_valid); +assign if_go = inst_valid && inst_ready; + +always @(posedge clk) begin + if(rst) begin + if_id_valid <= 0; + end + if(if_go) begin + if_id_valid <= inst_valid && ~stallif; + if_id_inst <= inst; + end else begin + if(id_go) + if_id_valid <= 1'b0; + end +end + +// -------------------------------------- +// ID + +// datapath +wire [1:0] op = if_id_inst[7:6]; +wire [1:0] rs1= if_id_inst[5:4]; +wire [1:0] rs2= if_id_inst[3:2]; +wire [1:0] rd = if_id_inst[1:0]; +wire [7:0] immd = {4'd0, if_id_inst[5:2]}; +wire id_wen = op == `OP_ADD || op == `OP_SET || op == `OP_NAND; + +wire [1:0] rs1_write_loc = scoreboard[rs1]; +wire [1:0] rs2_write_loc = scoreboard[rs2]; +wire [7:0] rs1_val = registers[rs1]; +wire [7:0] rs2_val = registers[rs2]; + +wire [7:0] id_rs1_val = rs1_write_loc == 2'b00 ? rs1_val : + rs1_write_loc == 2'b01 ? wb_forwarding_val : + ex_forwarding_val ; // 10/11 + +wire [7:0] id_rs2_val = rs2_write_loc == 2'b00 ? rs2_val : + rs2_write_loc == 2'b01 ? wb_forwarding_val : + ex_forwarding_val ; // 10/11 + +wire [7:0] id_operand1 = op == `OP_SET ? immd : id_rs1_val; +wire [7:0] id_operand2 = id_rs2_val; + +// forwarding output +assign forwarding_id_wdst = rd; +assign forwarding_id_wen = if_id_valid && id_wen; + +// control +assign id_if_ready = !stallid && + ( ex_id_ready || ( !id_ex_valid ) ); +assign id_go = if_id_valid & id_if_ready; + + +always @(posedge clk) begin + if(rst) begin + id_ex_reg_wen <= 1'b0; + id_ex_valid <= 1'b0; + end + else begin + if(id_go) begin + id_ex_inst <= if_id_inst; + + id_ex_valid <= if_id_valid & ~stallid; + id_ex_op <= op; + id_ex_reg_wen <= id_wen; + id_ex_rd <= rd; + id_ex_operand1 <= id_operand1; + id_ex_operand2 <= id_operand2; + end else begin + if(ex_go) + id_ex_valid <= 1'b0; + end + end +end + +// -------------------------------------- +// EX + +// datapath +wire[7:0] ex_alu_result = id_ex_op == `OP_ADD ? id_ex_operand1 + id_ex_operand2 : + id_ex_op == `OP_SET ? id_ex_operand1 : + id_ex_op == `OP_NAND ? ~(id_ex_operand1 & id_ex_operand2) : + 8'bxxxxxxxx; // `OP_NOP +assign ex_forwarding_val = ex_alu_result; + +assign forwarding_ex_wdst = id_ex_rd; +assign forwarding_ex_wen = id_ex_valid && id_ex_reg_wen; + +// control +assign ex_id_ready = !stallex && + ( wb_ex_ready || ( !ex_wb_valid ) ); +// stallex wb_ex_ready ex_wb_valid ex_id_ready +// 1 x x 0 +// 0 1 x 1 +// 0 0 0 1 +// 0 0 1 0 + +assign ex_go = id_ex_valid && ex_id_ready; + + +always @(posedge clk) begin + if (rst) begin + // reset + ex_wb_reg_wen <= 1'b0; + ex_wb_valid <= 1'b0; + end + else begin + if (ex_go) begin + ex_wb_inst <= id_ex_inst; + + ex_wb_valid <= id_ex_valid && !stallex; + ex_wb_reg_wen <= id_ex_reg_wen; + ex_wb_val <= ex_alu_result; + ex_wb_rd <= id_ex_rd; + end else begin + if(wb_go) + ex_wb_valid <= 1'b0; + end + end +end + + +// -------------------------------------- + + +// WB +assign wb_ex_ready = !stallwb; +assign wb_go = ex_wb_valid && wb_ex_ready; + +assign wb_forwarding_val = ex_wb_val; + +always @(posedge clk ) begin + if (wb_go && ex_wb_reg_wen) begin + registers[ex_wb_rd] <= ex_wb_val; + end +end + +// dummy read +assign dummy_rf_data = registers[dummy_read_rf]; + + +// formal properties +/* +assert property (scoreboard[0][1] == ( id_ex_valid && id_ex_reg_wen && id_ex_rd == 2'd0)); +assert property (scoreboard[0][0] == ( ex_wb_valid && ex_wb_reg_wen && ex_wb_rd == 2'd0)); + +assert property (scoreboard[1][1] == ( id_ex_valid && id_ex_reg_wen && id_ex_rd == 2'd1)); +assert property (scoreboard[1][0] == ( ex_wb_valid && ex_wb_reg_wen && ex_wb_rd == 2'd1)); + +assert property (scoreboard[2][1] == ( id_ex_valid && id_ex_reg_wen && id_ex_rd == 2'd2)); +assert property (scoreboard[2][0] == ( ex_wb_valid && ex_wb_reg_wen && ex_wb_rd == 2'd2)); + +assert property (scoreboard[3][1] == ( id_ex_valid && id_ex_reg_wen && id_ex_rd == 2'd3)); +assert property (scoreboard[3][0] == ( ex_wb_valid && ex_wb_reg_wen && ex_wb_rd == 2'd3)); +*/ +endmodule diff --git a/test/unit-data/vpipe/verify_stall/.gitignore b/test/unit-data/vpipe/verify_stall/.gitignore new file mode 100644 index 000000000..1bb4ab336 --- /dev/null +++ b/test/unit-data/vpipe/verify_stall/.gitignore @@ -0,0 +1,5 @@ +invariants/* +ADD/* +NOP/* +SET/* +NAND/* diff --git a/test/unit-include/pipe_ila.h b/test/unit-include/pipe_ila.h index 786825598..ab18f8bd3 100644 --- a/test/unit-include/pipe_ila.h +++ b/test/unit-include/pipe_ila.h @@ -14,6 +14,7 @@ class SimplePipe { public: static Ila BuildModel(); + static Ila BuildStallModel(); }; // class SimplePipe diff --git a/test/unit-src/pipe_ila.cc b/test/unit-src/pipe_ila.cc index eb5e8e671..f53315de6 100644 --- a/test/unit-src/pipe_ila.cc +++ b/test/unit-src/pipe_ila.cc @@ -66,6 +66,60 @@ Ila SimplePipe::BuildModel() { return pipe_ila; } + +Ila SimplePipe::BuildStallModel() { + // build the ila + auto pipe_ila = Ila("simplePipe"); + pipe_ila.SetValid(BoolConst(true)); + + auto inst = pipe_ila.NewBvInput("inst", 8); + auto r0 = pipe_ila.NewBvState("r0", 8); + auto r1 = pipe_ila.NewBvState("r1", 8); + auto r2 = pipe_ila.NewBvState("r2", 8); + auto r3 = pipe_ila.NewBvState("r3", 8); + + auto op = inst(7, 6); + auto rs1 = inst(5, 4); + auto rs2 = inst(3, 2); + auto rd = inst(1, 0); + auto immd = ZExt( inst(5,2), 8); + + auto rs1_val = Ite(rs1 == 0, r0, Ite(rs1 == 1, r1, Ite(rs1 == 2, r2, r3))); + + auto rs2_val = Ite(rs2 == 0, r0, Ite(rs2 == 1, r1, Ite(rs2 == 2, r2, r3))); + + auto NOP = pipe_ila.NewInstr("NOP"); + { + NOP.SetDecode(op == BvConst(0, 2)); + NOP.SetUpdate(r0, r0); + NOP.SetUpdate(r1, r1); + NOP.SetUpdate(r2, r2); + NOP.SetUpdate(r3, r3); + } + + auto ADD = pipe_ila.NewInstr("ADD"); + { + ADD.SetDecode(op == BvConst(1, 2)); + auto res = rs1_val + rs2_val; + SET_UPDATE(ADD, rd, res); + } + + auto SET = pipe_ila.NewInstr("SET"); + { + SET.SetDecode(op == BvConst(2, 2)); + SET_UPDATE(SET, rd, immd); + } + + auto NAND = pipe_ila.NewInstr("NAND"); + { + NAND.SetDecode(op == BvConst(3, 2)); + auto res = ~( rs1_val & rs2_val ); + SET_UPDATE(NAND, rd, res); + } + + return pipe_ila; +} + Ila UndetVal::BuildModel() { auto m = Ila("undetval"); auto r0 = m.NewBvState("r0", 8); From a867fcbc734e59ad57d3c744e58d18a60d6a828e Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 9 Sep 2021 14:46:45 +0800 Subject: [PATCH 36/78] new benchmark --- src/vtarget-out/gen_util.cc | 76 ++--- src/vtarget-out/single_target_misc.cc | 8 +- test/t_vtarget_gen.cc | 48 +++ .../cond-rfmap-pvholder-stall-short.json | 33 ++ .../vpipe/rfmap/cond-rfmap-stall-short.json | 33 ++ .../vmap-rfmap-pvholder-stall-short.json | 47 +++ .../vpipe/rfmap/vmap-rfmap-stall-short.json | 73 +++++ .../unit-data/vpipe/simple_pipe_stall_short.v | 290 ++++++++++++++++++ .../vpipe/verify_stall_short/.gitignore | 5 + .../verify_stall_short_nopvholder/.gitignore | 5 + test/unit-data/vpipe/vmem/vmap-rfarray.json | 39 +-- test/unit-data/vpipe/vmem/vmap-rfarray6.json | 27 ++ 12 files changed, 619 insertions(+), 65 deletions(-) create mode 100644 test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-stall-short.json create mode 100644 test/unit-data/vpipe/rfmap/cond-rfmap-stall-short.json create mode 100644 test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-stall-short.json create mode 100644 test/unit-data/vpipe/rfmap/vmap-rfmap-stall-short.json create mode 100644 test/unit-data/vpipe/simple_pipe_stall_short.v create mode 100644 test/unit-data/vpipe/verify_stall_short/.gitignore create mode 100644 test/unit-data/vpipe/verify_stall_short_nopvholder/.gitignore create mode 100644 test/unit-data/vpipe/vmem/vmap-rfarray6.json diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 86674cbe8..208cc3fea 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -483,43 +483,45 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, // mem write assertion // vlg_ila.ila_wports - const auto & write_ports = vlg_ila.ila_wports.at(ila_state_name); - unsigned rfmap_node_idx = 0; - - for(const auto & wport : write_ports) { - // the reason for _d1: see ConstructWrapper_get_ila_module_inst - // in single_target_connect.cc - size_t no = wport.first; - auto ila_wen = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_wen" + "_d1"); - auto ila_waddr = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_waddr" + "_d1"); - auto ila_wdata = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_wdata" + "_d1"); - - while(!(vmap.externmem_map.at(rfmap_node_idx).wport_mapped) - && rfmap_node_idx < vmap.externmem_map.size()) - ++ rfmap_node_idx; - - ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) - <<"#ila.write-port=" << write_ports.size() << " does not match #rfmap.write-port" - <<", and this is a mismatch for sname:" << ila_state_name; - - const auto & rfmap_wport = vmap.externmem_map.at(rfmap_node_idx); - - auto rtl_wen = singlemap_bv_to_rfexpr(rfmap_wport.wen_map); - auto rtl_waddr = singlemap_bv_to_rfexpr(rfmap_wport.waddr_map); - auto rtl_wdata = singlemap_bv_to_rfexpr(rfmap_wport.wdata_map); - - auto constr = - rfmap_and( - rfmap_eq(ila_wen , rtl_wen), - rfmap_imply(ila_wen, - rfmap_and( - rfmap_eq(ila_waddr, rtl_waddr), - rfmap_eq(ila_wdata, rtl_wdata)))); - - ADD_CONSTR(constr); - - ++ rfmap_node_idx; - } // for each write port + if(vlg_ila.ila_wports.find(ila_state_name) != vlg_ila.ila_wports.end()) { + const auto & write_ports = vlg_ila.ila_wports.at(ila_state_name); + unsigned rfmap_node_idx = 0; + + for(const auto & wport : write_ports) { + // the reason for _d1: see ConstructWrapper_get_ila_module_inst + // in single_target_connect.cc + size_t no = wport.first; + auto ila_wen = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_wen" + "_d1"); + auto ila_waddr = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_waddr" + "_d1"); + auto ila_wdata = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_wdata" + "_d1"); + + while(!(vmap.externmem_map.at(rfmap_node_idx).wport_mapped) + && rfmap_node_idx < vmap.externmem_map.size()) + ++ rfmap_node_idx; + + ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) + <<"#ila.write-port=" << write_ports.size() << " does not match #rfmap.write-port" + <<", and this is a mismatch for sname:" << ila_state_name; + + const auto & rfmap_wport = vmap.externmem_map.at(rfmap_node_idx); + + auto rtl_wen = singlemap_bv_to_rfexpr(rfmap_wport.wen_map); + auto rtl_waddr = singlemap_bv_to_rfexpr(rfmap_wport.waddr_map); + auto rtl_wdata = singlemap_bv_to_rfexpr(rfmap_wport.wdata_map); + + auto constr = + rfmap_and( + rfmap_eq(ila_wen , rtl_wen), + rfmap_imply(ila_wen, + rfmap_and( + rfmap_eq(ila_waddr, rtl_waddr), + rfmap_eq(ila_wdata, rtl_wdata)))); + + ADD_CONSTR(constr); + + ++ rfmap_node_idx; + } // for each write port + } // end of if wport found } // end of if assume else assert } #undef ADD_CONSTR diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index a11fd9442..bee85b2f8 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -309,13 +309,13 @@ void VlgSglTgtGen::ConstructWrapper_add_post_value_holder() { // for sanity check vlg_wrapper.add_reg(pv_name+"_sn_vhold", post_val_holder.second.width); rfmap_add_internal_reg(pv_name+"_sn_vhold", post_val_holder.second.width); - vlg_wrapper.add_reg(pv_name+"_sn_value", post_val_holder.second.width); - rfmap_add_internal_reg(pv_name+"_sn_value", post_val_holder.second.width); + vlg_wrapper.add_wire(pv_name+"_sn_value", post_val_holder.second.width); + rfmap_add_internal_wire(pv_name+"_sn_value", post_val_holder.second.width); vlg_wrapper.add_reg(pv_name+"_sn_condmet", 1); rfmap_add_internal_reg(pv_name+"_sn_condmet", 1); - vlg_wrapper.add_reg(pv_name+"_sn_cond", 1); - rfmap_add_internal_reg(pv_name+"_sn_cond", 1); + vlg_wrapper.add_wire(pv_name+"_sn_cond", 1); + rfmap_add_internal_wire(pv_name+"_sn_cond", 1); vlg_wrapper.add_init_stmt(pv_name+"_sn_condmet <= 1'b0;"); vlg_wrapper.add_always_stmt("if (" + pv_name+"_sn_cond ) begin " + pv_name+"_sn_condmet <= 1'b1; " diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index 901829115..e107cb600 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -230,6 +230,54 @@ TEST(TestVlgTargetGen, PipeExampleRfmapPost) { } +TEST(TestVlgTargetGen, PipeStallRfmapShortNoValueHolder) { + auto ila_model = SimplePipe::BuildStallModel(); + + auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); + auto rfDir = os_portable_append_dir(dirName, "rfmap"); + + VerilogVerificationTargetGenerator vg( + {}, // no include + {os_portable_append_dir(dirName, "simple_pipe_stall_short.v")}, // vlog files + "pipeline_v", // top_module_name + os_portable_append_dir(rfDir, + "vmap-rfmap-stall-short.json"), // variable mapping + os_portable_append_dir(rfDir, + "cond-rfmap-stall-short.json"), // instruction-mapping + os_portable_append_dir(dirName, "verify_stall_short_nopvholder"), // verification dir + ila_model.get(), // ILA model + VerilogVerificationTargetGenerator::backend_selector::PONO // engine + ); + + EXPECT_FALSE(vg.in_bad_state()); + + vg.GenerateTargets(); +} + +TEST(TestVlgTargetGen, PipeStallRfmapShort) { + auto ila_model = SimplePipe::BuildStallModel(); + + auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); + auto rfDir = os_portable_append_dir(dirName, "rfmap"); + + VerilogVerificationTargetGenerator vg( + {}, // no include + {os_portable_append_dir(dirName, "simple_pipe_stall_short.v")}, // vlog files + "pipeline_v", // top_module_name + os_portable_append_dir(rfDir, + "vmap-rfmap-pvholder-stall-short.json"), // variable mapping + os_portable_append_dir(rfDir, + "cond-rfmap-pvholder-stall-short.json"), // instruction-mapping + os_portable_append_dir(dirName, "verify_stall_short"), // verification dir + ila_model.get(), // ILA model + VerilogVerificationTargetGenerator::backend_selector::PONO // engine + ); + + EXPECT_FALSE(vg.in_bad_state()); + + vg.GenerateTargets(); +} + TEST(TestVlgTargetGen, PipeStallRfmap) { auto ila_model = SimplePipe::BuildStallModel(); diff --git a/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-stall-short.json b/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-stall-short.json new file mode 100644 index 000000000..b5848f1a1 --- /dev/null +++ b/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-stall-short.json @@ -0,0 +1,33 @@ +{ + // this is a comment + "global invariants": [ + "RTL.scoreboard[0][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd0)", + "RTL.scoreboard[0][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd0)", + "RTL.scoreboard[1][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd1)", + "RTL.scoreboard[1][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd1)", + "RTL.scoreboard[2][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd2)", + "RTL.scoreboard[2][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd2)", + "RTL.scoreboard[3][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd3)", + "RTL.scoreboard[3][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd3)" + ], + + "instructions": [ + { + "instruction": "NOP", + "ready signal": "#ppl_stage_finish# == 1" + }, + { + "instruction": "ADD", + "ready signal": "#ppl_stage_finish# == 1" + }, + { + "instruction": "SET", + "ready signal": "#ppl_stage_finish# == 1" + }, + { + "instruction": "NAND", + "ready signal": "#ppl_stage_finish# == 1" + } + ] +} + diff --git a/test/unit-data/vpipe/rfmap/cond-rfmap-stall-short.json b/test/unit-data/vpipe/rfmap/cond-rfmap-stall-short.json new file mode 100644 index 000000000..b5848f1a1 --- /dev/null +++ b/test/unit-data/vpipe/rfmap/cond-rfmap-stall-short.json @@ -0,0 +1,33 @@ +{ + // this is a comment + "global invariants": [ + "RTL.scoreboard[0][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd0)", + "RTL.scoreboard[0][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd0)", + "RTL.scoreboard[1][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd1)", + "RTL.scoreboard[1][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd1)", + "RTL.scoreboard[2][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd2)", + "RTL.scoreboard[2][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd2)", + "RTL.scoreboard[3][1:1] == ( RTL.id_ex_valid && RTL.id_ex_reg_wen && RTL.id_ex_rd == 2'd3)", + "RTL.scoreboard[3][0:0] == ( RTL.ex_wb_valid && RTL.ex_wb_reg_wen && RTL.ex_wb_rd == 2'd3)" + ], + + "instructions": [ + { + "instruction": "NOP", + "ready signal": "#ppl_stage_finish# == 1" + }, + { + "instruction": "ADD", + "ready signal": "#ppl_stage_finish# == 1" + }, + { + "instruction": "SET", + "ready signal": "#ppl_stage_finish# == 1" + }, + { + "instruction": "NAND", + "ready signal": "#ppl_stage_finish# == 1" + } + ] +} + diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-stall-short.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-stall-short.json new file mode 100644 index 000000000..c7b8e123a --- /dev/null +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-stall-short.json @@ -0,0 +1,47 @@ +{ + "state mapping": { + "r0":[ ["__START__", "RTL.registers[0] @ (#ppl_stage_wb# && RTL.wb_go)"] , ["1'b1", "RTL.registers[0]"] ] , + "r1":[ ["__START__", "RTL.registers[1] @ (#ppl_stage_wb# && RTL.wb_go)"] , ["1'b1", "RTL.registers[1]"] ] , + "r2":[ ["__START__", "RTL.registers[2] @ (#ppl_stage_wb# && RTL.wb_go)"] , ["1'b1", "RTL.registers[2]"] ] , + "r3":[ ["__START__", "RTL.registers[3] @ (#ppl_stage_wb# && RTL.wb_go)"] , ["1'b1", "RTL.registers[3]"] ] }, + + "input mapping": { + "inst":"RTL.inst" + }, + + "rtl-interface-connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + }, + + "monitor" : { + // pipeline tracker + "ppl_stage" : { + "template" : "phase tracker", + "rules" : [ + { // 1 + "name" : "ex", + "enter" : {"event" : "#decode#"}, + "exit" : {"event" : "RTL.ex_go"} + }, + + { // 2 + "name" : "wb", + "enter" : {"event" : "#ppl_stage_ex# && RTL.ex_go"}, + "exit" : {"event" : "RTL.wb_go"} + }, + + { // 3 + "name" : "finish", + "enter" : {"event" : "#ppl_stage_wb# && RTL.wb_go"}, + "exit" : {"event" : "1"} + } + ] + + } + }, // end of monitor + "additional mapping" : [ + "#decode# |-> ( RTL.inst_ready && RTL.inst_valid)", + "#decode# |-> ( RTL.inst == ILA.inst ) " // for the other time, there is no guarantee + ] +} diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-stall-short.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-stall-short.json new file mode 100644 index 000000000..208e96ebc --- /dev/null +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-stall-short.json @@ -0,0 +1,73 @@ +{ + "state mapping": { + + "r0": + [ ["#decode# && RTL.scoreboard[0] == 2'b10 ", " RTL.ex_alu_result == ILA.r0"], + ["#decode# && RTL.scoreboard[0] == 2'b11 ", " RTL.ex_alu_result == ILA.r0"], + ["#decode# && RTL.scoreboard[0] == 2'b01 ", " RTL.ex_wb_val == ILA.r0"], + ["#decode# && RTL.scoreboard[0] == 2'b00 ", " RTL.registers[0] == ILA.r0"], + ["1'b1", "RTL.registers[0]"]] , + + "r1": + [ ["#decode# && RTL.scoreboard[1] == 2'b10 ", "RTL.ex_alu_result == ILA.r1"], + ["#decode# && RTL.scoreboard[1] == 2'b11 ", "RTL.ex_alu_result == ILA.r1"], + ["#decode# && RTL.scoreboard[1] == 2'b01 ", "RTL.ex_wb_val == ILA.r1"], + ["#decode# && RTL.scoreboard[1] == 2'b00 ", "RTL.registers[1] == ILA.r1"], + ["1'b1", "RTL.registers[1]"]], + + "r2": + [ ["#decode# && RTL.scoreboard[2] == 2'b10 ", "RTL.ex_alu_result == ILA.r2"], + ["#decode# && RTL.scoreboard[2] == 2'b11 ", "RTL.ex_alu_result == ILA.r2"], + ["#decode# && RTL.scoreboard[2] == 2'b01 ", "RTL.ex_wb_val == ILA.r2"], + ["#decode# && RTL.scoreboard[2] == 2'b00 ", "RTL.registers[2] == ILA.r2"], + ["1'b1", "RTL.registers[2]"]], + + "r3": + + [ ["#decode# && RTL.scoreboard[3] == 2'b10 " , "RTL.ex_alu_result"], + ["#decode# && RTL.scoreboard[3] == 2'b11 " , "RTL.ex_alu_result"], + ["#decode# && RTL.scoreboard[3] == 2'b01 " , " RTL.ex_wb_val == ILA.r3"], + ["#decode# && RTL.scoreboard[3] == 2'b00 " , " RTL.registers[3] == ILA.r3"], + ["1'b1", "RTL.registers[3]"]] + }, + + "input mapping": { + "inst":"RTL.inst" + }, + + "rtl-interface-connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + }, + + "monitor" : { + // pipeline tracker + "ppl_stage" : { + "template" : "phase tracker", + "rules" : [ + { // 1 + "name" : "ex", + "enter" : {"event" : "#decode#"}, + "exit" : {"event" : "RTL.ex_go"} + }, + + { // 2 + "name" : "wb", + "enter" : {"event" : "#ppl_stage_ex# && RTL.ex_go"}, + "exit" : {"event" : "RTL.wb_go"} + }, + + { // 3 + "name" : "finish", + "enter" : {"event" : "#ppl_stage_wb# && RTL.wb_go"}, + "exit" : {"event" : "1"} + } + ] + + } + }, // end of monitor + "additional mapping" : [ + "#decode# |-> ( RTL.inst_ready && RTL.inst_valid)", + "#decode# |-> ( RTL.inst == ILA.inst ) " // for the other time, there is no guarantee + ] +} diff --git a/test/unit-data/vpipe/simple_pipe_stall_short.v b/test/unit-data/vpipe/simple_pipe_stall_short.v new file mode 100644 index 000000000..b838977e7 --- /dev/null +++ b/test/unit-data/vpipe/simple_pipe_stall_short.v @@ -0,0 +1,290 @@ +`default_nettype none + +// Hongce Zhang @ Princeton +// A simple pipelined processor +// that can only do add/sub/nop/and +// with only 4 registers +// for simplicity, we even make the instruction part +// as input +// ADD/SUB/AND 2-bit op, 2-bit rs1, 2-bit rs2, 2-bit rd +// SET 2-bit op, 4bit imm 2-bit rd + +// -- ID --|-- EX --|-- WB +// ^ | | +// | | | +// ------------------- +// forwarding + +`define OP_NOP 2'b00 +`define OP_ADD 2'b01 +`define OP_SET 2'b10 +`define OP_NAND 2'b11 + +module pipeline_v( + input clk, input rst, + input [7:0] inst, input inst_valid, output inst_ready, + input stallex, input stallwb, + input [1:0] dummy_read_rf, output [7:0] dummy_rf_data +); + +// TODO: finish this +// check invariant +// run inst sim + + +// main pipeline +wire [7:0] if_id_inst; +// can be removed +reg [7:0] id_ex_inst; +reg [7:0] ex_wb_inst; + +reg [7:0] id_ex_operand1; +reg [7:0] id_ex_operand2; +reg [1:0] id_ex_op; +reg [1:0] id_ex_rd; +reg id_ex_reg_wen; + +reg [7:0] ex_wb_val; +reg [1:0] ex_wb_rd; +reg ex_wb_reg_wen; + +reg [7:0] registers[3:0]; + + +// interlocking +// using ready valid signal + + +wire if_id_valid; +wire id_if_ready; +wire id_go; +wire stallid = 0; + +reg id_ex_valid; +wire ex_id_ready; +wire ex_go; + +reg ex_wb_valid; +wire wb_ex_ready; +wire wb_go; + + +// +// IF --|-- ID --|-- EX --|-- WB +// ^ | | +// | | | +// ------------------- +// forwarding logic + +wire [1:0] forwarding_id_wdst; +wire forwarding_id_wen; +wire [1:0] forwarding_ex_wdst; +wire forwarding_ex_wen; + + +// plus ex_go +wire [7:0] ex_forwarding_val; + +// plus wb_go +wire [7:0] wb_forwarding_val; + +reg [1:0] scoreboard[0:3]; // for reg 0-3 + +// -------------------------------------- +// scoreboard +wire [1:0] scoreboard_nxt[0:3]; + +assign scoreboard_nxt[0][1] = + id_go ? forwarding_id_wen && forwarding_id_wdst == 2'd0 : + ex_go ? 1'b0 : scoreboard[0][1]; + +assign scoreboard_nxt[0][0] = + ex_go ? forwarding_ex_wen && forwarding_ex_wdst == 2'd0 : + wb_go ? 1'b0 : scoreboard[0][0]; + +assign scoreboard_nxt[1][1] = + id_go ? forwarding_id_wen && forwarding_id_wdst == 2'd1 : + ex_go ? 1'b0 : scoreboard[1][1]; + +assign scoreboard_nxt[1][0] = + ex_go ? forwarding_ex_wen && forwarding_ex_wdst == 2'd1 : + wb_go ? 1'b0 : scoreboard[1][0]; + +assign scoreboard_nxt[2][1] = + id_go ? forwarding_id_wen && forwarding_id_wdst == 2'd2 : + ex_go ? 1'b0 : scoreboard[2][1]; + +assign scoreboard_nxt[2][0] = + ex_go ? forwarding_ex_wen && forwarding_ex_wdst == 2'd2 : + wb_go ? 1'b0 : scoreboard[2][0]; + +assign scoreboard_nxt[3][1] = + id_go ? forwarding_id_wen && forwarding_id_wdst == 2'd3 : + ex_go ? 1'b0 : scoreboard[3][1]; + +assign scoreboard_nxt[3][0] = + ex_go ? forwarding_ex_wen && forwarding_ex_wdst == 2'd3 : + wb_go ? 1'b0 : scoreboard[3][0]; + +// in reality, this will be generate +always @(posedge clk) begin + if (rst) begin + scoreboard[0] <= 0; + scoreboard[1] <= 0; + scoreboard[2] <= 0; + scoreboard[3] <= 0; + end else begin + scoreboard[0] <= scoreboard_nxt[0]; + scoreboard[1] <= scoreboard_nxt[1]; + scoreboard[2] <= scoreboard_nxt[2]; + scoreboard[3] <= scoreboard_nxt[3]; + end +end + +// -------------------------------------- +// IF + +assign inst_ready = id_if_ready; +assign if_id_inst = inst; +assign if_id_valid = inst_valid; + +// -------------------------------------- +// ID + +// datapath +wire [1:0] op = if_id_inst[7:6]; +wire [1:0] rs1= if_id_inst[5:4]; +wire [1:0] rs2= if_id_inst[3:2]; +wire [1:0] rd = if_id_inst[1:0]; +wire [7:0] immd = {4'd0, if_id_inst[5:2]}; +wire id_wen = op == `OP_ADD || op == `OP_SET || op == `OP_NAND; + +wire [1:0] rs1_write_loc = scoreboard[rs1]; +wire [1:0] rs2_write_loc = scoreboard[rs2]; +wire [7:0] rs1_val = registers[rs1]; +wire [7:0] rs2_val = registers[rs2]; + +wire [7:0] id_rs1_val = rs1_write_loc == 2'b00 ? rs1_val : + rs1_write_loc == 2'b01 ? wb_forwarding_val : + ex_forwarding_val ; // 10/11 + +wire [7:0] id_rs2_val = rs2_write_loc == 2'b00 ? rs2_val : + rs2_write_loc == 2'b01 ? wb_forwarding_val : + ex_forwarding_val ; // 10/11 + +wire [7:0] id_operand1 = op == `OP_SET ? immd : id_rs1_val; +wire [7:0] id_operand2 = id_rs2_val; + +// forwarding output +assign forwarding_id_wdst = rd; +assign forwarding_id_wen = if_id_valid && id_wen; + +// control +assign id_if_ready = !stallid && + ( ex_id_ready || ( !id_ex_valid ) ); +assign id_go = if_id_valid & id_if_ready; + + +always @(posedge clk) begin + if(rst) begin + id_ex_reg_wen <= 1'b0; + id_ex_valid <= 1'b0; + end + else begin + if(id_go) begin + id_ex_inst <= if_id_inst; + + id_ex_valid <= if_id_valid & ~stallid; + id_ex_op <= op; + id_ex_reg_wen <= id_wen; + id_ex_rd <= rd; + id_ex_operand1 <= id_operand1; + id_ex_operand2 <= id_operand2; + end else begin + if(ex_go) + id_ex_valid <= 1'b0; + end + end +end + +// -------------------------------------- +// EX + +// datapath +wire[7:0] ex_alu_result = id_ex_op == `OP_ADD ? id_ex_operand1 + id_ex_operand2 : + id_ex_op == `OP_SET ? id_ex_operand1 : + id_ex_op == `OP_NAND ? ~(id_ex_operand1 & id_ex_operand2) : + 8'bxxxxxxxx; // `OP_NOP +assign ex_forwarding_val = ex_alu_result; + +assign forwarding_ex_wdst = id_ex_rd; +assign forwarding_ex_wen = id_ex_valid && id_ex_reg_wen; + +// control +assign ex_id_ready = !stallex && + ( wb_ex_ready || ( !ex_wb_valid ) ); +// stallex wb_ex_ready ex_wb_valid ex_id_ready +// 1 x x 0 +// 0 1 x 1 +// 0 0 0 1 +// 0 0 1 0 + +assign ex_go = id_ex_valid && ex_id_ready; + + +always @(posedge clk) begin + if (rst) begin + // reset + ex_wb_reg_wen <= 1'b0; + ex_wb_valid <= 1'b0; + end + else begin + if (ex_go) begin + ex_wb_inst <= id_ex_inst; + + ex_wb_valid <= id_ex_valid && !stallex; + ex_wb_reg_wen <= id_ex_reg_wen; + ex_wb_val <= ex_alu_result; + ex_wb_rd <= id_ex_rd; + end else begin + if(wb_go) + ex_wb_valid <= 1'b0; + end + end +end + + +// -------------------------------------- + + +// WB +assign wb_ex_ready = !stallwb; +assign wb_go = ex_wb_valid && wb_ex_ready; + +assign wb_forwarding_val = ex_wb_val; + +always @(posedge clk ) begin + if (wb_go && ex_wb_reg_wen) begin + registers[ex_wb_rd] <= ex_wb_val; + end +end + +// dummy read +assign dummy_rf_data = registers[dummy_read_rf]; + + +// formal properties +/* +assert property (scoreboard[0][1] == ( id_ex_valid && id_ex_reg_wen && id_ex_rd == 2'd0)); +assert property (scoreboard[0][0] == ( ex_wb_valid && ex_wb_reg_wen && ex_wb_rd == 2'd0)); + +assert property (scoreboard[1][1] == ( id_ex_valid && id_ex_reg_wen && id_ex_rd == 2'd1)); +assert property (scoreboard[1][0] == ( ex_wb_valid && ex_wb_reg_wen && ex_wb_rd == 2'd1)); + +assert property (scoreboard[2][1] == ( id_ex_valid && id_ex_reg_wen && id_ex_rd == 2'd2)); +assert property (scoreboard[2][0] == ( ex_wb_valid && ex_wb_reg_wen && ex_wb_rd == 2'd2)); + +assert property (scoreboard[3][1] == ( id_ex_valid && id_ex_reg_wen && id_ex_rd == 2'd3)); +assert property (scoreboard[3][0] == ( ex_wb_valid && ex_wb_reg_wen && ex_wb_rd == 2'd3)); +*/ +endmodule diff --git a/test/unit-data/vpipe/verify_stall_short/.gitignore b/test/unit-data/vpipe/verify_stall_short/.gitignore new file mode 100644 index 000000000..1bb4ab336 --- /dev/null +++ b/test/unit-data/vpipe/verify_stall_short/.gitignore @@ -0,0 +1,5 @@ +invariants/* +ADD/* +NOP/* +SET/* +NAND/* diff --git a/test/unit-data/vpipe/verify_stall_short_nopvholder/.gitignore b/test/unit-data/vpipe/verify_stall_short_nopvholder/.gitignore new file mode 100644 index 000000000..1bb4ab336 --- /dev/null +++ b/test/unit-data/vpipe/verify_stall_short_nopvholder/.gitignore @@ -0,0 +1,5 @@ +invariants/* +ADD/* +NOP/* +SET/* +NAND/* diff --git a/test/unit-data/vpipe/vmem/vmap-rfarray.json b/test/unit-data/vpipe/vmem/vmap-rfarray.json index d0cd1752f..1f8e23fbf 100644 --- a/test/unit-data/vpipe/vmem/vmap-rfarray.json +++ b/test/unit-data/vpipe/vmem/vmap-rfarray.json @@ -1,32 +1,23 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, - "instruction mapping": [], "state mapping": { "rf":"rf", - "mem":"**MEM**mem"}, + "mem":{ + "wen" :"RTL.mem_w_en", + "waddr" :"RTL.mem_w_addr", + "wdata" :"RTL.mem_w_data", + "ren" :"RTL.mem_r_en", + "raddr" :"RTL.mem_r_addr", + "rdata" :"RTL.mem_r_data" + }}, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "op":"op", - "operand1":"operand1", - "operand2":"operand2", - - "mem_w_en" :"**MEM**mem.wen", - "mem_w_addr":"**MEM**mem.waddr", - "mem_w_data":"**MEM**mem.wdata", - "mem_r_en" :"**MEM**mem.ren", - "mem_r_addr":"**MEM**mem.raddr", - "mem_r_data":"**MEM**mem.rdata" + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" }, - "mapping control" : [ - "m1.operand1 <= 5 && m1.operand2 <= 5" - ], - "annotation" : { - "memory" : { - "rf":"internal", - "mem":"external" - } + "input mapping": { + "op":"RTL.op", + "operand1":"RTL.operand1", + "operand2":"RTL.operand2" } } diff --git a/test/unit-data/vpipe/vmem/vmap-rfarray6.json b/test/unit-data/vpipe/vmem/vmap-rfarray6.json new file mode 100644 index 000000000..bcef7e97d --- /dev/null +++ b/test/unit-data/vpipe/vmem/vmap-rfarray6.json @@ -0,0 +1,27 @@ +{ + "state mapping": { + "rf":"rf", + "mem":{ + "wen" :"RTL.mem_w_en", + "waddr" :"RTL.mem_w_addr", + "wdata" :"RTL.mem_w_data", + "ren" :"RTL.mem_r_en", + "raddr" :"RTL.mem_r_addr", + "rdata" :"RTL.mem_r_data" + }}, + + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + }, + + "input mapping": { + "op":"RTL.op", + "operand1":"RTL.operand1", + "operand2":"RTL.operand2" + }, + + "mapping control" : [ + "ILA.operand1 <= 5 && ILA.operand2 <= 5" + ] +} From f8f84dccdc8242f125d92d410b57e1da117b222b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 13 Sep 2021 17:31:02 +0800 Subject: [PATCH 37/78] test vtg --- src/rfmap-in/verilog_rfmap.cc | 2 +- src/vtarget-out/gen_util.cc | 55 +++--- src/vtarget-out/single_target_misc.cc | 3 +- src/vtarget-out/vtarget_gen_pono.cc | 2 +- test/t_vtarget_gen.cc | 125 ++----------- test/unit-data/vpipe/reset/out-z3/.gitignore | 1 - .../vpipe/reset/out-z3/inst/__design_smt.smt2 | 175 ------------------ .../reset/out-z3/invariants/__design_smt.smt2 | 68 ------- .../vpipe/reset/{out-abc => out2}/.gitignore | 0 test/unit-data/vpipe/reset/rfmap/cond.json | 2 +- test/unit-data/vpipe/reset/rfmap/vmap-e1.json | 19 +- test/unit-data/vpipe/reset/rfmap/vmap-e2.json | 17 -- test/unit-data/vpipe/reset/rfmap/vmap-e3.json | 22 --- test/unit-data/vpipe/reset/rfmap/vmap-e4.json | 16 -- test/unit-data/vpipe/reset/rfmap/vmap.json | 22 +-- test/unit-data/vpipe/undetf/vmap-func.json | 34 ++-- test/unit-data/vpipe/undetf/vmap-val.json | 28 ++- test/unit-data/vpipe/vmem/cond-rd.json | 2 +- test/unit-data/vpipe/vmem/vmap-rd.json | 31 ++-- test/unit-data/vpipe/vmem/vmap-rfarray.json | 14 +- test/unit-data/vpipe/vmem/vmap-rfarray6.json | 16 +- 21 files changed, 114 insertions(+), 540 deletions(-) delete mode 100644 test/unit-data/vpipe/reset/out-z3/.gitignore delete mode 100644 test/unit-data/vpipe/reset/out-z3/inst/__design_smt.smt2 delete mode 100644 test/unit-data/vpipe/reset/out-z3/invariants/__design_smt.smt2 rename test/unit-data/vpipe/reset/{out-abc => out2}/.gitignore (100%) delete mode 100644 test/unit-data/vpipe/reset/rfmap/vmap-e2.json delete mode 100644 test/unit-data/vpipe/reset/rfmap/vmap-e3.json delete mode 100644 test/unit-data/vpipe/reset/rfmap/vmap-e4.json diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index e3eae1992..d01167419 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -745,7 +745,7 @@ VerilogRefinementMap::VerilogRefinementMap } // clock { // uf section - nlohmann::json * func_section = GetJsonSection(rf_vmap,{"functions"}); + nlohmann::json * func_section = GetJsonSection(rf_vmap,{"functions","function","uf","ufs","uninterpreted function","uninterpreted functions"}); if (func_section) { ENSURE(func_section->is_object(), "Expect `functions` to be map:name->list of invocation "); for(auto & n_invocation_pair : func_section->items()) { diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 208cc3fea..6f160a474 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -442,40 +442,41 @@ void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, if(true_for_assumpt_false_for_assert) { // mem read assumption - const auto & read_ports = vlg_ila.ila_rports.at(ila_state_name); - unsigned rfmap_node_idx = 0; - - for(const auto & rport : read_ports) { - size_t no = rport.first; + if(vlg_ila.ila_rports.find(ila_state_name) != vlg_ila.ila_rports.end()) { + const auto & read_ports = vlg_ila.ila_rports.at(ila_state_name); + unsigned rfmap_node_idx = 0; - auto ila_raddr = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_raddr"); - auto ila_rdata = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_rdata"); + for(const auto & rport : read_ports) { + size_t no = rport.first; - while(!(vmap.externmem_map.at(rfmap_node_idx).rport_mapped) - && rfmap_node_idx < vmap.externmem_map.size()) - ++ rfmap_node_idx; + auto ila_raddr = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_raddr"); + auto ila_rdata = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_rdata"); - ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) - <<"#ila.read-port=" << read_ports.size() << " does not match #rfmap.read-port" - <<", and this is a mismatch for sname:" << ila_state_name; - - const auto & rfmap_rport = vmap.externmem_map.at(rfmap_node_idx); - - // expect bit-vector rather than booleans - auto rtl_ren = singlemap_bv_to_rfexpr(rfmap_rport.ren_map); - auto rtl_raddr = singlemap_bv_to_rfexpr(rfmap_rport.raddr_map); - auto rtl_rdata = singlemap_bv_to_rfexpr(rfmap_rport.rdata_map); - - auto constr = rfmap_imply( rfmap_and( - {rtl_ren, rfmap_eq(ila_raddr, rtl_raddr)}), - rfmap_eq(ila_rdata, rtl_rdata)); + while(!(vmap.externmem_map.at(rfmap_node_idx).rport_mapped) + && rfmap_node_idx < vmap.externmem_map.size()) + ++ rfmap_node_idx; - ADD_CONSTR(constr); + ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) + <<"#ila.read-port=" << read_ports.size() << " does not match #rfmap.read-port" + <<", and this is a mismatch for sname:" << ila_state_name; + + const auto & rfmap_rport = vmap.externmem_map.at(rfmap_node_idx); + + // expect bit-vector rather than booleans + auto rtl_ren = singlemap_bv_to_rfexpr(rfmap_rport.ren_map); + auto rtl_raddr = singlemap_bv_to_rfexpr(rfmap_rport.raddr_map); + auto rtl_rdata = singlemap_bv_to_rfexpr(rfmap_rport.rdata_map); + + auto constr = rfmap_imply( rfmap_and( + {rtl_ren, rfmap_eq(ila_raddr, rtl_raddr)}), + rfmap_eq(ila_rdata, rtl_rdata)); - ++ rfmap_node_idx; + ADD_CONSTR(constr); - } // for each read port + ++ rfmap_node_idx; + } // for each read port + } // if there is such port } else { // assert : IEND |-> // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index bee85b2f8..a791b8a5d 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -132,8 +132,9 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { // ) |-> ( // (decode |-> result_input == ??@??) // ) + auto pre_cond = prep.empty() ? rfmap_true(): rfmap_and(prep); add_an_assumption( - rfmap_imply(rfmap_and(prep), res_map), "funcmap"); + rfmap_imply(pre_cond, res_map), "funcmap"); } // for each apply in the list of apply name_to_fnapp_vec.erase(funcName); // remove from it diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index 39bbb2839..d8abc9b9c 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -119,7 +119,7 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { } std::string extra_smt_properties; - if(!_problems.smt_assertions.empty()) { + if(!_problems.smt_assertions.empty() || !_problems.smt_assumptions.empty()) { extra_smt_properties += " --property-file property.smt2 "; } diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index e107cb600..18e7c58eb 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -397,15 +397,6 @@ TEST(TestVlgTargetGen, MemoryInternal) { // test the expansion of memory TEST(TestVlgTargetGen, MemoryInternalExternal) { auto ila_model = MemorySwap::BuildRfAsMemModel(); - DebugLog::Enable("VTG.ReplWireEq"); - DebugLog::Enable("VTG.ReplAssert"); - DebugLog::Enable("VTG.ReplAssume"); - - DebugLog::Enable("VTG.AddWireEq"); - DebugLog::Enable("VTG.AddAssert"); - DebugLog::Enable("VTG.AddAssume"); - - auto dirName = os_portable_join_dir({ILANG_TEST_SRC_ROOT, "unit-data", "vpipe", "vmem"}); @@ -426,6 +417,16 @@ TEST(TestVlgTargetGen, MemoryInternalExternal) { TEST(TestVlgTargetGen, MemoryInternalExternalEntry6) { auto ila_model = MemorySwap::BuildRfAsMemModelRegEntry6(); + + DebugLog::Enable("VTG.ReplWireEq"); + DebugLog::Enable("VTG.ReplAssert"); + DebugLog::Enable("VTG.ReplAssume"); + + DebugLog::Enable("VTG.AddWireEq"); + DebugLog::Enable("VTG.AddAssert"); + DebugLog::Enable("VTG.AddAssume"); + + VlgVerifTgtGenBase::vtg_config_t vtg_cfg; vtg_cfg.PonoAddKeep = false; @@ -464,47 +465,6 @@ TEST(TestVlgTargetGen, MemoryRead) { vg.GenerateTargets(); } -TEST(TestVlgTargetGen, MemoryAbsRead) { - VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; - - auto ila_model = MemorySwap::BuildModel(); - - auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; - VerilogVerificationTargetGenerator vg( - {}, // no include - {dirName + "swap.v"}, // vlog files - "swap", // top_module_name - dirName + "vmap.json", // variable mapping - dirName + "cond.json", // cond path - dirName + "rdabs/", // output path - ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} - -TEST(TestVlgTargetGen, MemoryReadAbsRead) { - VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; - - auto ila_model = MemorySwap::BuildRdModel(); - - auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; - VerilogVerificationTargetGenerator vg( - {}, // no include - {dirName + "read.v"}, // vlog files - "rdtop", // top_module_name - dirName + "vmap-rd.json", // variable mapping - dirName + "cond-rd.json", // cond path - dirName + "rdabs/", // output path - ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} TEST(TestVlgTargetGen, MemoryReadAbsReadJasperGold) { VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; @@ -588,69 +548,6 @@ TEST(TestVlgTargetGen, ResetAnnotation) { vg.GenerateTargets(); } - { - auto ila_model = MemorySwap::BuildResetterTest(); - auto dirName = os_portable_join_dir( - {ILANG_TEST_SRC_ROOT, "unit-data", "vpipe", "reset"}); - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_join_dir( - {dirName, "verilog", "resetter.v"})}, // vlog files - "resetter", // top_module_name - os_portable_join_dir( - {dirName, "rfmap", "vmap-e2.json"}), // variable mapping - os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path - os_portable_append_dir(dirName, "out"), // output path - ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); - } - { - auto ila_model = MemorySwap::BuildResetterTest(); - auto dirName = os_portable_join_dir( - {ILANG_TEST_SRC_ROOT, "unit-data", "vpipe", "reset"}); - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_join_dir( - {dirName, "verilog", "resetter.v"})}, // vlog files - "resetter", // top_module_name - os_portable_join_dir( - {dirName, "rfmap", "vmap-e3.json"}), // variable mapping - os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path - os_portable_append_dir(dirName, "out"), // output path - ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); - } - { - auto ila_model = MemorySwap::BuildResetterTest(); - auto dirName = os_portable_join_dir( - {ILANG_TEST_SRC_ROOT, "unit-data", "vpipe", "reset"}); - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_join_dir( - {dirName, "verilog", "resetter.v"})}, // vlog files - "resetter", // top_module_name - os_portable_join_dir( - {dirName, "rfmap", "vmap-e4.json"}), // variable mapping - os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path - os_portable_append_dir(dirName, "out"), // output path - ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); - } { auto ila_model = MemorySwap::BuildResetterTest(); auto dirName = os_portable_join_dir( @@ -664,7 +561,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir( {dirName, "rfmap", "vmap.json"}), // variable mapping os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path - os_portable_append_dir(dirName, "out"), // output path + os_portable_append_dir(dirName, "out2"), // output path ila_model.get(), VerilogVerificationTargetGenerator::backend_selector::PONO); diff --git a/test/unit-data/vpipe/reset/out-z3/.gitignore b/test/unit-data/vpipe/reset/out-z3/.gitignore deleted file mode 100644 index 72e8ffc0d..000000000 --- a/test/unit-data/vpipe/reset/out-z3/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/test/unit-data/vpipe/reset/out-z3/inst/__design_smt.smt2 b/test/unit-data/vpipe/reset/out-z3/inst/__design_smt.smt2 deleted file mode 100644 index 222f73170..000000000 --- a/test/unit-data/vpipe/reset/out-z3/inst/__design_smt.smt2 +++ /dev/null @@ -1,175 +0,0 @@ -; SMT-LIBv2 description generated by Yosys 0.8+598 (git sha1 becd98cc, gcc 7.4.0-1ubuntu1~18.04.1 -fPIC -Os) -; yosys-smt2-stdt -; yosys-smt2-module wrapper -(declare-datatype |wrapper_s| ((|wrapper_mk| - (|wrapper_is| Bool) - (|wrapper#0| (_ BitVec 1)) ; \__2ndENDED__ - (|wrapper#1| (_ BitVec 4)) ; \__CYCLE_CNT__ - (|wrapper#3| (_ BitVec 1)) ; \__STARTED__ - (|wrapper#5| (_ BitVec 1)) ; \__ENDED__ - (|wrapper#8| (_ BitVec 1)) ; \m0.v - (|wrapper#9| (_ BitVec 1)) ; \__START__ - (|wrapper#11| (_ BitVec 1)) ; \m1.v1 - (|wrapper#12| (_ BitVec 1)) ; \m1.v2 - (|wrapper#18| (_ BitVec 1)) ; \dummy_reset - (|wrapper#22| Bool) ; \clk - (|wrapper#23| Bool) ; \m0.v_randinit - (|wrapper#24| Bool) ; \rst -))) -; yosys-smt2-output __2ndENDED__ 1 -; yosys-smt2-register __2ndENDED__ 1 -(define-fun |wrapper_n __2ndENDED__| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#0| state)) #b1)) -; yosys-smt2-output __CYCLE_CNT__ 4 -; yosys-smt2-register __CYCLE_CNT__ 4 -(define-fun |wrapper_n __CYCLE_CNT__| ((state |wrapper_s|)) (_ BitVec 4) (|wrapper#1| state)) -; yosys-smt2-wire __EDCOND__ 1 -(define-fun |wrapper#2| ((state |wrapper_s|)) Bool (= (|wrapper#1| state) #b0001)) ; $eq$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:112$27_Y -(define-fun |wrapper#4| ((state |wrapper_s|)) Bool (and (or (|wrapper#2| state) false) (or (= ((_ extract 0 0) (|wrapper#3| state)) #b1) false))) ; \__EDCOND__ -(define-fun |wrapper_n __EDCOND__| ((state |wrapper_s|)) Bool (|wrapper#4| state)) -; yosys-smt2-output __ENDED__ 1 -; yosys-smt2-register __ENDED__ 1 -(define-fun |wrapper_n __ENDED__| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#5| state)) #b1)) -; yosys-smt2-wire __IEND__ 1 -(define-fun |wrapper#6| ((state |wrapper_s|)) (_ BitVec 1) (bvnot (|wrapper#5| state))) ; $not$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:113$34_Y -(define-fun |wrapper#7| ((state |wrapper_s|)) Bool (and (or (|wrapper#4| state) false) (or (= ((_ extract 0 0) (|wrapper#6| state)) #b1) false))) ; \__IEND__ -(define-fun |wrapper_n __IEND__| ((state |wrapper_s|)) Bool (|wrapper#7| state)) -; yosys-smt2-output __ILA_SO_v 1 -; yosys-smt2-wire __ILA_SO_v 1 -(define-fun |wrapper_n __ILA_SO_v| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#8| state)) #b1)) -; yosys-smt2-wire __ILA_proc_decode_of_inst__ 1 -(define-fun |wrapper_n __ILA_proc_decode_of_inst__| ((state |wrapper_s|)) Bool true) -; yosys-smt2-wire __ILA_proc_valid__ 1 -(define-fun |wrapper_n __ILA_proc_valid__| ((state |wrapper_s|)) Bool true) -; yosys-smt2-wire __ISSUE__ 1 -(define-fun |wrapper_n __ISSUE__| ((state |wrapper_s|)) Bool true) -; yosys-smt2-output __RESETED__ 1 -(define-fun |wrapper_n __RESETED__| ((state |wrapper_s|)) Bool true) -; yosys-smt2-output __STARTED__ 1 -; yosys-smt2-register __STARTED__ 1 -(define-fun |wrapper_n __STARTED__| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#3| state)) #b1)) -; yosys-smt2-output __START__ 1 -; yosys-smt2-register __START__ 1 -(define-fun |wrapper_n __START__| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#9| state)) #b1)) -; yosys-smt2-output __all_assert_wire__ 1 -; yosys-smt2-wire __all_assert_wire__ 1 -(define-fun |wrapper#10| ((state |wrapper_s|)) (_ BitVec 1) (bvnot (ite (|wrapper#7| state) #b1 #b0))) ; $not$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:110$23_Y -(define-fun |wrapper#13| ((state |wrapper_s|)) (_ BitVec 1) (bvxor (|wrapper#11| state) (|wrapper#12| state))) ; \m1__DOT__v -(define-fun |wrapper#14| ((state |wrapper_s|)) Bool (= (|wrapper#13| state) (|wrapper#8| state))) ; \__m3__ -(define-fun |wrapper#15| ((state |wrapper_s|)) Bool (or (= ((_ extract 0 0) (|wrapper#10| state)) #b1) false (|wrapper#14| state) false)) ; \__all_assert_wire__ -(define-fun |wrapper_n __all_assert_wire__| ((state |wrapper_s|)) Bool (|wrapper#15| state)) -; yosys-smt2-output __all_assume_wire__ 1 -; yosys-smt2-wire __all_assume_wire__ 1 -(define-fun |wrapper#16| ((state |wrapper_s|)) (_ BitVec 1) (bvnot (|wrapper#12| state))) ; $not$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:111$25_Y -(define-fun |wrapper#17| ((state |wrapper_s|)) Bool (= (|wrapper#11| state) (|wrapper#16| state))) ; \invariant_assume__m5__ -(define-fun |wrapper#19| ((state |wrapper_s|)) (_ BitVec 1) (bvnot (|wrapper#18| state))) ; \noreset__m0__ -(define-fun |wrapper#20| ((state |wrapper_s|)) Bool (and (or (|wrapper#17| state) false) (or (= ((_ extract 0 0) (|wrapper#19| state)) #b1) false))) ; $logic_and$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:136$42_Y -(define-fun |wrapper#21| ((state |wrapper_s|)) Bool (and (or (|wrapper#20| state) false) (or (|wrapper#14| state) false))) ; \__all_assume_wire__ -(define-fun |wrapper_n __all_assume_wire__| ((state |wrapper_s|)) Bool (|wrapper#21| state)) -; yosys-smt2-output __m1__ 1 -; yosys-smt2-wire __m1__ 1 -(define-fun |wrapper_n __m1__| ((state |wrapper_s|)) Bool (|wrapper#14| state)) -; yosys-smt2-output __m3__ 1 -; yosys-smt2-wire __m3__ 1 -(define-fun |wrapper_n __m3__| ((state |wrapper_s|)) Bool (|wrapper#14| state)) -; yosys-smt2-input clk 1 -; yosys-smt2-clock clk posedge -(define-fun |wrapper_n clk| ((state |wrapper_s|)) Bool (|wrapper#22| state)) -; yosys-smt2-input dummy_reset 1 -; yosys-smt2-wire dummy_reset 1 -(define-fun |wrapper_n dummy_reset| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#18| state)) #b1)) -; yosys-smt2-output invariant_assume__m5__ 1 -; yosys-smt2-wire invariant_assume__m5__ 1 -(define-fun |wrapper_n invariant_assume__m5__| ((state |wrapper_s|)) Bool (|wrapper#17| state)) -; yosys-smt2-output issue_decode__m6__ 1 -; yosys-smt2-wire issue_decode__m6__ 1 -(define-fun |wrapper_n issue_decode__m6__| ((state |wrapper_s|)) Bool true) -; yosys-smt2-output issue_valid__m7__ 1 -; yosys-smt2-wire issue_valid__m7__ 1 -(define-fun |wrapper_n issue_valid__m7__| ((state |wrapper_s|)) Bool true) -; yosys-smt2-register m0.v 1 -(define-fun |wrapper_n m0.v| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#8| state)) #b1)) -; yosys-smt2-input m0.v_randinit 1 -; yosys-smt2-wire m0.v_randinit 1 -(define-fun |wrapper_n m0.v_randinit| ((state |wrapper_s|)) Bool (|wrapper#23| state)) -; yosys-smt2-wire m1.v 1 -(define-fun |wrapper_n m1.v| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#13| state)) #b1)) -; yosys-smt2-register m1.v1 1 -; yosys-smt2-wire m1.v1 1 -(define-fun |wrapper_n m1.v1| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#11| state)) #b1)) -; yosys-smt2-register m1.v2 1 -; yosys-smt2-wire m1.v2 1 -(define-fun |wrapper_n m1.v2| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#12| state)) #b1)) -; yosys-smt2-output m1__DOT__v 1 -; yosys-smt2-wire m1__DOT__v 1 -(define-fun |wrapper_n m1__DOT__v| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#13| state)) #b1)) -; yosys-smt2-output m1__DOT__v1 1 -; yosys-smt2-wire m1__DOT__v1 1 -(define-fun |wrapper_n m1__DOT__v1| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#11| state)) #b1)) -; yosys-smt2-output m1__DOT__v2 1 -; yosys-smt2-wire m1__DOT__v2 1 -(define-fun |wrapper_n m1__DOT__v2| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#12| state)) #b1)) -; yosys-smt2-output noreset__m0__ 1 -; yosys-smt2-wire noreset__m0__ 1 -(define-fun |wrapper_n noreset__m0__| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#19| state)) #b1)) -; yosys-smt2-input rst 1 -(define-fun |wrapper_n rst| ((state |wrapper_s|)) Bool (|wrapper#24| state)) -; yosys-smt2-output v 1 -; yosys-smt2-wire v 1 -(define-fun |wrapper_n v| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#13| state)) #b1)) -; yosys-smt2-output variable_map_assert__p4__ 1 -; yosys-smt2-wire variable_map_assert__p4__ 1 -(define-fun |wrapper_n variable_map_assert__p4__| ((state |wrapper_s|)) Bool (|wrapper#15| state)) -; yosys-smt2-output variable_map_assume___m2__ 1 -; yosys-smt2-wire variable_map_assume___m2__ 1 -(define-fun |wrapper_n variable_map_assume___m2__| ((state |wrapper_s|)) Bool (|wrapper#14| state)) -; yosys-smt2-assert 0 /home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:137 -(define-fun |wrapper_a 0| ((state |wrapper_s|)) Bool (or (|wrapper#15| state) (not true))) ; $assert$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:137$44 -; yosys-smt2-assume 0 /home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:139 -(define-fun |wrapper_u 0| ((state |wrapper_s|)) Bool (or (|wrapper#21| state) (not true))) ; $assume$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:139$45 -(define-fun |wrapper#25| ((state |wrapper_s|)) Bool (not (or (= ((_ extract 0 0) (|wrapper#11| state)) #b1) false))) ; $techmap\m1.$logic_not$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:192$53_Y -(define-fun |wrapper#26| ((state |wrapper_s|)) (_ BitVec 1) (ite (= ((_ extract 0 0) (|wrapper#18| state)) #b1) (ite (|wrapper#25| state) #b1 #b0) (|wrapper#12| state))) ; $techmap\m1.$0\v1[0:0] -(define-fun |wrapper#27| ((state |wrapper_s|)) Bool (or (= ((_ extract 0 0) (|wrapper#9| state)) #b1) false (= ((_ extract 0 0) (|wrapper#3| state)) #b1) false)) ; $logic_or$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:85$5_Y -(define-fun |wrapper#28| ((state |wrapper_s|)) (_ BitVec 1) (ite (|wrapper#27| state) #b0 #b1)) ; $procmux$97_Y -(define-fun |wrapper#29| ((state |wrapper_s|)) (_ BitVec 1) (ite (|wrapper#24| state) #b0 (|wrapper#28| state))) ; $0\__START__[0:0] -(define-fun |wrapper#30| ((state |wrapper_s|)) (_ BitVec 1) (ite (= ((_ extract 0 0) (|wrapper#9| state)) #b1) #b1 (|wrapper#8| state))) ; $techmap\m0.$procmux$72_Y -(define-fun |wrapper#31| ((state |wrapper_s|)) (_ BitVec 1) (ite (|wrapper#24| state) (ite (|wrapper#23| state) #b1 #b0) (|wrapper#30| state))) ; $techmap\m0.$0\v[0:0] -(define-fun |wrapper#32| ((state |wrapper_s|)) (_ BitVec 1) (ite (|wrapper#7| state) #b1 (|wrapper#5| state))) ; $procmux$84_Y -(define-fun |wrapper#33| ((state |wrapper_s|)) (_ BitVec 1) (ite (|wrapper#24| state) #b0 (|wrapper#32| state))) ; $0\__ENDED__[0:0] -(define-fun |wrapper#34| ((state |wrapper_s|)) (_ BitVec 1) (ite (= ((_ extract 0 0) (|wrapper#9| state)) #b1) #b1 (|wrapper#3| state))) ; $procmux$89_Y -(define-fun |wrapper#35| ((state |wrapper_s|)) (_ BitVec 1) (ite (|wrapper#24| state) #b0 (|wrapper#34| state))) ; $0\__STARTED__[0:0] -(define-fun |wrapper#36| ((state |wrapper_s|)) (_ BitVec 4) (bvadd (|wrapper#1| state) #b0001)) ; $add$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:85$8_Y -(define-fun |wrapper#37| ((state |wrapper_s|)) Bool (bvult (|wrapper#1| state) #b0110)) ; $lt$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:85$6_Y -(define-fun |wrapper#38| ((state |wrapper_s|)) Bool (and (or (|wrapper#27| state) false) (or (|wrapper#37| state) false))) ; $logic_and$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:85$7_Y -(define-fun |wrapper#39| ((state |wrapper_s|)) (_ BitVec 4) (ite (|wrapper#38| state) (|wrapper#36| state) (|wrapper#1| state))) ; $procmux$102_Y -(define-fun |wrapper#40| ((state |wrapper_s|)) (_ BitVec 4) (ite (|wrapper#24| state) #b0000 (|wrapper#39| state))) ; $0\__CYCLE_CNT__[3:0] -(define-fun |wrapper#41| ((state |wrapper_s|)) Bool (and (or (= ((_ extract 0 0) (|wrapper#5| state)) #b1) false) (or (|wrapper#4| state) false))) ; $logic_and$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:102$14_Y -(define-fun |wrapper#42| ((state |wrapper_s|)) (_ BitVec 1) (bvnot (|wrapper#0| state))) ; $not$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:102$15_Y -(define-fun |wrapper#43| ((state |wrapper_s|)) Bool (and (or (|wrapper#41| state) false) (or (= ((_ extract 0 0) (|wrapper#42| state)) #b1) false))) ; $logic_and$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/inst/wrapper.v:102$16_Y -(define-fun |wrapper#44| ((state |wrapper_s|)) (_ BitVec 1) (ite (|wrapper#43| state) #b1 (|wrapper#0| state))) ; $procmux$79_Y -(define-fun |wrapper#45| ((state |wrapper_s|)) (_ BitVec 1) (ite (|wrapper#24| state) #b0 (|wrapper#44| state))) ; $0\__2ndENDED__[0:0] -(define-fun |wrapper_a| ((state |wrapper_s|)) Bool - (|wrapper_a 0| state) -) -(define-fun |wrapper_u| ((state |wrapper_s|)) Bool - (|wrapper_u 0| state) -) -(define-fun |wrapper_i| ((state |wrapper_s|)) Bool (and - (= (= ((_ extract 0 0) (|wrapper#0| state)) #b1) false) ; __2ndENDED__ - (= (|wrapper#1| state) #b0000) ; __CYCLE_CNT__ - (= (= ((_ extract 0 0) (|wrapper#5| state)) #b1) false) ; __ENDED__ - (= (= ((_ extract 0 0) (|wrapper#3| state)) #b1) false) ; __STARTED__ - (= (= ((_ extract 0 0) (|wrapper#9| state)) #b1) false) ; __START__ -)) -(define-fun |wrapper_h| ((state |wrapper_s|)) Bool true) -(define-fun |wrapper_t| ((state |wrapper_s|) (next_state |wrapper_s|)) Bool (and - (= (|wrapper#11| state) (|wrapper#12| next_state)) ; $techmap/m1.$procdff$108 \m1.v2 - (= (|wrapper#26| state) (|wrapper#11| next_state)) ; $techmap/m1.$procdff$107 \m1.v1 - (= (|wrapper#29| state) (|wrapper#9| next_state)) ; $procdff$115 \__START__ - (= (|wrapper#31| state) (|wrapper#8| next_state)) ; $techmap/m0.$procdff$109 \m0.v - (= (|wrapper#33| state) (|wrapper#5| next_state)) ; $procdff$113 \__ENDED__ - (= (|wrapper#35| state) (|wrapper#3| next_state)) ; $procdff$114 \__STARTED__ - (= (|wrapper#40| state) (|wrapper#1| next_state)) ; $procdff$116 \__CYCLE_CNT__ - (= (|wrapper#45| state) (|wrapper#0| next_state)) ; $procdff$112 \__2ndENDED__ -)) ; end of module wrapper -; yosys-smt2-topmod wrapper -; end of yosys output diff --git a/test/unit-data/vpipe/reset/out-z3/invariants/__design_smt.smt2 b/test/unit-data/vpipe/reset/out-z3/invariants/__design_smt.smt2 deleted file mode 100644 index af56047ee..000000000 --- a/test/unit-data/vpipe/reset/out-z3/invariants/__design_smt.smt2 +++ /dev/null @@ -1,68 +0,0 @@ -; SMT-LIBv2 description generated by Yosys 0.8+598 (git sha1 becd98cc, gcc 7.4.0-1ubuntu1~18.04.1 -fPIC -Os) -; yosys-smt2-stdt -; yosys-smt2-module wrapper -(declare-datatype |wrapper_s| ((|wrapper_mk| - (|wrapper_is| Bool) - (|wrapper#0| Bool) ; \__ILA_SO_v - (|wrapper#1| (_ BitVec 1)) ; \m1.v1 - (|wrapper#2| (_ BitVec 1)) ; \m1.v2 - (|wrapper#5| (_ BitVec 1)) ; \rst - (|wrapper#7| Bool) ; \clk -))) -; yosys-smt2-input __ILA_SO_v 1 -; yosys-smt2-output __ILA_SO_v 1 -; yosys-smt2-wire __ILA_SO_v 1 -(define-fun |wrapper_n __ILA_SO_v| ((state |wrapper_s|)) Bool (|wrapper#0| state)) -; yosys-smt2-output __all_assert_wire__ 1 -; yosys-smt2-wire __all_assert_wire__ 1 -(define-fun |wrapper#3| ((state |wrapper_s|)) (_ BitVec 1) (bvnot (|wrapper#2| state))) ; $not$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/invariants/wrapper.v:37$1_Y -(define-fun |wrapper#4| ((state |wrapper_s|)) Bool (= (|wrapper#1| state) (|wrapper#3| state))) ; \__all_assert_wire__ -(define-fun |wrapper_n __all_assert_wire__| ((state |wrapper_s|)) Bool (|wrapper#4| state)) -; yosys-smt2-output __all_assume_wire__ 1 -; yosys-smt2-wire __all_assume_wire__ 1 -(define-fun |wrapper#6| ((state |wrapper_s|)) (_ BitVec 1) (bvnot (|wrapper#5| state))) ; \__all_assume_wire__ -(define-fun |wrapper_n __all_assume_wire__| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#6| state)) #b1)) -; yosys-smt2-input clk 1 -; yosys-smt2-clock clk posedge -(define-fun |wrapper_n clk| ((state |wrapper_s|)) Bool (|wrapper#7| state)) -; yosys-smt2-output invariant_assert__p0__ 1 -; yosys-smt2-wire invariant_assert__p0__ 1 -(define-fun |wrapper_n invariant_assert__p0__| ((state |wrapper_s|)) Bool (|wrapper#4| state)) -; yosys-smt2-register m1.v1 1 -; yosys-smt2-wire m1.v1 1 -(define-fun |wrapper_n m1.v1| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#1| state)) #b1)) -; yosys-smt2-register m1.v2 1 -; yosys-smt2-wire m1.v2 1 -(define-fun |wrapper_n m1.v2| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#2| state)) #b1)) -; yosys-smt2-output m1__DOT__v1 1 -; yosys-smt2-wire m1__DOT__v1 1 -(define-fun |wrapper_n m1__DOT__v1| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#1| state)) #b1)) -; yosys-smt2-output m1__DOT__v2 1 -; yosys-smt2-wire m1__DOT__v2 1 -(define-fun |wrapper_n m1__DOT__v2| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#2| state)) #b1)) -; yosys-smt2-input rst 1 -(define-fun |wrapper_n rst| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#5| state)) #b1)) -; yosys-smt2-output v 1 -; yosys-smt2-wire v 1 -(define-fun |wrapper#8| ((state |wrapper_s|)) (_ BitVec 1) (bvxor (|wrapper#1| state) (|wrapper#2| state))) ; \m1.v -(define-fun |wrapper_n v| ((state |wrapper_s|)) Bool (= ((_ extract 0 0) (|wrapper#8| state)) #b1)) -; yosys-smt2-assert 0 /home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/invariants/wrapper.v:48 -(define-fun |wrapper_a 0| ((state |wrapper_s|)) Bool (or (|wrapper#4| state) (not true))) ; $assert$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/invariants/wrapper.v:48$4 -; yosys-smt2-assume 0 /home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/invariants/wrapper.v:50 -(define-fun |wrapper_u 0| ((state |wrapper_s|)) Bool (or (= ((_ extract 0 0) (|wrapper#6| state)) #b1) (not true))) ; $assume$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/invariants/wrapper.v:50$5 -(define-fun |wrapper#9| ((state |wrapper_s|)) Bool (not (or (= ((_ extract 0 0) (|wrapper#1| state)) #b1) false))) ; $techmap\m1.$logic_not$/home/hongce/ila/ila-stable/test/unit-data/vpipe/reset/out-z3/invariants/wrapper.v:61$7_Y -(define-fun |wrapper#10| ((state |wrapper_s|)) (_ BitVec 1) (ite (= ((_ extract 0 0) (|wrapper#5| state)) #b1) (ite (|wrapper#9| state) #b1 #b0) (|wrapper#2| state))) ; $techmap\m1.$0\v1[0:0] -(define-fun |wrapper_a| ((state |wrapper_s|)) Bool - (|wrapper_a 0| state) -) -(define-fun |wrapper_u| ((state |wrapper_s|)) Bool - (|wrapper_u 0| state) -) -(define-fun |wrapper_i| ((state |wrapper_s|)) Bool true) -(define-fun |wrapper_h| ((state |wrapper_s|)) Bool true) -(define-fun |wrapper_t| ((state |wrapper_s|) (next_state |wrapper_s|)) Bool (and - (= (|wrapper#1| state) (|wrapper#2| next_state)) ; $techmap/m1.$procdff$15 \m1.v2 - (= (|wrapper#10| state) (|wrapper#1| next_state)) ; $techmap/m1.$procdff$14 \m1.v1 -)) ; end of module wrapper -; yosys-smt2-topmod wrapper -; end of yosys output diff --git a/test/unit-data/vpipe/reset/out-abc/.gitignore b/test/unit-data/vpipe/reset/out2/.gitignore similarity index 100% rename from test/unit-data/vpipe/reset/out-abc/.gitignore rename to test/unit-data/vpipe/reset/out2/.gitignore diff --git a/test/unit-data/vpipe/reset/rfmap/cond.json b/test/unit-data/vpipe/reset/rfmap/cond.json index 0c83f684e..ce6495528 100644 --- a/test/unit-data/vpipe/reset/rfmap/cond.json +++ b/test/unit-data/vpipe/reset/rfmap/cond.json @@ -1,5 +1,5 @@ { - "global invariants": ["m1.v1 == ~m1.v2"], + "global invariants": ["RTL.v1 == ~RTL.v2"], "instructions": [ { diff --git a/test/unit-data/vpipe/reset/rfmap/vmap-e1.json b/test/unit-data/vpipe/reset/rfmap/vmap-e1.json index 99ebcff9d..21818ff65 100644 --- a/test/unit-data/vpipe/reset/rfmap/vmap-e1.json +++ b/test/unit-data/vpipe/reset/rfmap/vmap-e1.json @@ -1,24 +1,15 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, "state mapping": { - "v":"v"}, + "v":"RTL.v"}, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "v":"**SO**" + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" }, // "mapping control" : ["__MEM_mema_0_ren == ((m1.state == 1)?1'b1:1'b0)", "__MEM_memb_0_ren == ((m1.state == 1)?1'b1:1'b0)"], - "annotation": { - "reset" : { - "cycle": 0, - "no-reset-after": true, - "reset-state":[], - "reset-sequence":[] - } - }, + "assumptions":["1==1"] } diff --git a/test/unit-data/vpipe/reset/rfmap/vmap-e2.json b/test/unit-data/vpipe/reset/rfmap/vmap-e2.json deleted file mode 100644 index 72ef32c1a..000000000 --- a/test/unit-data/vpipe/reset/rfmap/vmap-e2.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "models": { "ILA":"m0" , "VERILOG": "m1" }, - - "state mapping": { - "v":"v"}, - - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "v":"**SO**" - }, - - // "mapping control" : ["__MEM_mema_0_ren == ((m1.state == 1)?1'b1:1'b0)", "__MEM_memb_0_ren == ((m1.state == 1)?1'b1:1'b0)"], - - "annotation": "none", - "assumptions":["1==1"] -} diff --git a/test/unit-data/vpipe/reset/rfmap/vmap-e3.json b/test/unit-data/vpipe/reset/rfmap/vmap-e3.json deleted file mode 100644 index eeb62b144..000000000 --- a/test/unit-data/vpipe/reset/rfmap/vmap-e3.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "models": { "ILA":"m0" , "VERILOG": "m1" }, - - "state mapping": { - "v":"v"}, - - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "v":"**SO**" - }, - - // "mapping control" : ["__MEM_mema_0_ren == ((m1.state == 1)?1'b1:1'b0)", "__MEM_memb_0_ren == ((m1.state == 1)?1'b1:1'b0)"], - - "annotation": { - "width":{"m1.v":1}, - "memory":{"abc":"unknown"}, - "memory-ports":{"abc.r1":123,"bcd.r2":"abc"} - }, - - "assumptions":["1==1"] -} diff --git a/test/unit-data/vpipe/reset/rfmap/vmap-e4.json b/test/unit-data/vpipe/reset/rfmap/vmap-e4.json deleted file mode 100644 index a4dbd547f..000000000 --- a/test/unit-data/vpipe/reset/rfmap/vmap-e4.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "models": { "ILA":"m0" , "VERILOG": "m1" }, - - "state mapping": { - "v":"v"}, - - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "v":"" - }, - - // "mapping control" : ["__MEM_mema_0_ren == ((m1.state == 1)?1'b1:1'b0)", "__MEM_memb_0_ren == ((m1.state == 1)?1'b1:1'b0)"], - - "assumptions":["1==1"] -} diff --git a/test/unit-data/vpipe/reset/rfmap/vmap.json b/test/unit-data/vpipe/reset/rfmap/vmap.json index 73a81f4dc..c4f7a02e7 100644 --- a/test/unit-data/vpipe/reset/rfmap/vmap.json +++ b/test/unit-data/vpipe/reset/rfmap/vmap.json @@ -1,24 +1,16 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, - "state mapping": { - "v":"v"}, + "v":"RTL.v"}, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "v":"**SO**" + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" }, - // "mapping control" : ["__MEM_mema_0_ren == ((m1.state == 1)?1'b1:1'b0)", "__MEM_memb_0_ren == ((m1.state == 1)?1'b1:1'b0)"], - "annotation": { - "reset" : { - "cycle": 5, - "no-reset-after": true, - "reset-state":[], - "reset-sequence":[] - } + // "mapping control" : ["__MEM_mema_0_ren == ((m1.state == 1)?1'b1:1'b0)", "__MEM_memb_0_ren == ((m1.state == 1)?1'b1:1'b0)"], + "reset" : { + "cycles" : 5 }, "assumptions":["1==1"] } diff --git a/test/unit-data/vpipe/undetf/vmap-func.json b/test/unit-data/vpipe/undetf/vmap-func.json index 25bcf3ee8..9141bdcfc 100644 --- a/test/unit-data/vpipe/undetf/vmap-func.json +++ b/test/unit-data/vpipe/undetf/vmap-func.json @@ -1,25 +1,23 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, - "instruction mapping": [], "state mapping": { - "r0":"r0", - "r1":"r1", - "r2":"r2", - "r3":"r3", - "r4":"r4"}, + "r0":"RTL.r0", + "r1":"RTL.r1", + "r2":"RTL.r2", + "r3":"RTL.r3", + "r4":"RTL.r4"}, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "d":"**KEEP**" - }, + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + }, // d keep - "mapping control" : [], "functions":{ "nondet8_1":[ - ["__START__","res1","__START__","r0"], - ["__START__","res3","__START__","r0"]], + {"result": "RTL.res1@0", "arg":["RTL.r0@0"]}, + {"result": "RTL.res3@0", "arg":["RTL.r0@0"]} + ], "nondet8_2":[ - ["__START__","res4","__START__","r1","__START__","r2"], - ["__START__","res5","__START__","r3","__START__","r4"] - ] } + {"result": "RTL.res4@0", "arg":["RTL.r1@0", "RTL.r2@0"]}, + {"result": "RTL.res5@0", "arg":["RTL.r3@0", "RTL.r4@0"]} + ] + } } diff --git a/test/unit-data/vpipe/undetf/vmap-val.json b/test/unit-data/vpipe/undetf/vmap-val.json index 32e490d57..eaa574db3 100644 --- a/test/unit-data/vpipe/undetf/vmap-val.json +++ b/test/unit-data/vpipe/undetf/vmap-val.json @@ -1,20 +1,18 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, - "instruction mapping": [], "state mapping": { - "r0":"r0", - "r1":"r1", - "r2":"r2", - "r3":"r3", - "r4":"r4"}, + "r0":"RTL.r0", + "r1":"RTL.r1", + "r2":"RTL.r2", + "r3":"RTL.r3", + "r4":"RTL.r4"}, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "d":"**KEEP**" - }, + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + }, // d keep - "mapping control" : [], - "functions":{ "nondet8_1":[["__START__","res1"],["__START__","res3"]], - "nondet8_2":[["__START__","res4"],["__START__","res5"]] } + "functions":{ "nondet8_1": [{"result" : "RTL.res1@0", "arg" : []}, + {"result" : "RTL.res3@0", "arg" : []}], + "nondet8_2": [{"result" : "RTL.res4@0", "arg" : []}, + {"result" : "RTL.res5@0", "arg" : []}] } } diff --git a/test/unit-data/vpipe/vmem/cond-rd.json b/test/unit-data/vpipe/vmem/cond-rd.json index 4fecbea36..f79e88fcb 100644 --- a/test/unit-data/vpipe/vmem/cond-rd.json +++ b/test/unit-data/vpipe/vmem/cond-rd.json @@ -4,7 +4,7 @@ "instructions": [ { "instruction": "Rd", - "start condition":["m1.state == 0" , "$valid", "$decode" ], + "start condition":["RTL.state == 0" , "$valid", "$decode" ], "ready bound": 2 } ] diff --git a/test/unit-data/vpipe/vmem/vmap-rd.json b/test/unit-data/vpipe/vmem/vmap-rd.json index b819b6a48..7b30ab740 100644 --- a/test/unit-data/vpipe/vmem/vmap-rd.json +++ b/test/unit-data/vpipe/vmem/vmap-rd.json @@ -1,25 +1,20 @@ { - "models": { "ILA":"m0" , "VERILOG": "m1" }, - "instruction mapping": [], "state mapping": { - "mema":"**MEM**mema", - "membuf":"rdataa_buf"}, + "mema":{ + "ren" : "1'b1", // will always read + "raddr" : "RTL.mem_a_raddr@1", + "rdata" : "RTL.mem_a_rdata@1" + }, + "membuf":"RTL.rdataa_buf"}, - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "addra":"addra", - "start":"start", - "mem_a_raddr":"**MEM**mema.raddr", - "mem_a_rdata":"**MEM**mema.rdata" + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" }, - // "mapping control" : ["__MEM_mema_0_ren == ((m1.state == 1)?1'b1:1'b0)"], - - - "annotation": { - "memory-ports" : { - "mema.ren":"m1.state == 1" - } + "input mapping" : { + "addra" : "RTL.addra", + "start" : "RTL.start" } + } diff --git a/test/unit-data/vpipe/vmem/vmap-rfarray.json b/test/unit-data/vpipe/vmem/vmap-rfarray.json index 1f8e23fbf..205c72591 100644 --- a/test/unit-data/vpipe/vmem/vmap-rfarray.json +++ b/test/unit-data/vpipe/vmem/vmap-rfarray.json @@ -1,13 +1,13 @@ { "state mapping": { - "rf":"rf", + "rf":"RTL.rf", "mem":{ - "wen" :"RTL.mem_w_en", - "waddr" :"RTL.mem_w_addr", - "wdata" :"RTL.mem_w_data", - "ren" :"RTL.mem_r_en", - "raddr" :"RTL.mem_r_addr", - "rdata" :"RTL.mem_r_data" + "wen" :"RTL.mem_w_en@0", + "waddr" :"RTL.mem_w_addr@0", + "wdata" :"RTL.mem_w_data@0", + "ren" :"RTL.mem_r_en@0", + "raddr" :"RTL.mem_r_addr@0", + "rdata" :"RTL.mem_r_data@0" }}, "RTL interface connection" : { diff --git a/test/unit-data/vpipe/vmem/vmap-rfarray6.json b/test/unit-data/vpipe/vmem/vmap-rfarray6.json index bcef7e97d..1a7f1a285 100644 --- a/test/unit-data/vpipe/vmem/vmap-rfarray6.json +++ b/test/unit-data/vpipe/vmem/vmap-rfarray6.json @@ -1,13 +1,13 @@ { "state mapping": { - "rf":"rf", + "rf":"RTL.rf", "mem":{ - "wen" :"RTL.mem_w_en", - "waddr" :"RTL.mem_w_addr", - "wdata" :"RTL.mem_w_data", - "ren" :"RTL.mem_r_en", - "raddr" :"RTL.mem_r_addr", - "rdata" :"RTL.mem_r_data" + "wen" :"RTL.mem_w_en@0", + "waddr" :"RTL.mem_w_addr@0", + "wdata" :"RTL.mem_w_data@0", + "ren" :"RTL.mem_r_en@0", + "raddr" :"RTL.mem_r_addr@0", + "rdata" :"RTL.mem_r_data@0" }}, "RTL interface connection" : { @@ -21,7 +21,7 @@ "operand2":"RTL.operand2" }, - "mapping control" : [ + "additional mapping" : [ "ILA.operand1 <= 5 && ILA.operand2 <= 5" ] } From b4b65fe16f7f23232618b097196639864ae16397 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 14 Sep 2021 10:56:21 +0800 Subject: [PATCH 38/78] add flex dev --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6d39ff479..78160c391 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,6 +57,7 @@ jobs: - bison - z3 - libz3-dev + - libfl-dev - g++-7 before_install: - echo -n | openssl s_client -connect https://scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- @@ -77,6 +78,7 @@ addons: - bison - z3 - libz3-dev + - libfl-dev - g++-7 notifications: From 0c645288334df011a9826bf7413acb23eb5f6c14 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 14 Sep 2021 11:07:55 +0800 Subject: [PATCH 39/78] update workflow --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9e7372839..a89fb00e4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - name: Install Dependent Packages - run: sudo apt install bison flex z3 libz3-dev + run: sudo apt install bison flex z3 libz3-dev libfl-dev - name: Create Build Environment run: cmake -E make_directory ${{runner.workspace}}/build From 3315da81873776f98199bd310f034322ced00f4a Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 14 Sep 2021 17:06:34 +0800 Subject: [PATCH 40/78] style change --- include/ilang/rfmap-in/rfexpr_shortcut.h | 27 +- include/ilang/rfmap-in/rfexpr_to_smt.h | 37 +- include/ilang/rfmap-in/rfmap_typecheck.h | 182 ++- include/ilang/rfmap-in/rfvar_type.h | 43 +- include/ilang/rfmap-in/verilog_rfmap.h | 91 +- include/ilang/vtarget-out/directive.h | 1 - .../vtarget-out/inv-syn/grain_inv_parse.h | 14 +- include/ilang/vtarget-out/vlg_mod.h | 8 +- include/ilang/vtarget-out/vtarget_gen.h | 60 +- include/ilang/vtarget-out/vtarget_gen_impl.h | 165 +-- .../ilang/vtarget-out/vtarget_gen_jasper.h | 25 +- include/ilang/vtarget-out/vtarget_gen_pono.h | 28 +- src/rfmap-in/rfexpr_shortcut.cc | 68 +- src/rfmap-in/rfexpr_to_smt.cc | 549 ++++---- src/rfmap-in/rfmap_typecheck.cc | 775 ++++++----- src/rfmap-in/verilog_rfmap.cc | 1129 ++++++++++------- src/vtarget-out/directive.cc | 28 +- src/vtarget-out/gen_util.cc | 337 ++--- src/vtarget-out/inv-syn/grain_inv_parse.cc | 28 +- src/vtarget-out/inv-syn/inv_abc_parse.cc | 18 +- src/vtarget-out/inv-syn/inv_obj.cc | 14 +- src/vtarget-out/single_target.cc | 105 +- src/vtarget-out/single_target_as.cc | 346 +++-- src/vtarget-out/single_target_cond.cc | 71 +- src/vtarget-out/single_target_connect.cc | 46 +- .../single_target_inv_syn_support.cc | 28 +- src/vtarget-out/single_target_misc.cc | 328 ++--- src/vtarget-out/vlg_mod.cc | 13 +- src/vtarget-out/vtarget_gen.cc | 7 +- src/vtarget-out/vtarget_gen_impl.cc | 75 +- src/vtarget-out/vtarget_gen_jasper.cc | 27 +- src/vtarget-out/vtarget_gen_pono.cc | 198 ++- test/t_vtarget_gen.cc | 73 +- 33 files changed, 2497 insertions(+), 2447 deletions(-) diff --git a/include/ilang/rfmap-in/rfexpr_shortcut.h b/include/ilang/rfmap-in/rfexpr_shortcut.h index 4f86d49c8..10fab0090 100644 --- a/include/ilang/rfmap-in/rfexpr_shortcut.h +++ b/include/ilang/rfmap-in/rfexpr_shortcut.h @@ -2,7 +2,6 @@ /// construction /// Hongce Zhang (zhanghongce@126.com) - #ifndef ILANG_RFEXPR_SHORTCUT_H__ #define ILANG_RFEXPR_SHORTCUT_H__ @@ -10,21 +9,20 @@ namespace ilang { +rfmap::RfExpr rfmap_reduce_or(const rfmap::RfExpr& in); +rfmap::RfExpr rfmap_imply(const rfmap::RfExpr& l, const rfmap::RfExpr& r); +rfmap::RfExpr rfmap_and(const rfmap::RfExpr& l, const rfmap::RfExpr& r); +rfmap::RfExpr rfmap_or(const rfmap::RfExpr& l, const rfmap::RfExpr& r); +rfmap::RfExpr rfmap_and(const std::vector& v); +rfmap::RfExpr rfmap_or(const std::vector& v); -rfmap::RfExpr rfmap_reduce_or(const rfmap::RfExpr & in); -rfmap::RfExpr rfmap_imply(const rfmap::RfExpr &l, const rfmap::RfExpr &r); -rfmap::RfExpr rfmap_and(const rfmap::RfExpr &l, const rfmap::RfExpr &r); -rfmap::RfExpr rfmap_or(const rfmap::RfExpr &l, const rfmap::RfExpr &r); -rfmap::RfExpr rfmap_and(const std::vector &v); -rfmap::RfExpr rfmap_or(const std::vector &v); - -rfmap::RfExpr rfmap_ite(const rfmap::RfExpr &c, const rfmap::RfExpr &l, - const rfmap::RfExpr &r); +rfmap::RfExpr rfmap_ite(const rfmap::RfExpr& c, const rfmap::RfExpr& l, + const rfmap::RfExpr& r); -rfmap::RfExpr rfmap_eq(const rfmap::RfExpr &l, const rfmap::RfExpr &r); -rfmap::RfExpr rfmap_le(const rfmap::RfExpr &l, const rfmap::RfExpr &r); +rfmap::RfExpr rfmap_eq(const rfmap::RfExpr& l, const rfmap::RfExpr& r); +rfmap::RfExpr rfmap_le(const rfmap::RfExpr& l, const rfmap::RfExpr& r); -rfmap::RfExpr rfmap_not(const rfmap::RfExpr &l); +rfmap::RfExpr rfmap_not(const rfmap::RfExpr& l); rfmap::RfExpr rfmap_true(); rfmap::RfExpr rfmap_false(); @@ -33,9 +31,8 @@ rfmap::RfExpr rfmap_const(unsigned b, unsigned w, unsigned v); /// otherwise will use MakeSpecial /// will not determine its type /// ReplExpr will determine the type -rfmap::RfExpr rfmap_var(const std::string &v); +rfmap::RfExpr rfmap_var(const std::string& v); } // namespace ilang #endif // ILANG_RFEXPR_SHORTCUT_H__ - diff --git a/include/ilang/rfmap-in/rfexpr_to_smt.h b/include/ilang/rfmap-in/rfexpr_to_smt.h index 236b3ee50..0495f552b 100644 --- a/include/ilang/rfmap-in/rfexpr_to_smt.h +++ b/include/ilang/rfmap-in/rfexpr_to_smt.h @@ -1,7 +1,6 @@ /// \file rfexpr_to_smt.cc Refinement map to smt-lib2 /// Hongce Zhang (hongcez@princeton.edu) - #ifndef ILANG_RFEXPR_TO_SMT_H__ #define ILANG_RFEXPR_TO_SMT_H__ @@ -10,48 +9,50 @@ namespace ilang { namespace rfmap { -struct SmtType: public RfMapVarType { +struct SmtType : public RfMapVarType { bool bool_or_bv; SmtType() : RfMapVarType(1), bool_or_bv(true) {} SmtType(unsigned w) : RfMapVarType(w), bool_or_bv(false) {} - SmtType(unsigned a, unsigned d) : RfMapVarType(a,d), bool_or_bv(false) {} - SmtType(const RfMapVarType &r, bool request_bool) : - RfMapVarType(r), bool_or_bv(request_bool) {} + SmtType(unsigned a, unsigned d) : RfMapVarType(a, d), bool_or_bv(false) {} + SmtType(const RfMapVarType& r, bool request_bool) + : RfMapVarType(r), bool_or_bv(request_bool) {} bool is_bool() const { return bool_or_bv && (RfMapVarType::is_bv()); } bool is_bv() const { return (!bool_or_bv) && (RfMapVarType::is_bv()); } - bool operator==(const SmtType & r) const { - if(bool_or_bv != r.bool_or_bv) + bool operator==(const SmtType& r) const { + if (bool_or_bv != r.bool_or_bv) return false; - if(type != r.type) + if (type != r.type) return false; - if(type == TYPE::BV) + if (type == TYPE::BV) return width == r.width; - if(type == TYPE::MEM) + if (type == TYPE::MEM) return data_width == r.data_width && addr_width == r.addr_width; - return false; // unknown type , unknown - } // operator= + return false; // unknown type , unknown + } // operator= std::string type_to_smt2() const; }; // SmtType -struct RfExpr2Smt{ +struct RfExpr2Smt { public: - static std::string to_smt2(const RfExpr &in, SmtType expected_type); + static std::string to_smt2(const RfExpr& in, SmtType expected_type); protected: // helper function - static std::string to_smt2_const(const std::shared_ptr & in, SmtType expected_type); - static std::string to_smt2_var(const std::shared_ptr & in, SmtType expected_type); + static std::string + to_smt2_const(const std::shared_ptr& in, + SmtType expected_type); + static std::string + to_smt2_var(const std::shared_ptr& in, + SmtType expected_type); }; // struct RfExpr2Smt - } // namespace rfmap } // namespace ilang - #endif // ILANG_RFEXPR_TO_SMT_H__ diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index 301badfab..ae119d500 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -2,86 +2,78 @@ /// Type checker /// --- Hongce Zhang (hongcez@princeton.edu) - #ifndef ILANG_RFMAP_TYPECHECK_H__ #define ILANG_RFMAP_TYPECHECK_H__ -#include #include +#include #include - // define annotation - namespace ilang { namespace rfmap { - -class TypeAnnotation : - public ::verilog_expr::AbstractInternalInfo, - public ::ilang::rfmap::RfVarTypeOrig { - +class TypeAnnotation : public ::verilog_expr::AbstractInternalInfo, + public ::ilang::rfmap::RfVarTypeOrig { + public: // allow instantiation virtual void should_not_instantiate() override {} TypeAnnotation() {} - TypeAnnotation(const ::ilang::rfmap::RfVarTypeOrig & r): - ::ilang::rfmap::RfVarTypeOrig(r) {} + TypeAnnotation(const ::ilang::rfmap::RfVarTypeOrig& r) + : ::ilang::rfmap::RfVarTypeOrig(r) {} }; // TypeAnnotation - /// \class structure for recording variable replacement struct VarReplacement { RfExpr origvar; // this is certainly a var - RfExpr newvar; // this is certainly a var + RfExpr newvar; // this is certainly a var - VarReplacement(const RfExpr & o, const RfExpr & n); + VarReplacement(const RfExpr& o, const RfExpr& n); // returns v, there would not be `v[range]` at all std::string get_orig_name() const { - return std::dynamic_pointer_cast - (origvar)->get_name().first; - } - - std::string get_new_name() const{ - return std::dynamic_pointer_cast - (newvar)->get_name().first; } + return std::dynamic_pointer_cast(origvar) + ->get_name() + .first; + } - RfVarTypeOrig get_type_new() const { - return get_type_orig(); + std::string get_new_name() const { + return std::dynamic_pointer_cast(newvar) + ->get_name() + .first; } + RfVarTypeOrig get_type_new() const { return get_type_orig(); } + RfVarTypeOrig get_type_orig() const { auto annotation_ptr = newvar->get_annotation(); - return annotation_ptr?*annotation_ptr:RfVarTypeOrig(); + return annotation_ptr ? *annotation_ptr : RfVarTypeOrig(); } bool is_orig_rtlv() const { return get_type_orig().var_ref_type == RfVarTypeOrig::VARTYPE::RTLV; } - bool is_orig_ila_state() const{ + bool is_orig_ila_state() const { return get_type_orig().var_ref_type == RfVarTypeOrig::VARTYPE::ILAS; } - bool is_orig_ila_input() const{ + bool is_orig_ila_input() const { return get_type_orig().var_ref_type == RfVarTypeOrig::VARTYPE::ILAI; } - bool is_orig_var_array() const { - return get_type_orig().type.is_array(); - } - + bool is_orig_var_array() const { return get_type_orig().type.is_array(); } }; // convert RfExpr constant -> out -bool _compute_const(const RfExpr & in, unsigned & out); +bool _compute_const(const RfExpr& in, unsigned& out); // type infer rules -// +// -// provide function: +// provide function: // try_find_ila_type -> TypeAnnotation // try find_rtl_type -> TypeAnnotation @@ -90,95 +82,92 @@ bool _compute_const(const RfExpr & in, unsigned & out); class TypeAnalysisUtility { public: - typedef std::function var_typecheck_t; + typedef std::function var_typecheck_t; public: /// Annotate the type of a refinement expression /// and this process will be recursive - static void AnnotateType(const RfExpr & inout); - -protected: + static void AnnotateType(const RfExpr& inout); +protected: // internal use only, does not do recursion itself // therefore, an order of invocation is needed - static void infer_type_based_on_op_child(const RfExpr & inout) ; + static void infer_type_based_on_op_child(const RfExpr& inout); }; // struct TypeAnalysisUtility class RfExprAstUtility { public: - static bool HasArrayVar(const RfExpr & in, std::map & array_var); + static bool HasArrayVar(const RfExpr& in, + std::map& array_var); /// determine if a rf expr is a boolean expr - static bool IsLastLevelBooleanOp(const RfExpr & in); + static bool IsLastLevelBooleanOp(const RfExpr& in); /// get the variables from a expression - static void GetVars(const RfExpr & in, - std::unordered_map & vars_out); - static RfVarTypeOrig GetType(const RfExpr & in); - /// will modify where the pointer is pointing to + static void GetVars(const RfExpr& in, + std::unordered_map& vars_out); + static RfVarTypeOrig GetType(const RfExpr& in); + /// will modify where the pointer is pointing to /// because we will be creating new rfexpr - static void TraverseRfExpr(RfExpr & inout, std::function func) ; + static void TraverseRfExpr(RfExpr& inout, + std::function func); /// check to make sure no null ptr - static void RfMapNoNullNode(const RfExpr & in); + static void RfMapNoNullNode(const RfExpr& in); }; struct RfExprVarReplUtility { public: /// used by vtarget_gen to replace rtl/ila vars - RfExpr ReplacingRtlIlaVar(const RfExpr & in); + RfExpr ReplacingRtlIlaVar(const RfExpr& in); /// Register internal variables and also the mapping - void RegisterInternalVariableWithMapping( - const std::string & n, - const VarReplacement & in) { var_replacement.emplace(n, in); } + void RegisterInternalVariableWithMapping(const std::string& n, + const VarReplacement& in) { + var_replacement.emplace(n, in); + } - VarReplacement * CheckReplacement(const std::string & origname) { + VarReplacement* CheckReplacement(const std::string& origname) { auto pos = var_replacement.find(origname); - if(pos != var_replacement.end()) + if (pos != var_replacement.end()) return &(var_replacement.at(origname)); return NULL; } - const std::map & - GetVarReplacement() const { return var_replacement; } + const std::map& GetVarReplacement() const { + return var_replacement; + } protected: /// the replacement used for creating new wires - std::map var_replacement; // including rtl/ilas/ilav - + std::map + var_replacement; // including rtl/ilas/ilav }; -struct TypedVerilogRefinementMap : - public VerilogRefinementMap, - public TypeAnalysisUtility, - public RfExprAstUtility, - public RfExprVarReplUtility { +struct TypedVerilogRefinementMap : public VerilogRefinementMap, + public TypeAnalysisUtility, + public RfExprAstUtility, + public RfExprVarReplUtility { // type definitions using var_typecheck_t = TypeAnalysisUtility::var_typecheck_t; using VarDef = GeneralVerilogMonitor::VarDef; - + // constructor // typechecker is only used in TypeInferTraverseRfExpr - TypedVerilogRefinementMap( - const std::string & varmap_json_file, - const std::string & instcond_json_file, - var_typecheck_t type_checker - ); - - TypedVerilogRefinementMap( - const VerilogRefinementMap & refinement, - var_typecheck_t type_checker - ); - - -// references -// - named defined vars with type -// - named stages with type bit 1 - -// additional delayed - std::map aux_delays; -// additional value_recoder added to value_recorder + TypedVerilogRefinementMap(const std::string& varmap_json_file, + const std::string& instcond_json_file, + var_typecheck_t type_checker); + + TypedVerilogRefinementMap(const VerilogRefinementMap& refinement, + var_typecheck_t type_checker); + + // references + // - named defined vars with type + // - named stages with type bit 1 + + // additional delayed + std::map aux_delays; + // additional value_recoder added to value_recorder // defined vars // 1. first round : only explict ones @@ -191,28 +180,26 @@ struct TypedVerilogRefinementMap : // Var creating stage should deal with separate ones // this should include phase-tracker (m,v,alias) - // ... ? - void TraverseAllRfExpr(std::function func); + // ... ? + void TraverseAllRfExpr(std::function func); - // this function is used in + // this function is used in // (1) value holder/delay : width determination // will use all_var_def_types & typechecker // (2) vlg-monitor replace-var - RfMapVarType TypeInferTravserRfExpr(const RfExpr & in); - -protected: + RfMapVarType TypeInferTravserRfExpr(const RfExpr& in); +protected: // used in TypedVerilogRefinementMap::TypeInferTravserRfExpr // this is only used in the first stage : aux var width determination var_typecheck_t typechecker; - void initialize(); /// this function will not collect implicity vars /// or those with 0/auto width /// for the explicity vars /// it will add them to the `all_var_def_types` - /// for the implicit ones, ComputeDelayValueHolderWidth will + /// for the implicit ones, ComputeDelayValueHolderWidth will /// compute the width and add them to `all_var_def_types` /// this will also create `all_var_def_types` @@ -220,22 +207,21 @@ struct TypedVerilogRefinementMap : /// those replacement are added separately void CollectInternallyDefinedVars(); - /// deal with condition map - void TraverseCondMap(SingleVarMap & inout, std::function func) ; - + /// deal with condition map + void TraverseCondMap(SingleVarMap& inout, + std::function func); private: - // help with naming unsigned counter; std::string new_id(); // helper for AST traversal - void collect_inline_value_recorder_func(RfExpr & inout); - void collect_inline_delay_func(RfExpr & inout); - // this function uses the above two and the + void collect_inline_value_recorder_func(RfExpr& inout); + void collect_inline_delay_func(RfExpr& inout); + // this function uses the above two and the void CollectInlineDelayValueHolder(); - + void ComputeDelayValueHolderWidth(); }; // TypedVerilogRefinementMap @@ -244,5 +230,3 @@ struct TypedVerilogRefinementMap : } // namespace ilang #endif // ILANG_RFMAP_TYPECHECK_H__ - - diff --git a/include/ilang/rfmap-in/rfvar_type.h b/include/ilang/rfmap-in/rfvar_type.h index 0a291c289..cd5d9e66a 100644 --- a/include/ilang/rfmap-in/rfvar_type.h +++ b/include/ilang/rfmap-in/rfvar_type.h @@ -2,7 +2,6 @@ /// Variable Types /// --- Hongce Zhang (hongcez@princeton.edu) - #ifndef ILANG_RFMAP_VARTYPE_H__ #define ILANG_RFMAP_VARTYPE_H__ @@ -13,7 +12,7 @@ namespace rfmap { // define type struct RfMapVarType { - enum class TYPE {BV, MEM, UNKNOWN} type; + enum class TYPE { BV, MEM, UNKNOWN } type; unsigned width; unsigned addr_width; unsigned data_width; @@ -21,44 +20,48 @@ struct RfMapVarType { bool is_unknown() const { return type == TYPE::UNKNOWN; } bool is_bv() const { return type == TYPE::BV; } bool is_array() const { return type == TYPE::MEM; } - + /// for unknown type RfMapVarType() : type(TYPE::UNKNOWN) {} /// for bit-vector type RfMapVarType(unsigned w) : type(TYPE::BV), width(w) {} /// for array type - RfMapVarType(unsigned a, unsigned d) : type(TYPE::MEM), addr_width(a), data_width(d) {} - unsigned unified_width() const { return type == RfMapVarType::TYPE::BV ? width : data_width; } + RfMapVarType(unsigned a, unsigned d) + : type(TYPE::MEM), addr_width(a), data_width(d) {} + unsigned unified_width() const { + return type == RfMapVarType::TYPE::BV ? width : data_width; + } std::string to_string() const { - if(is_unknown()) + if (is_unknown()) return "(unknown)"; - if(is_bv()) - return "(_ BitVec " + std::to_string(width)+")"; - return "(Array (_ BitVec " + std::to_string(addr_width)+") (_ BitVec " + std::to_string(data_width)+"))"; + if (is_bv()) + return "(_ BitVec " + std::to_string(width) + ")"; + return "(Array (_ BitVec " + std::to_string(addr_width) + ") (_ BitVec " + + std::to_string(data_width) + "))"; } }; class RfVarTypeOrig { public: enum class VARTYPE { - NOTVAR, /*also unknown type*/ - ILAS, /*state var*/ - ILAI, /*ila input*/ - RTLV, /*rtl signal*/ + NOTVAR, /*also unknown type*/ + ILAS, /*state var*/ + ILAI, /*ila input*/ + RTLV, /*rtl signal*/ DEFINE_VAR, /*defined vars*/ - INTERNAL /* those already translated: - like __CYCLE_CNT__, __START__*/ }; - + INTERNAL /* those already translated: + like __CYCLE_CNT__, __START__*/ + }; + VARTYPE var_ref_type; RfMapVarType type; // constructur RfVarTypeOrig() : var_ref_type(VARTYPE::NOTVAR) {} - RfVarTypeOrig(const RfVarTypeOrig & r) : - var_ref_type(r.var_ref_type), - type(r.type) {} - + RfVarTypeOrig(const RfVarTypeOrig& r) + : var_ref_type(r.var_ref_type), type(r.type) {} + }; // class RfVarType } // namespace rfmap diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index c16b01bf8..cfb025ae5 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -2,21 +2,19 @@ /// External Refinement Map Interface Class /// --- Hongce Zhang (hongcez@princeton.edu) - #ifndef ILANG_VERILOG_RFMAP_H__ #define ILANG_VERILOG_RFMAP_H__ -#include -#include #include -#include #include +#include +#include +#include #include namespace ilang { namespace rfmap { - // ---------------------- varmap ------------------------------- // /* @@ -30,17 +28,16 @@ typedef verilog_expr::VExprAst::VExprAstPtr RfExpr; typedef verilog_expr::VExprAstVar::VExprAstVarPtr RfVar; /* -"ILA_mem_state_var_2" : { // case 4 : external RTL memory - "wen" : "", - "waddr" : "", +"ILA_mem_state_var_2" : { // case 4 : external RTL +memory "wen" : "", "waddr" : "", "wdata" : "", "ren" : "", "raddr" : "", "rdata" : "" -}, +}, */ -struct SingleVarMap{ +struct SingleVarMap { /// a single refinement string, will be initialized to NULL RfExpr single_map; /// a list of pair of string @@ -60,28 +57,24 @@ struct ExternalMemPortMap { }; // struct ExternalMemPortMap struct IlaVarMapping { - enum class StateVarMapType { - SINGLE, - CONDITIONAL, - EXTERNMEM - } type; + enum class StateVarMapType { SINGLE, CONDITIONAL, EXTERNMEM } type; /// a single refinement string SingleVarMap single_map; /// the standard 6-port map std::vector externmem_map; }; // struct IlaVarMapping -struct RtlInterfaceMapping{ +struct RtlInterfaceMapping { /// "CLOCK" : { "clkA" : "wclk", "clkB" : ["rclk", "clk"] } // name of the clock domain -> list of clock pins std::map> clock_domain_defs; - + // "RESET" : "reset", // you can have a list of signals here std::set reset_pins; // "NRESET" : ["nreset1", "nreset2"], // like this std::set nreset_pins; // "CUSTOMRESET" : {"name" : "input-pin", ...} - std::map> custom_reset_domain_defs; + std::map> custom_reset_domain_defs; }; // struct RtlInterfaceMapping typedef std::vector OneBitSignalSequence; @@ -94,7 +87,7 @@ struct ResetSpecification { // customized reset sequence std::map custom_reset_sequence; // default constructor - ResetSpecification() : reset_cycle(1) { } + ResetSpecification() : reset_cycle(1) {} }; // ResetSpecification struct ClockSpecification { @@ -108,10 +101,10 @@ struct ClockSpecification { // per-clock domain specification, name -> sequence std::map custom_clock_sequence; // specified by the factor - std::map custom_clock_factor; + std::map custom_clock_factor; }; // ClockSpecification -struct UninterpretedFunctionApplication{ +struct UninterpretedFunctionApplication { struct Apply { RfExpr result_map; std::vector arg_map; @@ -121,7 +114,7 @@ struct UninterpretedFunctionApplication{ struct GeneralVerilogMonitor { struct VarDef { - enum class var_type {REG, WIRE} type; + enum class var_type { REG, WIRE } type; unsigned width; }; // VarDef @@ -132,7 +125,7 @@ struct GeneralVerilogMonitor { bool keep_for_invariant; GeneralVerilogMonitor() : keep_for_invariant(false) {} -}; // GeneralVerilogMonitor +}; // GeneralVerilogMonitor struct ValueRecorder { RfExpr condition; @@ -145,14 +138,13 @@ struct ValueRecorder { // this is not directly used struct SignalDelay { - SignalDelay(const RfExpr & _signal, unsigned n_cycle) : - delay_type(delay_typeT::SINGLE), signal(_signal), - num_cycle(n_cycle), width(0), upper_bnd(0) {} + SignalDelay(const RfExpr& _signal, unsigned n_cycle) + : delay_type(delay_typeT::SINGLE), signal(_signal), num_cycle(n_cycle), + width(0), upper_bnd(0) {} - SignalDelay(const RfExpr & _signal, unsigned n_cycle, unsigned u_bnd) : - delay_type(u_bnd == 0 ? delay_typeT::TO_INFINITE : delay_typeT::RANGE), - signal(_signal), - num_cycle(n_cycle), width(0), upper_bnd(u_bnd) {} + SignalDelay(const RfExpr& _signal, unsigned n_cycle, unsigned u_bnd) + : delay_type(u_bnd == 0 ? delay_typeT::TO_INFINITE : delay_typeT::RANGE), + signal(_signal), num_cycle(n_cycle), width(0), upper_bnd(u_bnd) {} enum class delay_typeT { SINGLE, RANGE, TO_INFINITE } delay_type; RfExpr signal; @@ -165,7 +157,7 @@ struct SignalDelay { struct PhaseTracker { struct Assignment { std::string LHS; // a state name - RfExpr RHS; // a rhs expression + RfExpr RHS; // a rhs expression }; typedef std::vector Action; struct Rule { @@ -185,19 +177,19 @@ struct PhaseTracker { // ---------------------- inst-cond ------------------------------- // -struct InstructionCompleteCondition{ +struct InstructionCompleteCondition { std::string instruction_name; - enum class ConditionType {BOUND, SIGNAL} type; + enum class ConditionType { BOUND, SIGNAL } type; unsigned ready_bound; unsigned max_bound; std::vector start_condition; RfExpr ready_signal; - - InstructionCompleteCondition() : ready_bound(0), max_bound(0), ready_signal(nullptr) {} - bool is_readybound() const {return type == ConditionType::BOUND; } - bool is_readysignal() const {return type == ConditionType::SIGNAL; } -}; // + InstructionCompleteCondition() + : ready_bound(0), max_bound(0), ready_signal(nullptr) {} + bool is_readybound() const { return type == ConditionType::BOUND; } + bool is_readysignal() const { return type == ConditionType::SIGNAL; } +}; // struct VerilogRefinementMap { // ---------------------- varmap ------------------------------- // @@ -213,7 +205,7 @@ struct VerilogRefinementMap { ClockSpecification clock_specification; /// Uninterpreted function map : func-name -> applications std::map uf_application; - /// "additional mapping" section + /// "additional mapping" section std::vector additional_mapping; /// "assumptions" section std::vector assumptions; @@ -221,27 +213,28 @@ struct VerilogRefinementMap { std::map phase_tracker; std::map value_recorder; std::map customized_monitor; - + // ---------------------- inst-cond ------------------------------- // std::map inst_complete_cond; std::vector global_invariants; - // ---------------------- supplementary_info ------------------------------- // - std::map width_info; // this is needed in case our width inference failed + // ---------------------- supplementary_info ------------------------------- + // // + std::map + width_info; // this is needed in case our width inference failed // member function : return true if checking passed bool SelfCheckField() const; // from JSON - VerilogRefinementMap(const std::string & varmap_json_file, - const std::string & instcond_json_file); - - static RfExpr ParseRfExprFromString(const std::string & in); - + VerilogRefinementMap(const std::string& varmap_json_file, + const std::string& instcond_json_file); + + static RfExpr ParseRfExprFromString(const std::string& in); + }; // VerilogRefinementMap -} // namespace ilang } // namespace rfmap +} // namespace ilang #endif // ILANG_VERILOG_RFMAP_H__ - diff --git a/include/ilang/vtarget-out/directive.h b/include/ilang/vtarget-out/directive.h index c3e22e62f..418a52203 100644 --- a/include/ilang/vtarget-out/directive.h +++ b/include/ilang/vtarget-out/directive.h @@ -86,7 +86,6 @@ class IntefaceDirectiveRecorder { void RegisterExtraWire(const std::string& io_name, const std::string& outside_name); - protected: /// a sanity check for module instantiation string gen, check if all the vlg /// module i/o has been declared correctly. diff --git a/include/ilang/vtarget-out/inv-syn/grain_inv_parse.h b/include/ilang/vtarget-out/inv-syn/grain_inv_parse.h index c4dddefa3..0493b7f1a 100644 --- a/include/ilang/vtarget-out/inv-syn/grain_inv_parse.h +++ b/include/ilang/vtarget-out/inv-syn/grain_inv_parse.h @@ -56,9 +56,9 @@ class GrainInvariantParser : public SmtlibInvariantParser { // -------------- CALLBACK FNs ------------------- // - /// this is actually declare variables - virtual void declare_function(const std::string& name, SortPtrT sort) override; + virtual void declare_function(const std::string& name, + SortPtrT sort) override; /// this function receives the final assert result // virtual void assert_formula(SmtTermInfoVlgPtr result) override; -- use the @@ -75,10 +75,9 @@ class GrainInvariantParser : public SmtlibInvariantParser { SortPtrT sort) override; /// call back function to apply an uninterpreted function /// fall-through case if it is not an defined op, if failed, return NULL - virtual TermPtrT - mk_function(const std::string& name, SortPtrT sort, - const std::vector& idx, - const std::vector& args) override; + virtual TermPtrT mk_function(const std::string& name, SortPtrT sort, + const std::vector& idx, + const std::vector& args) override; /// call back function to make a number term // virtual SmtTermInfoVlgPtr mk_number(const std::string & rep, int width, int @@ -87,8 +86,7 @@ class GrainInvariantParser : public SmtlibInvariantParser { /// this function receives the final result virtual void define_function(const std::string& func_name, const std::vector& args, - SortPtrT ret_type, - TermPtrT func_body) override; + SortPtrT ret_type, TermPtrT func_body) override; }; // class GrainInvariantParser diff --git a/include/ilang/vtarget-out/vlg_mod.h b/include/ilang/vtarget-out/vlg_mod.h index 319707e39..62484e9dc 100644 --- a/include/ilang/vtarget-out/vlg_mod.h +++ b/include/ilang/vtarget-out/vlg_mod.h @@ -101,11 +101,9 @@ class VerilogModifier { /// record the name to add a keep there void RecordKeepSignalName(const std::string& vname); /// record the name to add related wires - void RecordConnectSigName( - const std::string& vname, // wirename - const std::string& hierarchy, // - const std::string& last_level_name, - unsigned width); + void RecordConnectSigName(const std::string& vname, // wirename + const std::string& hierarchy, // + const std::string& last_level_name, unsigned width); /// record the stmt to be added to a module void RecordAdditionalVlgModuleStmt(const std::string& stmt, diff --git a/include/ilang/vtarget-out/vtarget_gen.h b/include/ilang/vtarget-out/vtarget_gen.h index 15cd67e45..e50d3e506 100644 --- a/include/ilang/vtarget-out/vtarget_gen.h +++ b/include/ilang/vtarget-out/vtarget_gen.h @@ -28,33 +28,34 @@ class VlgVerifTgtGenBase { /// Type of the backend: /// Pono, JasperGold, CHC for chc solver, AIGER for abc // YOSYS is for invariant synthesis use - enum class backend_selector{ + enum class backend_selector { NONE = 0, JASPERGOLD = 2, - YOSYS = 128, // 10000000 - //CHC = YOSYS + 8, // 10001000 - //Z3PDR = CHC + 1, // 10001001 - //ELD_CEGAR = CHC + 2, // 10001010 - //GRAIN_SYGUS = CHC + 4, // 10001100 - //ABCPDR = YOSYS + 16, // 10010000 - PONO = YOSYS + 32, // 10100000 - RELCHC = YOSYS + 64 // 11000000 + YOSYS = 128, // 10000000 + // CHC = YOSYS + 8, // 10001000 + // Z3PDR = CHC + 1, // 10001001 + // ELD_CEGAR = CHC + 2, // 10001010 + // GRAIN_SYGUS = CHC + 4, // 10001100 + // ABCPDR = YOSYS + 16, // 10010000 + PONO = YOSYS + 32, // 10100000 + RELCHC = YOSYS + 64 // 11000000 }; - /// decide if a backend needs Yosys static bool backend_needs_yosys(backend_selector b) { - return (int(b) & int(backend_selector::YOSYS)) == int(backend_selector::YOSYS); + return (int(b) & int(backend_selector::YOSYS)) == + int(backend_selector::YOSYS); } /// Type of invariant synthesis backend /*enum class synthesis_backend_selector { - // Z3 = int(backend_selector::Z3PDR) ^ int(backend_selector::YOSYS), // 01001 - GRAIN = int(backend_selector::GRAIN_SYGUS) ^ int(backend_selector::YOSYS), // 01100 - ABC = int(backend_selector::ABCPDR) ^ int(backend_selector::YOSYS), // 10000 - ELDERICA = int(backend_selector::ELD_CEGAR) ^ int(backend_selector::YOSYS), // 01010 - NOSYN = int(backend_selector::YOSYS) // 1000000 - } ;*/ + // Z3 = int(backend_selector::Z3PDR) ^ + int(backend_selector::YOSYS), // 01001 GRAIN = + int(backend_selector::GRAIN_SYGUS) ^ int(backend_selector::YOSYS), // 01100 + ABC = int(backend_selector::ABCPDR) ^ + int(backend_selector::YOSYS), // 10000 ELDERICA = + int(backend_selector::ELD_CEGAR) ^ int(backend_selector::YOSYS), // 01010 + NOSYN = int(backend_selector::YOSYS) // 1000000 } ;*/ /// Type of the chc target enum class _chc_target_t { CEX, INVCANDIDATE, GENERAL_PROPERTY }; /// Verilog Target Generation Configuration @@ -82,7 +83,6 @@ class VlgVerifTgtGenBase { /// if true : assume ((START || STARTED) && cond && not_triggered) /// |-> reg == value bool EnforcingValueRecorderForOnlyOneCycle; - /// Configure the behavior of INV target, if false, /// will not check synthesized invariants by default (unless call @@ -100,7 +100,6 @@ class VlgVerifTgtGenBase { /// For Pono target generator : whether to force NEW/OLD port declaration enum class PortDeclStyleT { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; - /// Pono VCD output std::string PonoVcdOutputName; /// Binary location of Pono @@ -109,7 +108,7 @@ class VlgVerifTgtGenBase { /// buggy, so you can disable it if you want bool PonoAddKeep; /// For Pono backend: the default engine (ind by default) - /// other options: like bmc, bmc-sp, ind, interp, mbic3, + /// other options: like bmc, bmc-sp, ind, interp, mbic3, /// ic3bits, ic3ia, msat-ic3ia, ic3sa, sygus-pdr std::string PonoEngine; /// For Pono backend: what more options to add @@ -184,7 +183,7 @@ class VlgVerifTgtGenBase { /// CHC, whether to force assumption on the init bool BtorAddCommentsInOutputs; - /* TODO: future work: + /* TODO: future work: bool YosysAssumptionOverlyConstrainedCheck; */ @@ -230,16 +229,14 @@ class VlgVerifTgtGenBase { _vtg_config() : target_select(BOTH), CheckThisInstructionOnly(""), InstructionNoReset(true), InvariantCheckNoReset(false), - OnlyCheckInstUpdatedVars(true), - VerilogGenPassNodeName(false), + OnlyCheckInstUpdatedVars(true), VerilogGenPassNodeName(false), EnforcingValueRecorderForOnlyOneCycle(true), ValidateSynthesizedInvariant(_validate_synthesized_inv::ALL), // ----------- Options for Pono settings -------------- // ForceInstCheckReset(false), PortDeclStyle(PortDeclStyleT::AUTO), - PonoVcdOutputName("cex.vcd"), - PonoAddKeep(false), - PonoEngine("ind"), PonoOtherOptions(""), + PonoVcdOutputName("cex.vcd"), PonoAddKeep(false), PonoEngine("ind"), + PonoOtherOptions(""), PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), MaxBound(127), OnlyAssumeUpdatedVarsEq(false), @@ -250,8 +247,8 @@ class VlgVerifTgtGenBase { YosysUndrivenNetAsInput(true), YosysSmtFlattenHierarchy(true), YosysSmtFlattenDatatype(false), YosysPropertyCheckShowProof(false), YosysSmtArrayForRegFile(false), - YosysSmtStateSort(YosysStateSortT::Datatypes), InvariantSynthesisKeepMemory(true), - InvariantCheckKeepMemory(true), + YosysSmtStateSort(YosysStateSortT::Datatypes), + InvariantSynthesisKeepMemory(true), InvariantCheckKeepMemory(true), InvariantSynthesisReachableCheckKeepOldInvariant(false), YosysSetUndrivenZero(false), @@ -274,8 +271,7 @@ class VlgVerifTgtGenBase { AbcAssumptionStyle(AbcAssumptionStyle_t::AigMiterExtraOutput), // ----------- Options for Refinement Sanity Checks -------------- // - SanityCheck_ValueRecorderOverlyConstrained(true) - {} + SanityCheck_ValueRecorderOverlyConstrained(true) {} } vtg_config_t; /// Advanced parameters used for invariant synthesizer @@ -315,7 +311,7 @@ class VerilogVerificationTargetGenerator { /// Type of the backend using backend_selector = VlgVerifTgtGenBase::backend_selector; /// Type of the synthesis backend - //using synthesis_backend_selector = + // using synthesis_backend_selector = // VlgVerifTgtGenBase::synthesis_backend_selector; /// Type of configuration using vtg_config_t = VlgVerifTgtGenBase::vtg_config_t; @@ -325,7 +321,7 @@ class VerilogVerificationTargetGenerator { /// /// \param[in] implementation's include path (if it uses `include) /// \param[in] verilog's path, currently we only handle situation where all in - /// the same folder + /// the same folder /// \param[in] name of the top module of the implementation, /// leave "" to allow auto analysis /// \param[in] where to get variable mapping diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 682350958..d367e470e 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -22,8 +22,8 @@ #include "nlohmann/json.hpp" #include #include -#include #include +#include #include #include #include @@ -38,12 +38,9 @@ struct RtlExtraWire { std::string hierarchy; std::string internal_name; unsigned width; - RtlExtraWire(const std::string & wn, - const std::string & h, - const std::string & i, - unsigned _width) : - wire_name(wn), hierarchy(h), internal_name(i), - width(_width) { } + RtlExtraWire(const std::string& wn, const std::string& h, + const std::string& i, unsigned _width) + : wire_name(wn), hierarchy(h), internal_name(i), width(_width) {} // for example: // RTL.a.b.c[3] // wire_name : RTL__DOT__a__DOT__b__DOT__c_3_ @@ -62,7 +59,7 @@ class VlgSglTgtGen { /// Type of the verification backend using backend_selector = VlgVerifTgtGenBase::backend_selector; /// Type of the synthesis backend - //using synthesis_backend_selector = + // using synthesis_backend_selector = // VlgVerifTgtGenBase::synthesis_backend_selector; /// Type of configuration using vtg_config_t = VlgVerifTgtGenBase::vtg_config_t; @@ -85,17 +82,17 @@ class VlgSglTgtGen { /// \param[in] which backend to use, it needs this info to gen proper /// properties VlgSglTgtGen( - const std::string& output_path, // will be a sub directory of the output_path of its parent - const InstrPtr& instr_ptr, // which could be an empty pointer, and it will - // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const rfmap::VerilogRefinementMap & refinement, - VerilogInfo* _vlg_info_ptr, - const std::string& wrapper_name, - const std::vector& implementation_srcs, - const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector backend, - const target_type_t& target_tp, advanced_parameters_t* adv_ptr); + const std::string& output_path, // will be a sub directory of the + // output_path of its parent + const InstrPtr& instr_ptr, // which could be an empty pointer, and it will + // be used to verify invariants + const InstrLvlAbsPtr& ila_ptr, + const rfmap::VerilogRefinementMap& refinement, VerilogInfo* _vlg_info_ptr, + const std::string& wrapper_name, + const std::vector& implementation_srcs, + const std::vector& implementation_include_path, + const vtg_config_t& vtg_config, backend_selector backend, + const target_type_t& target_tp, advanced_parameters_t* adv_ptr); /// Destructor: do nothing , most importantly it is virtual virtual ~VlgSglTgtGen() {} @@ -163,7 +160,7 @@ class VlgSglTgtGen { const ExprPtr IlaGetInput(const std::string& sname) const; /// Get (a,d) width of a memory, if not existing, (0,0) std::pair - GetMemInfo(const std::string& ila_mem_name) const; + GetMemInfo(const std::string& ila_mem_name) const; /// Test if a string represents an ila state name bool TryFindIlaState(const std::string& sname); /// Test if a string represents an ila input name @@ -173,77 +170,79 @@ class VlgSglTgtGen { /// Try to find a ILA var according to a name ExprPtr TryFindIlaVarName(const std::string& sname); /// return the type of a variable when its name is given - rfmap::RfVarTypeOrig VarTypeCheckForRfExprParsing(const std::string &); - + rfmap::RfVarTypeOrig VarTypeCheckForRfExprParsing(const std::string&); + /// Check if ila name and vlg name are type compatible (not including special /// directives) static unsigned TypeMatched(const ExprPtr& ila_var, const SignalInfoBase& vlg_var); /// get width of an ila node static unsigned get_width(const ExprPtr& n); - + // ----------------------------------------------------------------------- - // Refinement map handling + // Refinement map handling // ----------------------------------------------------------------------- /// Create a variable replacement for var /// RTL_var/ ILA_IN/ ILA_SO/ INTERNL-DEFVAR /// a new var is always typed - /// otherwise, will not + /// otherwise, will not /// this function get type information from - /// VarTypeCheckForRfExprParsing and + /// VarTypeCheckForRfExprParsing and /// refinement_map.all_var_def_type - rfmap::VarReplacement CreateVarReplacement( - const rfmap::RfVar & var, bool replace_internal_names); + rfmap::VarReplacement CreateVarReplacement(const rfmap::RfVar& var, + bool replace_internal_names); /// replace var for assumptions/assertions /// (should only be used inside assumptions/assertions) /// 1. GetVar 2. Check Replacement 3. add replacement using the above /// function 4. do replacement for var 5. annotate type - rfmap::RfExpr ReplExpr(const rfmap::RfExpr & in); + rfmap::RfExpr ReplExpr(const rfmap::RfExpr& in); /// treat `in` as var map, if it is not a Boolean, add `==` /// this function is not used in `_bv` version below - rfmap::RfExpr TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn); - + rfmap::RfExpr TranslateMap(const rfmap::RfExpr& in, + const std::string& ila_vn); + /// translate a conditional map to rf expression rfmap::RfExpr condition_map_to_rfexpr( - const std::vector> & cond_map, - const std::string & ila_state_name); + const std::vector>& cond_map, + const std::string& ila_state_name); /// difference from condition_map_to_rfexpr is that /// this will not create (v == ...) , this expects bv rfmap::RfExpr condition_map_bv_to_rfexpr( - const std::vector> & cond_map); - + const std::vector>& cond_map); + /// translate a single map to rfexpr - rfmap::RfExpr singlemap_to_rfexpr( - const rfmap::SingleVarMap & single_map, - const std::string & ila_state_name); + rfmap::RfExpr singlemap_to_rfexpr(const rfmap::SingleVarMap& single_map, + const std::string& ila_state_name); /// translate a single map to rfexpr (expect bit-vector) - rfmap::RfExpr singlemap_bv_to_rfexpr( - const rfmap::SingleVarMap & single_map); + rfmap::RfExpr singlemap_bv_to_rfexpr(const rfmap::SingleVarMap& single_map); /// register a reg in refinement_map.all_var_def_type - void rfmap_add_internal_reg(const std::string &n, unsigned width); + void rfmap_add_internal_reg(const std::string& n, unsigned width); /// register a wire in refinement_map.all_var_def_type - void rfmap_add_internal_wire(const std::string &n, unsigned width); + void rfmap_add_internal_wire(const std::string& n, unsigned width); /// register a replacement in refinement_map /// this will affect ReplExpr's behavior /// (Note 1: ReplExpr will also create replacement, but it will not use /// this function. 2: will require that the new one has been registered /// in refinement_map.all_var_def_type) - void rfmap_add_replacement(const std::string &old, const std::string &n); + void rfmap_add_replacement(const std::string& old, const std::string& n); /// handle a var map void Gen_varmap_assumpt_assert(const std::string& ila_state_name, - const rfmap::IlaVarMapping &vmap, const std::string & problem_name, bool true_for_assumpt_false_for_assert); + const rfmap::IlaVarMapping& vmap, + const std::string& problem_name, + bool true_for_assumpt_false_for_assert); // handle an input map void Gen_input_map_assumpt(const std::string& ila_input_name, - const rfmap::IlaVarMapping &imap, const std::string & problem_name); + const rfmap::IlaVarMapping& imap, + const std::string& problem_name); /// add a start condition if it is given - void handle_start_condition(const std::vector & dc); + void handle_start_condition(const std::vector& dc); /// Find the current instruction-mapping - const rfmap::InstructionCompleteCondition & get_current_instruction_rf(); + const rfmap::InstructionCompleteCondition& get_current_instruction_rf(); protected: // --------------- STEPS OF GENERATION ------------------------// @@ -291,9 +290,9 @@ class VlgSglTgtGen { /// handle all_assumption/all_assertion /// ReplExpr all assertion/assumptions /// ReplExpr will know whether to create - /// `__DOT__`, but will anyway + /// `__DOT__`, but will anyway // do the other replacement, and non-repl - /// for yosys: + /// for yosys: /// 1. use var_replacement to create /// extra wire /// 2. check if contains array[const] @@ -344,17 +343,23 @@ class VlgSglTgtGen { backend_selector _backend; protected: - // ----------------------- MEMBERS for storing assumptions/assertions ------------------- // + // ----------------------- MEMBERS for storing assumptions/assertions + // ------------------- // /// assumptions : written by add_an_assumption, - /// consumed by ConstructWrapper_translate_property_and_collect_all_rtl_connection_var + /// consumed by + /// ConstructWrapper_translate_property_and_collect_all_rtl_connection_var std::map> all_assumptions; /// assumptions : written by add_an_assertion, - /// consumed by ConstructWrapper_translate_property_and_collect_all_rtl_connection_var + /// consumed by + /// ConstructWrapper_translate_property_and_collect_all_rtl_connection_var std::map> all_assertions; - /// consumed by ConstructWrapper_translate_property_and_collect_all_rtl_connection_var + /// consumed by + /// ConstructWrapper_translate_property_and_collect_all_rtl_connection_var std::map> all_sanity_assertions; /// assign or assumptions : vector of (dspt, wire_name, rhs, wn == rhs) - std::vector> assign_or_assumptions; + std::vector< + std::tuple> + assign_or_assumptions; /// map: wire_name -> (wire_name, hierarchy, internal name) std::unordered_map rtl_extra_wire; @@ -388,25 +393,25 @@ class VlgSglTgtGen { protected: // helper function to be implemented by COSA/JASPER /// Add an assumption -- backend dependent - virtual void add_a_direct_assumption(const std::string& aspt, - const std::string& dspt) = 0; + virtual void add_a_direct_assumption(const std::string& aspt, + const std::string& dspt) = 0; /// Add an assertion - virtual void add_a_direct_assertion(const std::string& aspt, - const std::string& dspt) = 0; + virtual void add_a_direct_assertion(const std::string& aspt, + const std::string& dspt) = 0; /// Add a sanity assertion - virtual void add_a_direct_sanity_assertion(const std::string& aspt, - const std::string& dspt) = 0; - + virtual void add_a_direct_sanity_assertion(const std::string& aspt, + const std::string& dspt) = 0; + /// Add SMT-lib2 assumption virtual void add_a_direct_smt_assumption(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) = 0; + const std::string& ret, + const std::string& body, + const std::string& dspt) = 0; /// Add SMT-lib2 assertion virtual void add_a_direct_smt_assertion(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) = 0; + const std::string& ret, + const std::string& body, + const std::string& dspt) = 0; // helper function to add assumption/assertions to internal data-strcture virtual void add_an_assumption(const rfmap::RfExpr& aspt, @@ -418,31 +423,29 @@ class VlgSglTgtGen { /// Add an assertion for sanity checking -- simply put in record void add_a_santiy_assertion(const rfmap::RfExpr& aspt, - const std::string& dspt); + const std::string& dspt); // Add SMT assumption (using rfexpr) // - will use add_a_direct_smt_assumption/assertion - virtual void add_smt_assumption( - const rfmap::RfExpr & body, - const std::string & dspt); + virtual void add_smt_assumption(const rfmap::RfExpr& body, + const std::string& dspt); // Add SMT assertion (using rfexpr) - virtual void add_smt_assertion( - const rfmap::RfExpr & body, - const std::string & dspt); + virtual void add_smt_assertion(const rfmap::RfExpr& body, + const std::string& dspt); - /// Add an assignment which in JasperGold could be an assignment, but in Yosys-based solution - /// has to be an assumption + /// Add an assignment which in JasperGold could be an assignment, but in + /// Yosys-based solution has to be an assumption virtual void add_wire_assign_assumption(const std::string& varname, - const rfmap::RfExpr &aspt, + const rfmap::RfExpr& aspt, const std::string& dspt); /// Add an assignment, will always be an assumption /// will use add_an_assumption, and it is up to /// the derived class to determine whether to add as vlg/smt assumption virtual void add_reg_cassign_assumption(const std::string& varname, - const rfmap::RfExpr & expression, - int width, const rfmap::RfExpr & cond, + const rfmap::RfExpr& expression, + int width, const rfmap::RfExpr& cond, const std::string& dspt); public: @@ -496,7 +499,7 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { VlgVerifTgtGen(const std::vector& implementation_include_path, const std::vector& implementation_srcs, const std::string& implementation_top_module, - const rfmap::VerilogRefinementMap & refinement, + const rfmap::VerilogRefinementMap& refinement, const std::string& output_path, const InstrLvlAbsPtr& ila_ptr, backend_selector backend, const vtg_config_t& vtg_config, advanced_parameters_t* adv_ptr = NULL); @@ -538,7 +541,6 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { /// to store the generate script name std::vector runnable_script_name; - public: // --------------------- METHODS ---------------------------- // /// Generate everything @@ -565,7 +567,6 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { /// generate the runable script name const std::vector& GetRunnableScriptName() const; - protected: /// If it is bad state, return true and display a message bool bad_state_return(void); diff --git a/include/ilang/vtarget-out/vtarget_gen_jasper.h b/include/ilang/vtarget-out/vtarget_gen_jasper.h index 2ba31bae8..115be6103 100644 --- a/include/ilang/vtarget-out/vtarget_gen_jasper.h +++ b/include/ilang/vtarget-out/vtarget_gen_jasper.h @@ -38,14 +38,13 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants const InstrLvlAbsPtr& ila_ptr, - const rfmap::VerilogRefinementMap & refinement, - VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, + const rfmap::VerilogRefinementMap& refinement, VerilogInfo* _vlg_info_ptr, + const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& include_dirs, const vtg_config_t& vtg_config, backend_selector backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr); - protected: /// internal storage of problems /// vector of pairs of @@ -53,21 +52,21 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { /// vector of pairs of std::vector> assertions; /// vector of clock signals that need to be taken care of - + /// Name of the problem file std::string jg_script_name; protected: /// Add SMT-lib2 assumption virtual void add_a_direct_smt_assumption(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) override; + const std::string& ret, + const std::string& body, + const std::string& dspt) override; /// Add SMT-lib2 assertion virtual void add_a_direct_smt_assertion(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) override; + const std::string& ret, + const std::string& body, + const std::string& dspt) override; /// Add a direct assumption virtual void add_a_direct_assumption(const std::string& aspt, @@ -77,9 +76,9 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { const std::string& dspt) override; /// Add a direct assertion virtual void add_a_direct_sanity_assertion(const std::string& asst, - const std::string& dspt) override { - add_a_direct_assertion(asst,dspt); } - + const std::string& dspt) override { + add_a_direct_assertion(asst, dspt); + } /// Pre export work : nothing for cosa void virtual PreExportProcess() override {} diff --git a/include/ilang/vtarget-out/vtarget_gen_pono.h b/include/ilang/vtarget-out/vtarget_gen_pono.h index e9221955d..29fe48f75 100644 --- a/include/ilang/vtarget-out/vtarget_gen_pono.h +++ b/include/ilang/vtarget-out/vtarget_gen_pono.h @@ -42,11 +42,11 @@ class Pono_problem { problemset_t assertions; /// problems are splitted into items problemset_t sanity_assertions; - + /// SMT-LIB2 assumptions prop_t smt_assumptions; /// SMT-LIB2 assertions - prop_t smt_assertions; + prop_t smt_assertions; }; // Pono_problem @@ -66,8 +66,8 @@ class VlgSglTgtGen_Pono : public VlgSglTgtGen { // --------------------- CONSTRUCTOR ---------------------------- // /// /// \param[in] output path (ila-verilog, wrapper-verilog, problem.txt, - /// run-verify-by-???, modify-impl, it there is ) - /// \param[in] pointer to the instruction + /// run-verify-by-???, modify-impl, it there is ) + /// \param[in] pointer to the instruction /// \param[in] the refinement map /// \param[in] pointer to verify info class /// \param[in] verilog module name @@ -82,8 +82,8 @@ class VlgSglTgtGen_Pono : public VlgSglTgtGen { const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants const InstrLvlAbsPtr& ila_ptr, - const rfmap::VerilogRefinementMap & refinement, - VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, + const rfmap::VerilogRefinementMap& refinement, VerilogInfo* _vlg_info_ptr, + const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& include_dirs, const vtg_config_t& vtg_config, backend_selector backend, @@ -104,18 +104,18 @@ class VlgSglTgtGen_Pono : public VlgSglTgtGen { const std::string& dspt) override; /// Add a direct assertion virtual void add_a_direct_sanity_assertion(const std::string& asst, - const std::string& dspt) override; - + const std::string& dspt) override; + /// Add SMT-lib2 assumption virtual void add_a_direct_smt_assumption(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) override; + const std::string& ret, + const std::string& body, + const std::string& dspt) override; /// Add SMT-lib2 assertion virtual void add_a_direct_smt_assertion(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) override; + const std::string& ret, + const std::string& body, + const std::string& dspt) override; /// Pre export work : nothing for pono void virtual PreExportProcess() override; diff --git a/src/rfmap-in/rfexpr_shortcut.cc b/src/rfmap-in/rfexpr_shortcut.cc index 59de905af..00c1a0b60 100644 --- a/src/rfmap-in/rfexpr_shortcut.cc +++ b/src/rfmap-in/rfexpr_shortcut.cc @@ -2,85 +2,89 @@ /// Hongce Zhang (zhanghongce@126.com) #include -#include #include +#include namespace ilang { -rfmap::RfExpr rfmap_reduce_or(const rfmap::RfExpr & in) { - return verilog_expr::VExprAst::MakeUnaryAst(verilog_expr::voperator::B_OR, in); +rfmap::RfExpr rfmap_reduce_or(const rfmap::RfExpr& in) { + return verilog_expr::VExprAst::MakeUnaryAst(verilog_expr::voperator::B_OR, + in); } -rfmap::RfExpr rfmap_imply(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { +rfmap::RfExpr rfmap_imply(const rfmap::RfExpr& l, const rfmap::RfExpr& r) { return rfmap_or(rfmap_not(l), r); } -rfmap::RfExpr rfmap_and(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { - return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, l, r); +rfmap::RfExpr rfmap_and(const rfmap::RfExpr& l, const rfmap::RfExpr& r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_AND, + l, r); } -rfmap::RfExpr rfmap_or(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { - return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_OR, l, r); +rfmap::RfExpr rfmap_or(const rfmap::RfExpr& l, const rfmap::RfExpr& r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_OR, l, + r); } -rfmap::RfExpr rfmap_and(const std::vector &v) { +rfmap::RfExpr rfmap_and(const std::vector& v) { ILA_ERROR_IF(v.empty()) << "rfmap_and([])"; - + auto ret = v.at(0); - for (size_t idx = 1; idx < v.size(); ++ idx) + for (size_t idx = 1; idx < v.size(); ++idx) ret = rfmap_and(ret, v.at(idx)); return ret; } -rfmap::RfExpr rfmap_or(const std::vector &v) { +rfmap::RfExpr rfmap_or(const std::vector& v) { ILA_ERROR_IF(v.empty()) << "rfmap_or([])"; - + auto ret = v.at(0); - for (size_t idx = 1; idx < v.size(); ++ idx) + for (size_t idx = 1; idx < v.size(); ++idx) ret = rfmap_or(ret, v.at(idx)); return ret; } -rfmap::RfExpr rfmap_ite(const rfmap::RfExpr &c, const rfmap::RfExpr &l, - const rfmap::RfExpr &r) { - return verilog_expr::VExprAst::MakeTernaryAst(verilog_expr::voperator::TERNARY, - c, l, r); +rfmap::RfExpr rfmap_ite(const rfmap::RfExpr& c, const rfmap::RfExpr& l, + const rfmap::RfExpr& r) { + return verilog_expr::VExprAst::MakeTernaryAst( + verilog_expr::voperator::TERNARY, c, l, r); } -rfmap::RfExpr rfmap_eq(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { - return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, l, r); +rfmap::RfExpr rfmap_eq(const rfmap::RfExpr& l, const rfmap::RfExpr& r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, l, + r); } -rfmap::RfExpr rfmap_le(const rfmap::RfExpr &l, const rfmap::RfExpr &r) { - return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::LTE, l, r); +rfmap::RfExpr rfmap_le(const rfmap::RfExpr& l, const rfmap::RfExpr& r) { + return verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::LTE, l, + r); } -rfmap::RfExpr rfmap_not(const rfmap::RfExpr &l) { - return verilog_expr::VExprAst::MakeUnaryAst (verilog_expr::voperator::L_NEG, l); +rfmap::RfExpr rfmap_not(const rfmap::RfExpr& l) { + return verilog_expr::VExprAst::MakeUnaryAst(verilog_expr::voperator::L_NEG, + l); } rfmap::RfExpr rfmap_true() { - return verilog_expr::VExprAst::MakeConstant(2,1,"1"); + return verilog_expr::VExprAst::MakeConstant(2, 1, "1"); } rfmap::RfExpr rfmap_false() { - return verilog_expr::VExprAst::MakeConstant(2,1,"0"); + return verilog_expr::VExprAst::MakeConstant(2, 1, "0"); } rfmap::RfExpr rfmap_const(unsigned b, unsigned w, unsigned v) { - return verilog_expr::VExprAst::MakeConstant(b, w, IntToStrCustomBase(v, b, false)); + return verilog_expr::VExprAst::MakeConstant(b, w, + IntToStrCustomBase(v, b, false)); } /// if it is RTL. or ILA. then will use MakeVar /// otherwise will use MakeSpecial /// will not determine its type /// ReplExpr will determine the type -rfmap::RfExpr rfmap_var(const std::string &v) { - if(StrStartsWith(v, "RTL.") || StrStartsWith(v, "ILA.")) +rfmap::RfExpr rfmap_var(const std::string& v) { + if (StrStartsWith(v, "RTL.") || StrStartsWith(v, "ILA.")) return verilog_expr::VExprAst::MakeVar(v); return verilog_expr::VExprAst::MakeSpecialName(v); } - - - } // namespace ilang diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc index 49551f287..ff3b9e840 100644 --- a/src/rfmap-in/rfexpr_to_smt.cc +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -2,73 +2,51 @@ /// Hongce Zhang (hongcez@princeton.edu) #include -#include #include +#include #include - namespace ilang { namespace rfmap { - std::string SmtType::type_to_smt2() const { - if(is_bool()) + if (is_bool()) return "Bool"; - if(is_bv()) - return "(_ BitVec "+std::to_string(unified_width())+")"; + if (is_bv()) + return "(_ BitVec " + std::to_string(unified_width()) + ")"; ILA_ERROR_IF(!is_array()) << "Does not know how to translate unknown type"; - return "(Array (_ BitVec " +std::to_string(addr_width)+") (_ BitVec " + std::to_string(data_width)+"))"; + return "(Array (_ BitVec " + std::to_string(addr_width) + ") (_ BitVec " + + std::to_string(data_width) + "))"; } static std::vector voperator_str_smt = { - "bvmul", // STAR - "bvadd", - "bvsub", - "bvshl", - "bvashr", - "bvshl", - "bvlshr", - "bvudiv", - "#notsupported", // POW ** - "bvurem", - "bvuge", - "bvule", - "bvugt", - "bvult", - "not", - "and", - "or", - "=", - "=", - "#special", - "#special", - "bvnot", - "bvand", - "bvor", - "bvxor", - "bvxnor", - "bvnand", - "bvnor", // B_NOR - "#special", // select/extract [idx] operator A[i1][i2] -> index(index(A,i1),i2) A[i1[i2]] index(A, index(i1,i2)) - "#special", // extract [i1:i2] ternary - "#special", // extract [i1:+i2] ternary - "#special", // extract [i1:-i2] ternary - "store", // store A:<3>:5:<4>:6:<5>:7 (not supported yet) - "#notsupported", // AT - "ite", // ternary - /*special ops*/ - "#special", // function app - "concat", - "#special", // REPEAT if it is const we can handle - /*Placeholder*/ - "MK_CONST", - "MK_VAR", - - "#notsupported" // delay + "bvmul", // STAR + "bvadd", "bvsub", "bvshl", "bvashr", "bvshl", "bvlshr", "bvudiv", + "#notsupported", // POW ** + "bvurem", "bvuge", "bvule", "bvugt", "bvult", "not", "and", "or", "=", "=", + "#special", "#special", "bvnot", "bvand", "bvor", "bvxor", "bvxnor", + "bvnand", + "bvnor", // B_NOR + "#special", // select/extract [idx] operator A[i1][i2] -> + // index(index(A,i1),i2) A[i1[i2]] index(A, index(i1,i2)) + "#special", // extract [i1:i2] ternary + "#special", // extract [i1:+i2] ternary + "#special", // extract [i1:-i2] ternary + "store", // store A:<3>:5:<4>:6:<5>:7 (not supported yet) + "#notsupported", // AT + "ite", // ternary + /*special ops*/ + "#special", // function app + "concat", + "#special", // REPEAT if it is const we can handle + /*Placeholder*/ + "MK_CONST", "MK_VAR", + + "#notsupported" // delay }; -static RfMapVarType get_type(const RfExpr & in) { +static RfMapVarType get_type(const RfExpr& in) { auto tp = in->get_annotation(); if (tp == nullptr) return RfMapVarType(); @@ -77,82 +55,86 @@ static RfMapVarType get_type(const RfExpr & in) { static std::string smt_const(unsigned value, unsigned width) { auto ret = IntToStrCustomBase(value, 2, false); - if(ret.length() > width) { - ILA_ERROR << "Creating SMT constant with value " << value << " width: " << width; - throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + if (ret.length() > width) { + ILA_ERROR << "Creating SMT constant with value " << value + << " width: " << width; + throw verilog_expr::VexpException( + verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); } - + std::string zero; - if(width > ret.length()) - for (unsigned idx = 0; idx < width - ret.length(); ++ idx) + if (width > ret.length()) + for (unsigned idx = 0; idx < width - ret.length(); ++idx) zero += "0"; return "#b" + zero + ret; } // smt_const -static std::string split_bit(const std::string & opstr, - unsigned width, const std::string & childstr) { - if(width <= 1) +static std::string split_bit(const std::string& opstr, unsigned width, + const std::string& childstr) { + if (width <= 1) return childstr; std::vector child; - for(unsigned idx = 0; idx < width; ++ idx) { - auto ext = "(_ extract " + std::to_string(idx) + " " + std::to_string(idx) + ")"; - child.push_back("(" + ext + " " + childstr + ")"); + for (unsigned idx = 0; idx < width; ++idx) { + auto ext = + "(_ extract " + std::to_string(idx) + " " + std::to_string(idx) + ")"; + child.push_back("(" + ext + " " + childstr + ")"); } - std::string ret = "(" + opstr + " " + child.at(0) + " " + child.at(1)+")"; - for (unsigned idx = 2; idx < child.size(); ++ idx) - ret = "(" + opstr + " " + ret + " " + child.at(idx) +")"; + std::string ret = "(" + opstr + " " + child.at(0) + " " + child.at(1) + ")"; + for (unsigned idx = 2; idx < child.size(); ++idx) + ret = "(" + opstr + " " + ret + " " + child.at(idx) + ")"; return ret; } static SmtType common_type(RfMapVarType tp1, RfMapVarType tp2) { - if(tp1.is_array() || tp2.is_array()) { + if (tp1.is_array() || tp2.is_array()) { ILA_CHECK(tp2.is_array() && tp1.is_array() && - tp2.addr_width == tp1.addr_width && - tp2.data_width == tp1.data_width); + tp2.addr_width == tp1.addr_width && + tp2.data_width == tp1.data_width); return SmtType(tp1, false); } - if(tp1.is_bv() && tp2.is_bv()) { - return SmtType( std::max(tp1.unified_width(), tp2.unified_width()) ); + if (tp1.is_bv() && tp2.is_bv()) { + return SmtType(std::max(tp1.unified_width(), tp2.unified_width())); } - if(tp1.is_unknown() || tp2.is_unknown()) { + if (tp1.is_unknown() || tp2.is_unknown()) { if (!tp1.is_unknown()) - return SmtType(tp1,false); + return SmtType(tp1, false); if (!tp2.is_unknown()) - return SmtType(tp2,false); + return SmtType(tp2, false); } ILA_CHECK(false) << "unable to determine common type"; } -static std::string extend_width(const std::string & in, unsigned inw, unsigned outw) { +static std::string extend_width(const std::string& in, unsigned inw, + unsigned outw) { ILA_CHECK(outw > inw); - return "(concat " + smt_const(0, outw-inw) + " " + in + ")"; + return "(concat " + smt_const(0, outw - inw) + " " + in + ")"; } // make sure in_bool -> out_bool -static std::string type_convert(SmtType out_tp, SmtType in_tp, const std::string & in) { - if(out_tp == in_tp) - return in; +static std::string type_convert(SmtType out_tp, SmtType in_tp, + const std::string& in) { + if (out_tp == in_tp) + return in; - if(out_tp.is_bool() && in_tp.is_bv()) { - return "(not (= " + in + " "+ smt_const(0, in_tp.unified_width()) +"))"; + if (out_tp.is_bool() && in_tp.is_bv()) { + return "(not (= " + in + " " + smt_const(0, in_tp.unified_width()) + "))"; } - if(in_tp.is_bool() && out_tp.is_bv()) { - return extend_width("(ite " + in + " #b1 #b0)",1,out_tp.unified_width()) ; + if (in_tp.is_bool() && out_tp.is_bv()) { + return extend_width("(ite " + in + " #b1 #b0)", 1, out_tp.unified_width()); } - if(in_tp.is_bv() && out_tp.is_bv() && - in_tp.unified_width() != out_tp.unified_width()) - { + if (in_tp.is_bv() && out_tp.is_bv() && + in_tp.unified_width() != out_tp.unified_width()) { ILA_ASSERT(out_tp.unified_width() > in_tp.unified_width()) - << "[Convert to SMT] cutting input bit-vector, not allowed."; + << "[Convert to SMT] cutting input bit-vector, not allowed."; return extend_width(in, in_tp.unified_width(), out_tp.unified_width()); } - if(in_tp.is_array() || out_tp.is_array()) { + if (in_tp.is_array() || out_tp.is_array()) { ILA_CHECK(false) << "Unable to convert array of different sizes"; } ILA_CHECK(false) << "Unable to convert types"; @@ -160,7 +142,7 @@ static std::string type_convert(SmtType out_tp, SmtType in_tp, const std::string } // typeconvert -// intype == outtype +// intype == outtype // bv_n -> bool // bool -> bv_n // bv_n -> bv_(n+m) @@ -168,33 +150,37 @@ static std::string type_convert(SmtType out_tp, SmtType in_tp, const std::string // E: array -> ? // E: ? -> array -std::string RfExpr2Smt::to_smt2_const(const std::shared_ptr & in, SmtType expected_type) { +std::string RfExpr2Smt::to_smt2_const( + const std::shared_ptr& in, + SmtType expected_type) { unsigned out; bool succ = _compute_const(in, out); - if(!succ) - throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + if (!succ) + throw verilog_expr::VexpException( + verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); auto b_w_l = in->get_constant(); auto width = std::get<1>(b_w_l); - if(width == 0) + if (width == 0) width = expected_type.unified_width(); - return type_convert(expected_type, SmtType(width), smt_const(out, width) ); + return type_convert(expected_type, SmtType(width), smt_const(out, width)); } // to_smt2_const -std::string RfExpr2Smt::to_smt2_var(const std::shared_ptr & in, SmtType expected_type) { +std::string +RfExpr2Smt::to_smt2_var(const std::shared_ptr& in, + SmtType expected_type) { RfMapVarType tp = get_type(in); - auto ret = "|" + in->get_name().first+"|"; - if(!tp.is_array()) + auto ret = "|" + in->get_name().first + "|"; + if (!tp.is_array()) ret = type_convert(expected_type, SmtType(tp.unified_width()), ret); else - ILA_ASSERT(expected_type == SmtType(tp,false)); + ILA_ASSERT(expected_type == SmtType(tp, false)); return ret; } // to_smt2_var - -std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { - if(in->is_var()) { +std::string RfExpr2Smt::to_smt2(const RfExpr& in, SmtType expected_type) { + if (in->is_var()) { auto ptr = std::dynamic_pointer_cast(in); ILA_NOT_NULL(ptr); return to_smt2_var(ptr, expected_type); @@ -206,262 +192,251 @@ std::string RfExpr2Smt::to_smt2(const RfExpr &in, SmtType expected_type) { } auto op_ = in->get_op(); - const auto & child_ = in->get_child(); + const auto& child_ = in->get_child(); - ILA_ASSERT(op_ != verilog_expr::voperator::MK_CONST && op_ != verilog_expr::voperator::MK_CONST); + ILA_ASSERT(op_ != verilog_expr::voperator::MK_CONST && + op_ != verilog_expr::voperator::MK_CONST); unsigned idx = static_cast(op_); ILA_ASSERT(idx < voperator_str_smt.size()); auto opstr = voperator_str_smt.at(idx); if (opstr == "#notsupported") - throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2, opstr ); - // TODO: + throw verilog_expr::VexpException( + verilog_expr::ExceptionCause::UntranslatedSmtlib2, opstr); + // TODO: - if ( child_.size() == 1 && - (op_ == verilog_expr::voperator::L_NEG)) { + if (child_.size() == 1 && (op_ == verilog_expr::voperator::L_NEG)) { - RfMapVarType tp = get_type(child_.at(0)); - return type_convert( expected_type, SmtType(tp,true), - "("+opstr + " " + to_smt2(child_.at(0), SmtType(tp,true) )+")"); + RfMapVarType tp = get_type(child_.at(0)); + return type_convert(expected_type, SmtType(tp, true), + "(" + opstr + " " + + to_smt2(child_.at(0), SmtType(tp, true)) + ")"); } - if ( child_.size() == 1 && - (op_ == verilog_expr::voperator::B_NEG)) { + if (child_.size() == 1 && (op_ == verilog_expr::voperator::B_NEG)) { - RfMapVarType tp = get_type(child_.at(0)); - return type_convert(expected_type, SmtType(tp,false), - "("+opstr + " " + to_smt2(child_.at(0), SmtType(tp,false))+")"); + RfMapVarType tp = get_type(child_.at(0)); + return type_convert(expected_type, SmtType(tp, false), + "(" + opstr + " " + + to_smt2(child_.at(0), SmtType(tp, false)) + ")"); } - if (child_.size() == 1 && - op_ == verilog_expr::voperator::PLUS) { + if (child_.size() == 1 && op_ == verilog_expr::voperator::PLUS) { - RfMapVarType tp = get_type(in); - return type_convert(expected_type, SmtType(tp,false), - to_smt2(child_.at(0), SmtType(tp,false))); + RfMapVarType tp = get_type(in); + return type_convert(expected_type, SmtType(tp, false), + to_smt2(child_.at(0), SmtType(tp, false))); } - if (child_.size() == 1 && - op_ == verilog_expr::voperator::MINUS) { + if (child_.size() == 1 && op_ == verilog_expr::voperator::MINUS) { - RfMapVarType tp = get_type(in); - return type_convert(expected_type, SmtType(tp,false), - "(bvsub " + smt_const(0,tp.unified_width()) + " "+to_smt2(child_.at(0), SmtType(tp,false))); + RfMapVarType tp = get_type(in); + return type_convert(expected_type, SmtType(tp, false), + "(bvsub " + smt_const(0, tp.unified_width()) + " " + + to_smt2(child_.at(0), SmtType(tp, false))); } - if (child_.size() == 1 && - ( op_ == verilog_expr::voperator::B_AND || - op_ == verilog_expr::voperator::B_NAND || - op_ == verilog_expr::voperator::B_OR || - op_ == verilog_expr::voperator::B_NOR || - op_ == verilog_expr::voperator::B_XOR || - op_ == verilog_expr::voperator::B_EQU - )) { + if (child_.size() == 1 && (op_ == verilog_expr::voperator::B_AND || + op_ == verilog_expr::voperator::B_NAND || + op_ == verilog_expr::voperator::B_OR || + op_ == verilog_expr::voperator::B_NOR || + op_ == verilog_expr::voperator::B_XOR || + op_ == verilog_expr::voperator::B_EQU)) { - RfMapVarType tp = get_type(in); + RfMapVarType tp = get_type(in); - return type_convert(expected_type, SmtType(tp,false), - split_bit(opstr, tp.unified_width(), to_smt2(child_.at(0), SmtType(tp,false)))); + return type_convert(expected_type, SmtType(tp, false), + split_bit(opstr, tp.unified_width(), + to_smt2(child_.at(0), SmtType(tp, false)))); } RfMapVarType parent_tp = get_type(in); // binary or more - switch(op_) { - case verilog_expr::voperator::STAR: // mul - case verilog_expr::voperator::PLUS: - case verilog_expr::voperator::MINUS: - case verilog_expr::voperator::ASL: - case verilog_expr::voperator::ASR: - case verilog_expr::voperator::LSL: - case verilog_expr::voperator::LSR: - case verilog_expr::voperator::DIV: - case verilog_expr::voperator::MOD: - ILA_ASSERT(child_.size() == 2); - return type_convert(expected_type, SmtType(parent_tp,false), - "(" + opstr+" " - + to_smt2(child_.at(0),SmtType(parent_tp,false)) + " " - + to_smt2(child_.at(1),SmtType(parent_tp,false))+")" - ); - break; - - case verilog_expr::voperator::GTE: - case verilog_expr::voperator::LTE: - case verilog_expr::voperator::GT: - case verilog_expr::voperator::LT: - case verilog_expr::voperator::C_EQ: - case verilog_expr::voperator::L_EQ: - ILA_ASSERT(child_.size() == 2); - { - SmtType common_tp = common_type(get_type(child_.at(0)), get_type(child_.at(1))); - return type_convert(expected_type, SmtType(parent_tp,true), - "(" + opstr - + " " + to_smt2(child_.at(0),common_tp) - + " " + to_smt2(child_.at(1),common_tp)+")" - ); - } - break; - - case verilog_expr::voperator::C_NEQ: - case verilog_expr::voperator::L_NEQ: - ILA_ASSERT(child_.size() == 2); - { // expect common_type to make bool false? - SmtType common_tp = common_type(get_type(child_.at(0)), get_type(child_.at(1))); - return type_convert(expected_type, SmtType(parent_tp,true), - "(not (= " + - to_smt2(child_.at(0),common_tp) + " " + - to_smt2(child_.at(1),common_tp) + "))" - ); - break; - } - - case verilog_expr::voperator::L_AND: - case verilog_expr::voperator::L_OR: - ILA_ASSERT(child_.size() == 2); - return type_convert(expected_type, SmtType(parent_tp,true), - "(" + opstr - + " " + to_smt2(child_.at(0),SmtType(get_type(child_.at(0)),true)) - + " " + to_smt2(child_.at(1),SmtType(get_type(child_.at(1)),true)) - + ")" - ); + switch (op_) { + case verilog_expr::voperator::STAR: // mul + case verilog_expr::voperator::PLUS: + case verilog_expr::voperator::MINUS: + case verilog_expr::voperator::ASL: + case verilog_expr::voperator::ASR: + case verilog_expr::voperator::LSL: + case verilog_expr::voperator::LSR: + case verilog_expr::voperator::DIV: + case verilog_expr::voperator::MOD: + ILA_ASSERT(child_.size() == 2); + return type_convert( + expected_type, SmtType(parent_tp, false), + "(" + opstr + " " + to_smt2(child_.at(0), SmtType(parent_tp, false)) + + " " + to_smt2(child_.at(1), SmtType(parent_tp, false)) + ")"); + break; + + case verilog_expr::voperator::GTE: + case verilog_expr::voperator::LTE: + case verilog_expr::voperator::GT: + case verilog_expr::voperator::LT: + case verilog_expr::voperator::C_EQ: + case verilog_expr::voperator::L_EQ: + ILA_ASSERT(child_.size() == 2); + { + SmtType common_tp = + common_type(get_type(child_.at(0)), get_type(child_.at(1))); + return type_convert(expected_type, SmtType(parent_tp, true), + "(" + opstr + " " + to_smt2(child_.at(0), common_tp) + + " " + to_smt2(child_.at(1), common_tp) + ")"); + } + break; + + case verilog_expr::voperator::C_NEQ: + case verilog_expr::voperator::L_NEQ: + ILA_ASSERT(child_.size() == 2); + { // expect common_type to make bool false? + SmtType common_tp = + common_type(get_type(child_.at(0)), get_type(child_.at(1))); + return type_convert(expected_type, SmtType(parent_tp, true), + "(not (= " + to_smt2(child_.at(0), common_tp) + " " + + to_smt2(child_.at(1), common_tp) + "))"); break; + } + + case verilog_expr::voperator::L_AND: + case verilog_expr::voperator::L_OR: + ILA_ASSERT(child_.size() == 2); + return type_convert( + expected_type, SmtType(parent_tp, true), + "(" + opstr + " " + + to_smt2(child_.at(0), SmtType(get_type(child_.at(0)), true)) + " " + + to_smt2(child_.at(1), SmtType(get_type(child_.at(1)), true)) + ")"); + break; + + case verilog_expr::voperator::B_AND: + case verilog_expr::voperator::B_OR: + case verilog_expr::voperator::B_XOR: + case verilog_expr::voperator::B_EQU: + case verilog_expr::voperator::B_NAND: + case verilog_expr::voperator::B_NOR: { + SmtType common_tp = + common_type(get_type(child_.at(0)), get_type(child_.at(1))); + + ILA_ASSERT(child_.size() == 2); + return type_convert(expected_type, SmtType(parent_tp, false), + "(" + opstr + " " + to_smt2(child_.at(0), common_tp) + + " " + to_smt2(child_.at(1), common_tp) + ")"); + break; + } - case verilog_expr::voperator::B_AND: - case verilog_expr::voperator::B_OR: - case verilog_expr::voperator::B_XOR: - case verilog_expr::voperator::B_EQU: - case verilog_expr::voperator::B_NAND: - case verilog_expr::voperator::B_NOR: - { - SmtType common_tp = common_type(get_type(child_.at(0)), get_type(child_.at(1))); - - ILA_ASSERT(child_.size() == 2); - return type_convert(expected_type, SmtType(parent_tp, false), - "(" + opstr - + " " + to_smt2(child_.at(0),common_tp) - + " " + to_smt2(child_.at(1),common_tp) - + ")" - ); - break; - } - - default: - break; + default: + break; } // end switch - if(op_ == verilog_expr::voperator::INDEX) { - RfMapVarType tp = get_type(child_.at(0)); - if(tp.is_array()) { - return type_convert(expected_type, SmtType(tp.unified_width()), - "(select " + to_smt2(child_.at(0), SmtType(tp, false) ) - + " " - + to_smt2(child_.at(1), SmtType(tp.addr_width)) + ")"); + if (op_ == verilog_expr::voperator::INDEX) { + RfMapVarType tp = get_type(child_.at(0)); + if (tp.is_array()) { + return type_convert( + expected_type, SmtType(tp.unified_width()), + "(select " + to_smt2(child_.at(0), SmtType(tp, false)) + " " + + to_smt2(child_.at(1), SmtType(tp.addr_width)) + ")"); } // else is bv // request to index to be constant unsigned bitidx; - bool succ = _compute_const(child_.at(1),bitidx); - if(!succ) - throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + bool succ = _compute_const(child_.at(1), bitidx); + if (!succ) + throw verilog_expr::VexpException( + verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); auto bitidxstr = std::to_string(bitidx); return type_convert(expected_type, SmtType(1) /* (_ BitVec 1) */, - "((_ extract " + bitidxstr + " " + bitidxstr+") " - + to_smt2( child_.at(0), - SmtType(tp, false) - ) - + ")" ); + "((_ extract " + bitidxstr + " " + bitidxstr + ") " + + to_smt2(child_.at(0), SmtType(tp, false)) + ")"); } // end if INDEX - if(op_ == verilog_expr::voperator::IDX_PRT_SEL_PLUS || - op_ == verilog_expr::voperator::IDX_PRT_SEL_MINUS || - op_ == verilog_expr::voperator::RANGE_INDEX - ) { - - unsigned l,r; - bool succ = _compute_const(child_.at(1),l); - succ = succ && _compute_const(child_.at(2),r); - if(!succ) - throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); - - if(op_ == verilog_expr::voperator::IDX_PRT_SEL_PLUS) + if (op_ == verilog_expr::voperator::IDX_PRT_SEL_PLUS || + op_ == verilog_expr::voperator::IDX_PRT_SEL_MINUS || + op_ == verilog_expr::voperator::RANGE_INDEX) { + + unsigned l, r; + bool succ = _compute_const(child_.at(1), l); + succ = succ && _compute_const(child_.at(2), r); + if (!succ) + throw verilog_expr::VexpException( + verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + + if (op_ == verilog_expr::voperator::IDX_PRT_SEL_PLUS) r = l + r - 1; else if (op_ == verilog_expr::voperator::IDX_PRT_SEL_MINUS) r = l - r + 1; auto lstr = std::to_string(l); auto rstr = std::to_string(r); - RfMapVarType tp = get_type(child_.at(0)); - return type_convert(expected_type, SmtType(l-r+1), - "((_ extract " + lstr + " " + rstr+") " - + to_smt2( child_.at(0), - SmtType(tp, false) - ) - + ")"); + RfMapVarType tp = get_type(child_.at(0)); + return type_convert(expected_type, SmtType(l - r + 1), + "((_ extract " + lstr + " " + rstr + ") " + + to_smt2(child_.at(0), SmtType(tp, false)) + ")"); } // IDX_PRT_SEL_PLUS, IDX_PRT_SEL_MINUS, RANGE_INDEX - + if (op_ == verilog_expr::voperator::STORE_OP) { - SmtType tp0(get_type(child_.at(0)), false); - SmtType tp1(get_type(child_.at(1)), false); + SmtType tp0(get_type(child_.at(0)), false); + SmtType tp1(get_type(child_.at(1)), false); // no need to convert ILA_ASSERT(expected_type == tp0); - return "(store " - + to_smt2(child_.at(0),tp0) + " " - + to_smt2(child_.at(1),tp1) + ")"; + return "(store " + to_smt2(child_.at(0), tp0) + " " + + to_smt2(child_.at(1), tp1) + ")"; // do not convert as we are unable to do so } // STORE_OP if (op_ == verilog_expr::voperator::TERNARY) { RfMapVarType parent_tp = get_type(in); // you need to handle the case of array - SmtType common_tp = common_type(get_type(child_.at(1)), get_type(child_.at(2))); - - if(parent_tp.is_array()) { + SmtType common_tp = + common_type(get_type(child_.at(1)), get_type(child_.at(2))); + + if (parent_tp.is_array()) { // do not convert as we are unable to do so - return "(ite " + to_smt2(child_.at(0), SmtType() ) + " " + - to_smt2(child_.at(1), common_tp) + " " + - to_smt2(child_.at(2), common_tp) + ")"; + return "(ite " + to_smt2(child_.at(0), SmtType()) + " " + + to_smt2(child_.at(1), common_tp) + " " + + to_smt2(child_.at(2), common_tp) + ")"; } // else - + return type_convert(expected_type, common_tp, - "(ite " + to_smt2(child_.at(0), SmtType()) + " " + - to_smt2(child_.at(1), common_tp) + " " + - to_smt2(child_.at(2), common_tp) + ")"); + "(ite " + to_smt2(child_.at(0), SmtType()) + " " + + to_smt2(child_.at(1), common_tp) + " " + + to_smt2(child_.at(2), common_tp) + ")"); } if (op_ == verilog_expr::voperator::FUNCTION_APP) - throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2); - + throw verilog_expr::VexpException( + verilog_expr::ExceptionCause::UntranslatedSmtlib2); + if (op_ == verilog_expr::voperator::CONCAT) { - ILA_ASSERT( in->get_child_cnt() == 2 ); - return type_convert(expected_type, SmtType(parent_tp,false), - "(concat " - + to_smt2(child_.at(0), SmtType(get_type(child_.at(0)), false) ) + " " - + to_smt2(child_.at(1), SmtType(get_type(child_.at(1)), false) ) + ")"); + ILA_ASSERT(in->get_child_cnt() == 2); + return type_convert( + expected_type, SmtType(parent_tp, false), + "(concat " + + to_smt2(child_.at(0), SmtType(get_type(child_.at(0)), false)) + + " " + + to_smt2(child_.at(1), SmtType(get_type(child_.at(1)), false)) + + ")"); } // CONCAT if (op_ == verilog_expr::voperator::REPEAT) { - ILA_ASSERT( in->get_child_cnt() == 2 ); + ILA_ASSERT(in->get_child_cnt() == 2); unsigned ntimes; - if(!_compute_const(in->child(0), ntimes)) - throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); + if (!_compute_const(in->child(0), ntimes)) + throw verilog_expr::VexpException( + verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); ILA_ASSERT(ntimes > 0); - std::string c1 = to_smt2( - child_.at(1), - SmtType(get_type(child_.at(1)),false) ); - std::string ret = "(concat " + c1 + " " + c1 + ")" ; - - for(unsigned idx = 2; idx < ntimes; ++idx) + std::string c1 = + to_smt2(child_.at(1), SmtType(get_type(child_.at(1)), false)); + std::string ret = "(concat " + c1 + " " + c1 + ")"; + + for (unsigned idx = 2; idx < ntimes; ++idx) ret = "(concat " + ret + " " + c1 + ")"; - return type_convert(expected_type, SmtType(parent_tp,false), ret); + return type_convert(expected_type, SmtType(parent_tp, false), ret); } - throw verilog_expr::VexpException(verilog_expr::ExceptionCause::UntranslatedSmtlib2); + throw verilog_expr::VexpException( + verilog_expr::ExceptionCause::UntranslatedSmtlib2); return ""; } // end to_smt - - } // namespace rfmap } // namespace ilang - - diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 645bff79e..1f57ed289 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -2,12 +2,12 @@ /// Second pass : rfexpr typecheck #include -#include #include +#include -#include -#include #include +#include +#include namespace ilang { namespace rfmap { @@ -15,33 +15,30 @@ namespace rfmap { using namespace verilog_expr; std::string TypedVerilogRefinementMap::new_id() { - return "__auxvar"+std::to_string(counter++) + "__"; + return "__auxvar" + std::to_string(counter++) + "__"; } TypedVerilogRefinementMap::TypedVerilogRefinementMap( - const VerilogRefinementMap & refinement, - var_typecheck_t type_checker - ) : VerilogRefinementMap(refinement), typechecker(type_checker), - counter(0) { + const VerilogRefinementMap& refinement, var_typecheck_t type_checker) + : VerilogRefinementMap(refinement), typechecker(type_checker), counter(0) { initialize(); } TypedVerilogRefinementMap::TypedVerilogRefinementMap( - const std::string & varmap_json_file, - const std::string & instcond_json_file, - var_typecheck_t type_checker - ) : VerilogRefinementMap(varmap_json_file, instcond_json_file), - typechecker(type_checker), counter(0) { + const std::string& varmap_json_file, const std::string& instcond_json_file, + var_typecheck_t type_checker) + : VerilogRefinementMap(varmap_json_file, instcond_json_file), + typechecker(type_checker), counter(0) { initialize(); } // TypedVerilogRefinementMap::TypedVerilogRefinementMap - + void TypedVerilogRefinementMap::initialize() { // collect those with unknown types // a. delay // b. value holder CollectInlineDelayValueHolder(); - // put existing internal vars in + // put existing internal vars in // all_var_def_types CollectInternallyDefinedVars(); @@ -52,23 +49,20 @@ void TypedVerilogRefinementMap::initialize() { } // initialize - // this function will iteratively make a new copy of the whole AST. -RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar( - const RfExpr & in) -{ - - // skip state memory mapped +RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar(const RfExpr& in) { + + // skip state memory mapped // provide a function to ReplExpr... auto tp_annotate = in->get_annotation(); - if(in->is_var()) { + if (in->is_var()) { auto var_ptr = std::dynamic_pointer_cast(in); ILA_NOT_NULL(var_ptr); auto n = var_ptr->get_name(); ILA_CHECK(var_replacement.find(n.first) != var_replacement.end()) - << "variable " << n.first << " has no replacement"; + << "variable " << n.first << " has no replacement"; return var_replacement.at(n.first).newvar; } else if (in->is_constant()) { @@ -76,18 +70,16 @@ RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar( } // else is op auto ret_copy = std::make_shared(*in); - for (size_t idx = 0 ; idx < ret_copy->get_child_cnt(); ++ idx) { - ret_copy->child(idx) = - ReplacingRtlIlaVar( - ret_copy->get_child().at(idx)); + for (size_t idx = 0; idx < ret_copy->get_child_cnt(); ++idx) { + ret_copy->child(idx) = ReplacingRtlIlaVar(ret_copy->get_child().at(idx)); } // for each child return ret_copy; } // AnnotateSignalsAndCollectRtlVars - -void TypedVerilogRefinementMap::collect_inline_value_recorder_func(RfExpr & inout) { - if(inout->get_op() == verilog_expr::voperator::AT) { - auto recorder_name = new_id()+"recorder"; +void TypedVerilogRefinementMap::collect_inline_value_recorder_func( + RfExpr& inout) { + if (inout->get_op() == verilog_expr::voperator::AT) { + auto recorder_name = new_id() + "recorder"; auto new_node = verilog_expr::VExprAst::MakeVar(recorder_name); verilog_expr::VExprAst::VExprAstPtrVec child(inout->get_child()); @@ -97,44 +89,46 @@ void TypedVerilogRefinementMap::collect_inline_value_recorder_func(RfExpr & inou // TODO: deal with value@CLK.n if (child.at(1)->is_constant()) { // deal with value@0 - auto new_cond = verilog_expr::VExprAst::MakeBinaryAst(verilog_expr::voperator::L_EQ, - verilog_expr::VExprAst::MakeVar("__CYCLE_CNT__"), - child.at(1) - ); + auto new_cond = verilog_expr::VExprAst::MakeBinaryAst( + verilog_expr::voperator::L_EQ, + verilog_expr::VExprAst::MakeVar("__CYCLE_CNT__"), child.at(1)); tmp_value_recorder.condition = new_cond; } else tmp_value_recorder.condition = child.at(1); - value_recorder.emplace(recorder_name, tmp_value_recorder); + value_recorder.emplace(recorder_name, tmp_value_recorder); inout = new_node; // rewrite the node } } // collect_inline_value_recorder_func -void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr & inout) { - if(inout->get_op() == voperator::DELAY) { +void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr& inout) { + if (inout->get_op() == voperator::DELAY) { assert(inout->get_parameter().size() == inout->get_str_parameter().size()); assert(inout->get_child().size() == 1 || inout->get_child().size() == 2); - assert(inout->get_parameter().size() == 1 || inout->get_parameter().size() == 2); + assert(inout->get_parameter().size() == 1 || + inout->get_parameter().size() == 2); - auto delay_name = new_id()+"delay"; + auto delay_name = new_id() + "delay"; auto new_node = VExprAst::MakeVar(delay_name); - if( inout->get_parameter().size() == 1 ) { - // Single a ##n + if (inout->get_parameter().size() == 1) { + // Single a ##n int delay = inout->get_parameter().at(0); - aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), delay) ); + aux_delays.emplace(delay_name, + SignalDelay(inout->get_child().at(0), delay)); } else { // inout->get_parameter().size() == 2 // RANGE/INF a ##[n,m] / ##[n,0] 0 represents $ int delay = inout->get_parameter().at(0); int delay_upper = inout->get_parameter().at(1); - aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), delay, delay_upper) ); + aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), + delay, delay_upper)); } - if(inout->get_child().size() == 1) { + if (inout->get_child().size() == 1) { inout = new_node; } else { assert(inout->get_child().size() == 2); - auto tmp_node = VExprAst::MakeBinaryAst(voperator::L_AND, - new_node, inout->get_child().at(1) ); + auto tmp_node = VExprAst::MakeBinaryAst(voperator::L_AND, new_node, + inout->get_child().at(1)); inout = tmp_node; } } @@ -145,42 +139,47 @@ void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr & inout) { // will put in aux_delays // and value_recorder void TypedVerilogRefinementMap::CollectInlineDelayValueHolder() { - TraverseAllRfExpr([this](RfExpr & inout) -> void { this->collect_inline_delay_func(inout);} ); - TraverseAllRfExpr([this](RfExpr & inout) -> void { this->collect_inline_value_recorder_func(inout);} ); + TraverseAllRfExpr([this](RfExpr& inout) -> void { + this->collect_inline_delay_func(inout); + }); + TraverseAllRfExpr([this](RfExpr& inout) -> void { + this->collect_inline_value_recorder_func(inout); + }); } // internal datastructure like -// phase_tracker, value_recorder, customized_monitor, aux_delay -> all_var_def_types -// +// phase_tracker, value_recorder, customized_monitor, aux_delay -> +// all_var_def_types +// void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { - for (const auto & n_st : phase_tracker) { - for (const auto & var_def : n_st.second.event_alias ) { + for (const auto& n_st : phase_tracker) { + for (const auto& var_def : n_st.second.event_alias) { VarDef tmp; tmp.type = VarDef::var_type::WIRE; tmp.width = 1; all_var_def_types.emplace(var_def.first, tmp); } - for (const auto & var_def : n_st.second.var_defs ) { + for (const auto& var_def : n_st.second.var_defs) { all_var_def_types.emplace(var_def.first, var_def.second); } - for (const auto & stage : n_st.second.rules) { + for (const auto& stage : n_st.second.rules) { VarDef tmp; tmp.type = VarDef::var_type::REG; tmp.width = 1; all_var_def_types.emplace(stage.stage_name, tmp); } } - for (const auto & n_st : value_recorder) { + for (const auto& n_st : value_recorder) { VarDef tmp; - if(n_st.second.width != 0) { + if (n_st.second.width != 0) { tmp.width = n_st.second.width; tmp.type = VarDef::var_type::REG; all_var_def_types.emplace(n_st.first, tmp); - } + } } // value recorder - for (const auto & n_st : customized_monitor) { - for (const auto & var_def : n_st.second.var_defs ) { + for (const auto& n_st : customized_monitor) { + for (const auto& var_def : n_st.second.var_defs) { all_var_def_types.emplace(var_def.first, var_def.second); } } @@ -194,34 +193,37 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { all_var_def_types.emplace("decode", tmp); // these are the stage info all_var_def_types.emplace("commit", tmp); - all_var_def_types.emplace("$decode", tmp); // these are the ila.decode/ila.valid info + all_var_def_types.emplace("$decode", + tmp); // these are the ila.decode/ila.valid info all_var_def_types.emplace("$valid", tmp); } // end of add decode,commit, $decode, $valid - + } // CollectInternallyDefinedVars -void TypedVerilogRefinementMap::TraverseCondMap(SingleVarMap & inout, std::function func) { - if(inout.single_map) +void TypedVerilogRefinementMap::TraverseCondMap( + SingleVarMap& inout, std::function func) { + if (inout.single_map) TraverseRfExpr(inout.single_map, func); else - for (auto & c : inout.cond_map) { + for (auto& c : inout.cond_map) { TraverseRfExpr(c.first, func); TraverseRfExpr(c.second, func); } } // TraverseCondMap -void TypedVerilogRefinementMap::TraverseAllRfExpr(std::function func) { - for(auto & sv : ila_state_var_map) { - if(sv.second.type == IlaVarMapping::StateVarMapType::SINGLE) - TraverseRfExpr(sv.second.single_map.single_map,func); - else if(sv.second.type == IlaVarMapping::StateVarMapType::CONDITIONAL) { - for (auto & c : sv.second.single_map.cond_map) { +void TypedVerilogRefinementMap::TraverseAllRfExpr( + std::function func) { + for (auto& sv : ila_state_var_map) { + if (sv.second.type == IlaVarMapping::StateVarMapType::SINGLE) + TraverseRfExpr(sv.second.single_map.single_map, func); + else if (sv.second.type == IlaVarMapping::StateVarMapType::CONDITIONAL) { + for (auto& c : sv.second.single_map.cond_map) { TraverseRfExpr(c.first, func); TraverseRfExpr(c.second, func); } } else { // extern map - for (auto & m : sv.second.externmem_map) { + for (auto& m : sv.second.externmem_map) { TraverseCondMap(m.raddr_map, func); TraverseCondMap(m.rdata_map, func); TraverseCondMap(m.ren_map, func); @@ -232,132 +234,141 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr(std::functionis_constant()) +bool _compute_const(const RfExpr& in, unsigned& out) { + if (!in->is_constant()) return false; - std::shared_ptr cst_ast_ptr = std::dynamic_pointer_cast(in); - if(cst_ast_ptr == nullptr) + std::shared_ptr cst_ast_ptr = + std::dynamic_pointer_cast(in); + if (cst_ast_ptr == nullptr) return false; auto bws = cst_ast_ptr->get_constant(); auto base = std::get<0>(bws); - if(base == 0) + if (base == 0) base = 10; // auto width = std::get<1>(bws); out = StrToLong(std::get<2>(bws), base); - return true; + return true; } - // this does not rely on type annotation // relies on TypeInferTravserRfExpr // and therefore, all_var_def_types void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { - for(auto & name_delay_pair: aux_delays) { - if(name_delay_pair.second.width == 0) { + for (auto& name_delay_pair : aux_delays) { + if (name_delay_pair.second.width == 0) { auto tp = TypeInferTravserRfExpr(name_delay_pair.second.signal); - ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; - ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_delay_pair.second.signal->to_verilog(); + ILA_ERROR_IF(tp.is_array()) + << "Currently does not support to delay a memory variable"; + ILA_ERROR_IF(tp.is_unknown()) + << "Type inference failed on: " + << name_delay_pair.second.signal->to_verilog(); name_delay_pair.second.width = tp.unified_width(); // replendish all_var_def_types VarDef internal_var_def; - internal_var_def.width = tp.unified_width(); + internal_var_def.width = tp.unified_width(); internal_var_def.type = VarDef::var_type::REG; all_var_def_types.emplace(name_delay_pair.first, internal_var_def); } } - for (auto & name_vr : value_recorder) { + for (auto& name_vr : value_recorder) { if (name_vr.second.width == 0) { auto tp = TypeInferTravserRfExpr(name_vr.second.value); - ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; - ILA_ERROR_IF(tp.is_unknown()) << "Type inference failed on: " << name_vr.second.value->to_verilog(); + ILA_ERROR_IF(tp.is_array()) + << "Currently does not support to delay a memory variable"; + ILA_ERROR_IF(tp.is_unknown()) + << "Type inference failed on: " << name_vr.second.value->to_verilog(); name_vr.second.width = tp.unified_width(); // replendish all_var_def_types VarDef internal_var_def; - internal_var_def.width = tp.unified_width(); + internal_var_def.width = tp.unified_width(); internal_var_def.type = VarDef::var_type::REG; all_var_def_types.emplace(name_vr.first, internal_var_def); } - } // replendish internal defined vars + } // replendish internal defined vars } // ComputeDelayValueHolderWidth - // relies on typechecker and all_var_def_types -RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in) { +RfMapVarType +TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { - if(in->is_constant()) { - auto c = std::dynamic_pointer_cast(in)->get_constant(); + if (in->is_constant()) { + auto c = std::dynamic_pointer_cast(in) + ->get_constant(); return RfMapVarType(std::get<1>(c)); } else if (in->is_var()) { - auto n = std::dynamic_pointer_cast(in)->get_name(); + auto n = + std::dynamic_pointer_cast(in)->get_name(); auto pos_def_var = all_var_def_types.find(n.first); - if(n.second) { // is a special name + if (n.second) { // is a special name // check special name first if (pos_def_var != all_var_def_types.end()) { - ILA_WARN_IF(pos_def_var->second.width == 0) << "Using width of not yet" - << " determined var " << n.first; + ILA_WARN_IF(pos_def_var->second.width == 0) + << "Using width of not yet" + << " determined var " << n.first; return RfMapVarType(pos_def_var->second.width); } @@ -372,67 +383,63 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in if (!rtl_ila_vartype.type.is_unknown()) return rtl_ila_vartype.type; if (pos_def_var != all_var_def_types.end()) { - ILA_WARN_IF(pos_def_var->second.width == 0) << "Using width of not yet" - << " determined var " << n.first; - return RfMapVarType(pos_def_var->second.width); + ILA_WARN_IF(pos_def_var->second.width == 0) + << "Using width of not yet" + << " determined var " << n.first; + return RfMapVarType(pos_def_var->second.width); + } + + } // if # ... # else not + return RfMapVarType(); // unknown type + } else { // has op + if (in->get_op() == verilog_expr::voperator::STAR || + in->get_op() == verilog_expr::voperator::PLUS || + in->get_op() == verilog_expr::voperator::MINUS || + in->get_op() == verilog_expr::voperator::DIV || + in->get_op() == verilog_expr::voperator::POW || + in->get_op() == verilog_expr::voperator::MOD || + in->get_op() == verilog_expr::voperator::B_NEG || + in->get_op() == verilog_expr::voperator::B_AND || + in->get_op() == verilog_expr::voperator::B_OR || + in->get_op() == verilog_expr::voperator::B_XOR || + in->get_op() == verilog_expr::voperator::B_NAND || + in->get_op() == verilog_expr::voperator::B_NOR) { + // the max of the args + unsigned nchild = in->get_child_cnt(); + unsigned maxw = 0; + for (size_t idx = 0; idx < nchild; idx++) { + RfMapVarType t = TypeInferTravserRfExpr(in->child(idx)); + if (t.is_bv()) + maxw = std::max(maxw, t.unified_width()); } - - } // if # ... # else not - return RfMapVarType(); // unknown type - } else { // has op - if(in->get_op() == verilog_expr::voperator::STAR || - in->get_op() == verilog_expr::voperator::PLUS || - in->get_op() == verilog_expr::voperator::MINUS || - in->get_op() == verilog_expr::voperator::DIV || - in->get_op() == verilog_expr::voperator::POW || - in->get_op() == verilog_expr::voperator::MOD || - in->get_op() == verilog_expr::voperator::B_NEG || - in->get_op() == verilog_expr::voperator::B_AND || - in->get_op() == verilog_expr::voperator::B_OR || - in->get_op() == verilog_expr::voperator::B_XOR || - in->get_op() == verilog_expr::voperator::B_NAND || - in->get_op() == verilog_expr::voperator::B_NOR - ) { - // the max of the args - unsigned nchild = in->get_child_cnt(); - unsigned maxw = 0; - for(size_t idx = 0; idx < nchild; idx ++) { - RfMapVarType t = TypeInferTravserRfExpr( in->child(idx) ); - if(t.is_bv()) - maxw = std::max(maxw, t.unified_width()); - } - return RfMapVarType(maxw); - } else if ( - in->get_op() == verilog_expr::voperator::ASL || - in->get_op() == verilog_expr::voperator::ASR || - in->get_op() == verilog_expr::voperator::LSL || - in->get_op() == verilog_expr::voperator::LSR || - in->get_op() == verilog_expr::voperator::AT - ) { // the left type - assert( in->get_child_cnt() == 2); - return TypeInferTravserRfExpr(in->child(0)); - } else if ( in->get_op() == verilog_expr::voperator::DELAY) { + return RfMapVarType(maxw); + } else if (in->get_op() == verilog_expr::voperator::ASL || + in->get_op() == verilog_expr::voperator::ASR || + in->get_op() == verilog_expr::voperator::LSL || + in->get_op() == verilog_expr::voperator::LSR || + in->get_op() == verilog_expr::voperator::AT) { // the left type + assert(in->get_child_cnt() == 2); + return TypeInferTravserRfExpr(in->child(0)); + } else if (in->get_op() == verilog_expr::voperator::DELAY) { // arg 1: width of first // arg 2: width is 1 !!! - assert(in->get_child_cnt() == 1 || in->get_child_cnt() == 2); + assert(in->get_child_cnt() == 1 || in->get_child_cnt() == 2); if (in->get_child_cnt() == 2) return RfMapVarType(1); - + // set return type to be the same as the first one return TypeInferTravserRfExpr(in->child(0)); - } else if ( - in->get_op() == verilog_expr::voperator::GTE || - in->get_op() == verilog_expr::voperator::LTE || - in->get_op() == verilog_expr::voperator::GT || - in->get_op() == verilog_expr::voperator::LT || - in->get_op() == verilog_expr::voperator::C_EQ || - in->get_op() == verilog_expr::voperator::L_EQ || - in->get_op() == verilog_expr::voperator::C_NEQ || - in->get_op() == verilog_expr::voperator::L_NEQ || - in->get_op() == verilog_expr::voperator::L_NEG || - in->get_op() == verilog_expr::voperator::L_AND || - in->get_op() == verilog_expr::voperator::L_OR - ) { + } else if (in->get_op() == verilog_expr::voperator::GTE || + in->get_op() == verilog_expr::voperator::LTE || + in->get_op() == verilog_expr::voperator::GT || + in->get_op() == verilog_expr::voperator::LT || + in->get_op() == verilog_expr::voperator::C_EQ || + in->get_op() == verilog_expr::voperator::L_EQ || + in->get_op() == verilog_expr::voperator::C_NEQ || + in->get_op() == verilog_expr::voperator::L_NEQ || + in->get_op() == verilog_expr::voperator::L_NEG || + in->get_op() == verilog_expr::voperator::L_AND || + in->get_op() == verilog_expr::voperator::L_OR) { return RfMapVarType(1); } else if (in->get_op() == verilog_expr::voperator::INDEX) { RfMapVarType child_type = TypeInferTravserRfExpr(in->child(0)); @@ -442,9 +449,8 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in if (child_type.is_bv()) return RfMapVarType(1); return RfMapVarType(); // UNKNOWN type - } else if ( - in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || - in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { + } else if (in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || + in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { assert(in->get_child().size() == 3); unsigned diff; bool succ = _compute_const(in->child(2), diff /*ref*/); @@ -454,173 +460,163 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr & in return RfMapVarType(); } else if (in->get_op() == verilog_expr::voperator::RANGE_INDEX) { assert(in->get_child_cnt() == 3); - unsigned l,r; - + unsigned l, r; + bool succ = _compute_const(in->child(1), l /*ref*/); succ = succ && _compute_const(in->child(2), r /*ref*/); - if(!succ) + if (!succ) return RfMapVarType(); // TODO: check width! - return RfMapVarType(std::max(l,r)-std::min(l,r) + 1); + return RfMapVarType(std::max(l, r) - std::min(l, r) + 1); } else if (in->get_op() == verilog_expr::voperator::STORE_OP) { // TODO: check width! // actually not implemented return TypeInferTravserRfExpr(in->child(0)); } else if (in->get_op() == verilog_expr::voperator::TERNARY) { - auto left = TypeInferTravserRfExpr(in->child(1)); - auto right = TypeInferTravserRfExpr(in->child(2)); - if(left.is_array() || right.is_array()) + auto left = TypeInferTravserRfExpr(in->child(1)); + auto right = TypeInferTravserRfExpr(in->child(2)); + if (left.is_array() || right.is_array()) return left; // TODO: check compatibility - return RfMapVarType(std::max(left.unified_width(), right.unified_width())); + return RfMapVarType( + std::max(left.unified_width(), right.unified_width())); } else if (in->get_op() == verilog_expr::voperator::FUNCTION_APP) { return RfMapVarType(); - } else if(in->get_op() == verilog_expr::voperator::CONCAT) { + } else if (in->get_op() == verilog_expr::voperator::CONCAT) { unsigned nchild = in->get_child_cnt(); unsigned sumw = 0; - for(size_t idx = 0; idx < nchild; idx ++) { - RfMapVarType t = TypeInferTravserRfExpr( in->child(idx) ); - if(t.is_bv()) + for (size_t idx = 0; idx < nchild; idx++) { + RfMapVarType t = TypeInferTravserRfExpr(in->child(idx)); + if (t.is_bv()) sumw += t.unified_width(); else return RfMapVarType(); // cannot decide } return RfMapVarType(sumw); } else if (in->get_op() == verilog_expr::voperator::REPEAT) { - assert( in->get_child_cnt() == 2 ); + assert(in->get_child_cnt() == 2); unsigned ntimes; - if(!_compute_const(in->child(0), ntimes)) + if (!_compute_const(in->child(0), ntimes)) return RfMapVarType(); auto tp = TypeInferTravserRfExpr(in->child(1)); - return RfMapVarType(tp.unified_width()*ntimes); + return RfMapVarType(tp.unified_width() * ntimes); } - ILA_ASSERT(false) << "BUG: Operator " << int(in->get_op()) << " is not handled"; + ILA_ASSERT(false) << "BUG: Operator " << int(in->get_op()) + << " is not handled"; } // end of else has op return RfMapVarType(); } // TypeInferTravserRfExpr - // -------------------------------------------------------- // RfExprAstUtility // -------------------------------------------------------- - -RfVarTypeOrig RfExprAstUtility::GetType(const RfExpr & in) { +RfVarTypeOrig RfExprAstUtility::GetType(const RfExpr& in) { auto anno = in->get_annotation(); ILA_NOT_NULL(anno); return *anno; } -void RfExprAstUtility::GetVars(const RfExpr & in, - std::unordered_map & vars_out) -{ +void RfExprAstUtility::GetVars( + const RfExpr& in, std::unordered_map& vars_out) { // bfs walk - std::vector > stack; + std::vector> stack; stack.push_back(std::make_pair(in, false)); - while(!stack.empty()) { - auto & back = stack.back(); + while (!stack.empty()) { + auto& back = stack.back(); auto backvar = back.first; - if(back.second) { + if (back.second) { stack.pop_back(); continue; } // back.second == false back.second = true; - for(const auto & c : backvar->get_child()) + for (const auto& c : backvar->get_child()) stack.push_back(std::make_pair(c, false)); - if(backvar->is_var()) { + if (backvar->is_var()) { ILA_ASSERT(backvar->get_child().size() == 0); - verilog_expr::VExprAstVar::VExprAstVarPtr varptr = - std::dynamic_pointer_cast(backvar); + verilog_expr::VExprAstVar::VExprAstVarPtr varptr = + std::dynamic_pointer_cast(backvar); ILA_NOT_NULL(varptr); vars_out.emplace(varptr->get_name().first, varptr); } } // end while (stack is not empty) } // end of GetVars - -bool RfExprAstUtility::HasArrayVar( - const RfExpr & in, std::map & array_var) -{ - if(in->is_var()) { +bool RfExprAstUtility::HasArrayVar(const RfExpr& in, + std::map& array_var) { + if (in->is_var()) { auto anno = in->get_annotation(); ILA_NOT_NULL(anno); auto memvar = std::dynamic_pointer_cast(in); ILA_NOT_NULL(memvar); - if(anno->type.is_array()) { + if (anno->type.is_array()) { array_var.emplace(std::get<0>(memvar->get_name()), memvar); return true; } return false; } else if (in->is_constant()) { return false; - } + } bool has_array = false; - for (size_t idx = 0; idx < in->get_child_cnt(); idx ++) { + for (size_t idx = 0; idx < in->get_child_cnt(); idx++) { has_array = has_array || HasArrayVar(in->child(idx), array_var); } return has_array; } -void RfExprAstUtility::RfMapNoNullNode(const RfExpr & in) { +void RfExprAstUtility::RfMapNoNullNode(const RfExpr& in) { ILA_NOT_NULL(in); size_t cnt = in->get_child_cnt(); - for(size_t idx = 0; idx < cnt; ++idx) + for (size_t idx = 0; idx < cnt; ++idx) RfMapNoNullNode(in->child(idx)); } -void RfExprAstUtility::TraverseRfExpr(RfExpr & inout, std::function func) { +void RfExprAstUtility::TraverseRfExpr(RfExpr& inout, + std::function func) { // DFS -- Note: we need to call func on the parent's child // and make sure it runs the first std::vector> parent_stack; - parent_stack.push_back(std::make_pair(inout,0U)); - while(!parent_stack.empty()) { - auto & lastlv = parent_stack.back(); + parent_stack.push_back(std::make_pair(inout, 0U)); + while (!parent_stack.empty()) { + auto& lastlv = parent_stack.back(); auto cnt = lastlv.first->get_child_cnt(); - auto & idx = lastlv.second; - if(idx >= cnt) { + auto& idx = lastlv.second; + if (idx >= cnt) { parent_stack.pop_back(); - if(!parent_stack.empty()) { - // refer to parent - func( parent_stack.back().first->child( parent_stack.back().second ) ); - ++ parent_stack.back().second; + if (!parent_stack.empty()) { + // refer to parent + func(parent_stack.back().first->child(parent_stack.back().second)); + ++parent_stack.back().second; } continue; } else { // enter c[idx] - if(lastlv.first->get_child_cnt() == 0) { - func ( lastlv.first->child(idx) ); + if (lastlv.first->get_child_cnt() == 0) { + func(lastlv.first->child(idx)); ++idx; } else { - parent_stack.push_back( std::make_pair(lastlv.first->child(idx), 0U )); + parent_stack.push_back(std::make_pair(lastlv.first->child(idx), 0U)); } } } // end of while func(inout); } // TraverseRfExpr - -bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr & in) { +bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr& in) { std::set boolean_op = { - verilog_expr::voperator::GTE, - verilog_expr::voperator::LTE, - verilog_expr::voperator::GT, - verilog_expr::voperator::LT, - verilog_expr::voperator::C_EQ, - verilog_expr::voperator::L_EQ, - verilog_expr::voperator::C_NEQ, - verilog_expr::voperator::L_NEQ, - verilog_expr::voperator::L_NEG, - verilog_expr::voperator::L_AND, - verilog_expr::voperator::L_OR - }; - - if(in->is_constant() || in->is_var()) + verilog_expr::voperator::GTE, verilog_expr::voperator::LTE, + verilog_expr::voperator::GT, verilog_expr::voperator::LT, + verilog_expr::voperator::C_EQ, verilog_expr::voperator::L_EQ, + verilog_expr::voperator::C_NEQ, verilog_expr::voperator::L_NEQ, + verilog_expr::voperator::L_NEG, verilog_expr::voperator::L_AND, + verilog_expr::voperator::L_OR}; + + if (in->is_constant() || in->is_var()) return false; auto op = in->get_op(); return (boolean_op.find(op) != boolean_op.end()); } - // -------------------------------------------------------- // TypeAnalysisUtility // -------------------------------------------------------- @@ -630,53 +626,54 @@ bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr & in) { // 1. no var replacement (__ILA_I_, __ILA_SO_, __DOT__), array[idx] // 2. no special name handling // 3. this is used only in unit test -void TypeAnalysisUtility::AnnotateType(const RfExpr & inout) { +void TypeAnalysisUtility::AnnotateType(const RfExpr& inout) { auto tp_annotate = inout->get_annotation(); - - if(inout->is_var()) { - auto ptr = std::dynamic_pointer_cast (inout); + + if (inout->is_var()) { + auto ptr = std::dynamic_pointer_cast(inout); ILA_CHECK(tp_annotate != nullptr && !tp_annotate->type.is_unknown()) - << ptr->get_name().first << " has no type annotation" ; + << ptr->get_name().first << " has no type annotation"; } else if (inout->is_constant()) { - if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { + if (tp_annotate == nullptr || tp_annotate->type.is_unknown()) { RfVarTypeOrig tp; - auto cptr = std::dynamic_pointer_cast(inout); + auto cptr = + std::dynamic_pointer_cast(inout); ILA_NOT_NULL(cptr); - tp.type = RfMapVarType(std::get<1>(cptr->get_constant())); // base, width,... + tp.type = + RfMapVarType(std::get<1>(cptr->get_constant())); // base, width,... inout->set_annotation(std::make_shared(tp)); - } // end if no annotation + } // end if no annotation } else { // op - for (size_t idx = 0 ; idx < inout->get_child_cnt(); ++ idx) + for (size_t idx = 0; idx < inout->get_child_cnt(); ++idx) AnnotateType(inout->child(idx)); infer_type_based_on_op_child(inout); // for each child } // end if-else- op } // TypeAnalysisUtility::AnnotateType -void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr & inout) { - assert( - inout->get_op() != verilog_expr::voperator::MK_CONST && - inout->get_op() != verilog_expr::voperator::MK_VAR ); - - if(inout->get_op() == verilog_expr::voperator::STAR || - inout->get_op() == verilog_expr::voperator::PLUS || - inout->get_op() == verilog_expr::voperator::MINUS || - inout->get_op() == verilog_expr::voperator::DIV || - inout->get_op() == verilog_expr::voperator::POW || - inout->get_op() == verilog_expr::voperator::MOD || - inout->get_op() == verilog_expr::voperator::B_NEG || - inout->get_op() == verilog_expr::voperator::B_AND || - inout->get_op() == verilog_expr::voperator::B_OR || - inout->get_op() == verilog_expr::voperator::B_XOR || - inout->get_op() == verilog_expr::voperator::B_NAND || - inout->get_op() == verilog_expr::voperator::B_NOR - ) { +void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { + assert(inout->get_op() != verilog_expr::voperator::MK_CONST && + inout->get_op() != verilog_expr::voperator::MK_VAR); + + if (inout->get_op() == verilog_expr::voperator::STAR || + inout->get_op() == verilog_expr::voperator::PLUS || + inout->get_op() == verilog_expr::voperator::MINUS || + inout->get_op() == verilog_expr::voperator::DIV || + inout->get_op() == verilog_expr::voperator::POW || + inout->get_op() == verilog_expr::voperator::MOD || + inout->get_op() == verilog_expr::voperator::B_NEG || + inout->get_op() == verilog_expr::voperator::B_AND || + inout->get_op() == verilog_expr::voperator::B_OR || + inout->get_op() == verilog_expr::voperator::B_XOR || + inout->get_op() == verilog_expr::voperator::B_NAND || + inout->get_op() == verilog_expr::voperator::B_NOR) { // the max of the args unsigned nchild = inout->get_child_cnt(); unsigned maxw = 0; - for(size_t idx = 0; idx < nchild; idx ++) { - RfMapVarType t = inout->child(idx)->get_annotation()->type; - if(t.is_bv()) + for (size_t idx = 0; idx < nchild; idx++) { + RfMapVarType t = + inout->child(idx)->get_annotation()->type; + if (t.is_bv()) maxw = std::max(maxw, t.unified_width()); } auto new_annotation = std::make_shared(); @@ -685,142 +682,136 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr & inout) { return; } - if ( - inout->get_op() == verilog_expr::voperator::ASL || - inout->get_op() == verilog_expr::voperator::ASR || - inout->get_op() == verilog_expr::voperator::LSL || - inout->get_op() == verilog_expr::voperator::LSR || - inout->get_op() == verilog_expr::voperator::AT - ) { // the left type - assert( inout->get_child_cnt() == 2); + if (inout->get_op() == verilog_expr::voperator::ASL || + inout->get_op() == verilog_expr::voperator::ASR || + inout->get_op() == verilog_expr::voperator::LSL || + inout->get_op() == verilog_expr::voperator::LSR || + inout->get_op() == verilog_expr::voperator::AT) { // the left type + assert(inout->get_child_cnt() == 2); inout->set_annotation(inout->child(0)->get_annotation()); return; - } else if ( inout->get_op() == verilog_expr::voperator::DELAY) { - // arg 1: width of first - // arg 2: width is 1 !!! - assert(inout->get_child_cnt() == 1 || inout->get_child_cnt() == 2); - if (inout->get_child_cnt() == 2) { - auto new_annotation = std::make_shared(); - new_annotation->type = RfMapVarType(1); - inout->set_annotation(new_annotation); - return ; - } - - // set return type to be the same as the first one - inout->set_annotation(inout->child(0)->get_annotation()); - return; - - } else if ( - inout->get_op() == verilog_expr::voperator::GTE || - inout->get_op() == verilog_expr::voperator::LTE || - inout->get_op() == verilog_expr::voperator::GT || - inout->get_op() == verilog_expr::voperator::LT || - inout->get_op() == verilog_expr::voperator::C_EQ || - inout->get_op() == verilog_expr::voperator::L_EQ || - inout->get_op() == verilog_expr::voperator::C_NEQ || - inout->get_op() == verilog_expr::voperator::L_NEQ || - inout->get_op() == verilog_expr::voperator::L_NEG || - inout->get_op() == verilog_expr::voperator::L_AND || - inout->get_op() == verilog_expr::voperator::L_OR - ) { + } else if (inout->get_op() == verilog_expr::voperator::DELAY) { + // arg 1: width of first + // arg 2: width is 1 !!! + assert(inout->get_child_cnt() == 1 || inout->get_child_cnt() == 2); + if (inout->get_child_cnt() == 2) { auto new_annotation = std::make_shared(); new_annotation->type = RfMapVarType(1); inout->set_annotation(new_annotation); - return ; - } else if (inout->get_op() == verilog_expr::voperator::INDEX) { - RfMapVarType child_type = inout->child(0)->get_annotation()->type; - - auto new_annotation = std::make_shared(); - if (child_type.is_array()) - new_annotation->type = RfMapVarType(child_type.unified_width()); - // TODO: check index within ? - else - new_annotation->type = RfMapVarType(1); - inout->set_annotation(new_annotation); return; - } else if ( - inout->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || - inout->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { - assert(inout->get_child().size() == 3); - unsigned diff = 0; - bool succ = _compute_const(inout->child(2), diff /*ref*/); - ILA_ASSERT(succ); + } - auto new_annotation = std::make_shared(); - new_annotation->type = RfMapVarType(diff); - inout->set_annotation(new_annotation); + // set return type to be the same as the first one + inout->set_annotation(inout->child(0)->get_annotation()); + return; - // TODO: check index within ? - return; - - } else if (inout->get_op() == verilog_expr::voperator::RANGE_INDEX) { - assert(inout->get_child_cnt() == 3); - unsigned l,r; - - bool succ = _compute_const(inout->child(1), l /*ref*/); - succ = succ && _compute_const(inout->child(2), r /*ref*/); - ILA_ASSERT(succ); + } else if (inout->get_op() == verilog_expr::voperator::GTE || + inout->get_op() == verilog_expr::voperator::LTE || + inout->get_op() == verilog_expr::voperator::GT || + inout->get_op() == verilog_expr::voperator::LT || + inout->get_op() == verilog_expr::voperator::C_EQ || + inout->get_op() == verilog_expr::voperator::L_EQ || + inout->get_op() == verilog_expr::voperator::C_NEQ || + inout->get_op() == verilog_expr::voperator::L_NEQ || + inout->get_op() == verilog_expr::voperator::L_NEG || + inout->get_op() == verilog_expr::voperator::L_AND || + inout->get_op() == verilog_expr::voperator::L_OR) { + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(1); + inout->set_annotation(new_annotation); + return; + } else if (inout->get_op() == verilog_expr::voperator::INDEX) { + RfMapVarType child_type = + inout->child(0)->get_annotation()->type; - auto new_annotation = std::make_shared(); - new_annotation->type = RfMapVarType(std::max(l,r)-std::min(l,r) + 1); - inout->set_annotation(new_annotation); - - return ; - } else if (inout->get_op() == verilog_expr::voperator::STORE_OP) { - inout->set_annotation(inout->child(0)->get_annotation()); - return; + auto new_annotation = std::make_shared(); + if (child_type.is_array()) + new_annotation->type = RfMapVarType(child_type.unified_width()); + // TODO: check index within ? + else + new_annotation->type = RfMapVarType(1); + inout->set_annotation(new_annotation); + return; + } else if (inout->get_op() == verilog_expr::voperator::IDX_PRT_SEL_PLUS || + inout->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { + assert(inout->get_child().size() == 3); + unsigned diff = 0; + bool succ = _compute_const(inout->child(2), diff /*ref*/); + ILA_ASSERT(succ); - } else if (inout->get_op() == verilog_expr::voperator::TERNARY) { - inout->set_annotation(inout->child(1)->get_annotation()); - return; - } else if (inout->get_op() == verilog_expr::voperator::FUNCTION_APP) { - ILA_ASSERT(false); - auto new_annotation = std::make_shared(); - new_annotation->type = RfMapVarType(0); - inout->set_annotation(new_annotation); - return; - } else if(inout->get_op() == verilog_expr::voperator::CONCAT) { - unsigned nchild = inout->get_child_cnt(); - unsigned sumw = 0; - for(size_t idx = 0; idx < nchild; idx ++) { - RfMapVarType t = ( inout->child(idx)->get_annotation()->type ); - sumw += t.unified_width(); - } - auto new_annotation = std::make_shared(); - new_annotation->type = RfMapVarType(sumw); - inout->set_annotation(new_annotation); - return; - } else if (inout->get_op() == verilog_expr::voperator::REPEAT) { - assert( inout->get_child_cnt() == 2 ); - unsigned ntimes; - if(!_compute_const(inout->child(0), ntimes)) - ILA_ASSERT(false); - auto tp = ( inout->child(1)->get_annotation()->type ); + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(diff); + inout->set_annotation(new_annotation); - auto new_annotation = std::make_shared(); - new_annotation->type = RfMapVarType(tp.unified_width()*ntimes); - inout->set_annotation(new_annotation); + // TODO: check index within ? + return; - return ; - } - ILA_ASSERT(false) << "BUG: Operator " << int(inout->get_op()) << " is not handled"; + } else if (inout->get_op() == verilog_expr::voperator::RANGE_INDEX) { + assert(inout->get_child_cnt() == 3); + unsigned l, r; + + bool succ = _compute_const(inout->child(1), l /*ref*/); + succ = succ && _compute_const(inout->child(2), r /*ref*/); + ILA_ASSERT(succ); + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(std::max(l, r) - std::min(l, r) + 1); + inout->set_annotation(new_annotation); + + return; + } else if (inout->get_op() == verilog_expr::voperator::STORE_OP) { + inout->set_annotation(inout->child(0)->get_annotation()); + return; + + } else if (inout->get_op() == verilog_expr::voperator::TERNARY) { + inout->set_annotation(inout->child(1)->get_annotation()); + return; + } else if (inout->get_op() == verilog_expr::voperator::FUNCTION_APP) { + ILA_ASSERT(false); auto new_annotation = std::make_shared(); new_annotation->type = RfMapVarType(0); inout->set_annotation(new_annotation); -} // infer_type_op + return; + } else if (inout->get_op() == verilog_expr::voperator::CONCAT) { + unsigned nchild = inout->get_child_cnt(); + unsigned sumw = 0; + for (size_t idx = 0; idx < nchild; idx++) { + RfMapVarType t = + (inout->child(idx)->get_annotation()->type); + sumw += t.unified_width(); + } + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(sumw); + inout->set_annotation(new_annotation); + return; + } else if (inout->get_op() == verilog_expr::voperator::REPEAT) { + assert(inout->get_child_cnt() == 2); + unsigned ntimes; + if (!_compute_const(inout->child(0), ntimes)) + ILA_ASSERT(false); + auto tp = (inout->child(1)->get_annotation()->type); + + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(tp.unified_width() * ntimes); + inout->set_annotation(new_annotation); + return; + } + ILA_ASSERT(false) << "BUG: Operator " << int(inout->get_op()) + << " is not handled"; + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(0); + inout->set_annotation(new_annotation); +} // infer_type_op -VarReplacement:: VarReplacement(const RfExpr & o, const RfExpr & n) : - origvar(o), newvar(n) -{ +VarReplacement::VarReplacement(const RfExpr& o, const RfExpr& n) + : origvar(o), newvar(n) { auto annotation_ptr = newvar->get_annotation(); ILA_NOT_NULL(annotation_ptr); - ILA_CHECK(!annotation_ptr->type.is_unknown()) << - "new var is not typed: " << newvar->to_verilog() ; + ILA_CHECK(!annotation_ptr->type.is_unknown()) + << "new var is not typed: " << newvar->to_verilog(); } } // namespace rfmap } // namespace ilang - diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index d01167419..d343fa7ef 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -2,14 +2,14 @@ /// First pass : JSON -> rfmap object #include +#include #include #include -#include #include -#include "nlohmann/json.hpp" #include "interpreter.h" +#include "nlohmann/json.hpp" namespace ilang { namespace rfmap { @@ -71,28 +71,25 @@ static bool load_json(const std::string& fname, nlohmann::json& j) { return true; } // load_json - - static bool ParseRfExprErrFlag = false; - -RfExpr VerilogRefinementMap::ParseRfExprFromString(const std::string & in) { +RfExpr VerilogRefinementMap::ParseRfExprFromString(const std::string& in) { Vexp::Interpreter intp; std::stringstream ss; ss << in; intp.switchInputStream(&ss); - try{ + try { intp.parse(); - } catch (verilog_expr::VexpException &e) { + } catch (verilog_expr::VexpException& e) { return nullptr; } - if(intp.HasError()) + if (intp.HasError()) return nullptr; return intp.GetAstRoot(); } -RfExpr ParseRfMapExpr(const std::string & in) { +RfExpr ParseRfMapExpr(const std::string& in) { // TODO auto ret = VerilogRefinementMap::ParseRfExprFromString(in); ILA_ERROR_IF(ret == nullptr) << "Parsing string: `" << in << "` failed."; @@ -101,20 +98,22 @@ RfExpr ParseRfMapExpr(const std::string & in) { return ret; } -RfExpr ParseRfMapExprJson(nlohmann::json & in) { +RfExpr ParseRfMapExprJson(nlohmann::json& in) { return ParseRfMapExpr(in.get()); } -bool JsonRfmapParseCond(SingleVarMap & cond_map, nlohmann::json & json_array) { +bool JsonRfmapParseCond(SingleVarMap& cond_map, nlohmann::json& json_array) { assert(json_array.is_array()); bool succ = true; - for (const auto & idx_array_pair : json_array.items()) { - succ = succ && idx_array_pair.value().is_array() && idx_array_pair.value().size() == 2; - if (!idx_array_pair.value().is_array() || idx_array_pair.value().size() != 2) + for (const auto& idx_array_pair : json_array.items()) { + succ = succ && idx_array_pair.value().is_array() && + idx_array_pair.value().size() == 2; + if (!idx_array_pair.value().is_array() || + idx_array_pair.value().size() != 2) continue; RfExpr cond, mapping; - for (const auto & index_map_pair : idx_array_pair.value().items()) { + for (const auto& index_map_pair : idx_array_pair.value().items()) { if (index_map_pair.key() == "0") { cond = ParseRfMapExprJson(index_map_pair.value()); } else if (index_map_pair.key() == "1") { @@ -122,72 +121,82 @@ bool JsonRfmapParseCond(SingleVarMap & cond_map, nlohmann::json & json_array) { } } assert(cond.get() != nullptr && mapping.get() != nullptr); - cond_map.cond_map.push_back(std::make_pair(cond,mapping)); + cond_map.cond_map.push_back(std::make_pair(cond, mapping)); } // for each array_element return succ; } // JsonRfmapParseCond -bool JsonRfmapParseSingleOrCond(SingleVarMap & sc_map, nlohmann::json & json_single_or_array) { - if(json_single_or_array.is_array()) +bool JsonRfmapParseSingleOrCond(SingleVarMap& sc_map, + nlohmann::json& json_single_or_array) { + if (json_single_or_array.is_array()) return JsonRfmapParseCond(sc_map, json_single_or_array); assert(json_single_or_array.is_string()); sc_map.single_map = ParseRfMapExprJson(json_single_or_array); return sc_map.single_map != nullptr; } -bool JsonRfmapParseMem(ExternalMemPortMap & mem_rfmap , nlohmann::json & json_obj) { +bool JsonRfmapParseMem(ExternalMemPortMap& mem_rfmap, + nlohmann::json& json_obj) { assert(json_obj.is_object()); bool succ = true; if (json_obj.contains("wen")) - succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.wen_map, json_obj["wen"]); + succ = + succ && JsonRfmapParseSingleOrCond(mem_rfmap.wen_map, json_obj["wen"]); if (json_obj.contains("waddr")) - succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.waddr_map, json_obj["waddr"]); + succ = succ && + JsonRfmapParseSingleOrCond(mem_rfmap.waddr_map, json_obj["waddr"]); if (json_obj.contains("wdata")) - succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.wdata_map, json_obj["wdata"]); + succ = succ && + JsonRfmapParseSingleOrCond(mem_rfmap.wdata_map, json_obj["wdata"]); if (json_obj.contains("ren")) - succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.ren_map, json_obj["ren"]); + succ = + succ && JsonRfmapParseSingleOrCond(mem_rfmap.ren_map, json_obj["ren"]); if (json_obj.contains("raddr")) - succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.raddr_map, json_obj["raddr"]); + succ = succ && + JsonRfmapParseSingleOrCond(mem_rfmap.raddr_map, json_obj["raddr"]); if (json_obj.contains("rdata")) - succ = succ && JsonRfmapParseSingleOrCond(mem_rfmap.rdata_map, json_obj["rdata"]); + succ = succ && + JsonRfmapParseSingleOrCond(mem_rfmap.rdata_map, json_obj["rdata"]); mem_rfmap.rport_mapped = json_obj.contains("ren"); mem_rfmap.wport_mapped = json_obj.contains("wen"); - if(mem_rfmap.rport_mapped) + if (mem_rfmap.rport_mapped) succ = succ && json_obj.contains("raddr") && json_obj.contains("rdata"); - if(mem_rfmap.wport_mapped) + if (mem_rfmap.wport_mapped) succ = succ && json_obj.contains("waddr") && json_obj.contains("wdata"); return (succ && (json_obj.contains("ren") || json_obj.contains("wen"))); } // JsonRfmapParseMem -char inline to_space(char in) { return ( (in == '-' || in == '_') ? ' ' : in); } +char inline to_space(char in) { return ((in == '-' || in == '_') ? ' ' : in); } -bool SectionNameRelaxedMatch(const std::string & in1, const std::string & in2) { - if(in1.length() != in2.length()) - return false; - for (size_t idx = 0; idx < in1.length(); ++ idx) { - if ( tolower(in1.at(idx)) != tolower(in2.at(idx)) && - (to_space(in1.at(idx)) != to_space(in2.at(idx))) ) +bool SectionNameRelaxedMatch(const std::string& in1, const std::string& in2) { + if (in1.length() != in2.length()) return false; + for (size_t idx = 0; idx < in1.length(); ++idx) { + if (tolower(in1.at(idx)) != tolower(in2.at(idx)) && + (to_space(in1.at(idx)) != to_space(in2.at(idx)))) + return false; } return true; } // SectionNameRelaxedMatch -nlohmann::json * GetJsonSection(nlohmann::json & in, const std::set & sec_names, bool allow_dup = false) { - nlohmann::json * ret = NULL; +nlohmann::json* GetJsonSection(nlohmann::json& in, + const std::set& sec_names, + bool allow_dup = false) { + nlohmann::json* ret = NULL; if (!in.is_object()) return NULL; - for (const auto & n : sec_names) { - for (const auto & n_v : in.items() ) { - if ( SectionNameRelaxedMatch(n_v.key(), n) ) { + for (const auto& n : sec_names) { + for (const auto& n_v : in.items()) { + if (SectionNameRelaxedMatch(n_v.key(), n)) { ILA_ERROR_IF(ret) << "Section " << n << " is duplicated."; if (ret && !allow_dup) - return NULL; - + return NULL; + ret = &(in.at(n_v.key())); } } @@ -195,65 +204,67 @@ nlohmann::json * GetJsonSection(nlohmann::json & in, const std::set return ret; } // GetJsonSection -bool JsonRfmapParseSingleSequence(OneBitSignalSequence & out, nlohmann::json & seq) { +bool JsonRfmapParseSingleSequence(OneBitSignalSequence& out, + nlohmann::json& seq) { - auto get_multipler = [](const std::string & in) -> unsigned { - if(in.length() < 2 ) - return 0; + auto get_multipler = [](const std::string& in) -> unsigned { + if (in.length() < 2) + return 0; if (in.at(0) != '*') return 0; auto sub = in.substr(1); - return StrToInt(sub,10); + return StrToInt(sub, 10); }; - if(!seq.is_array()) + if (!seq.is_array()) return false; OneBitSignalSequence tmp_seq; bool the_last_encountered = false; - for(auto & elem : seq.items()){ + for (auto& elem : seq.items()) { if (the_last_encountered) return false; - auto & e = elem.value(); - if(!(e.is_number_unsigned() || e.is_array() || e.is_string())) + auto& e = elem.value(); + if (!(e.is_number_unsigned() || e.is_array() || e.is_string())) return false; - if(e.is_number_unsigned()) + if (e.is_number_unsigned()) tmp_seq.push_back(e.get()); - else if(e.is_array()) { - if(!JsonRfmapParseSingleSequence(tmp_seq, e)) + else if (e.is_array()) { + if (!JsonRfmapParseSingleSequence(tmp_seq, e)) return false; - } else if (e.is_string()) { + } else if (e.is_string()) { // duplicate the tmp_sequence auto mult = e.get(); unsigned n_count = get_multipler(mult); unsigned length = tmp_seq.size(); - if(length == 0 || n_count == 0) + if (length == 0 || n_count == 0) return false; - for(unsigned iter = 0; iter & out, nlohmann::json & in) { - if(!in.is_object()) +bool JsonRfmapParseSequence(std::map& out, + nlohmann::json& in) { + if (!in.is_object()) return false; - - for(const auto & n_seq_pair : in.items()) { - const auto & name = n_seq_pair.key(); - auto & seq = n_seq_pair.value(); - if(!seq.is_array()) + + for (const auto& n_seq_pair : in.items()) { + const auto& name = n_seq_pair.key(); + auto& seq = n_seq_pair.value(); + if (!seq.is_array()) return false; - if(IN(name, out)) + if (IN(name, out)) return false; auto insert_ret = out.insert(std::make_pair(name, OneBitSignalSequence())); // [pos (name, seq) , bool] - auto & seq_ref = insert_ret.first->second; + auto& seq_ref = insert_ret.first->second; bool succ = JsonRfmapParseSingleSequence(seq_ref, seq); if (!succ) return false; @@ -261,37 +272,39 @@ bool JsonRfmapParseSequence(std::map & out, n return true; } // JsonRfmapParseSequence -bool JsonRfmapParseClockFactor(std::map & out, nlohmann::json & in) { - if(!in.is_object()) +bool JsonRfmapParseClockFactor( + std::map& out, + nlohmann::json& in) { + if (!in.is_object()) return false; - for(const auto & n_obj_pair : in.items()) { - const auto & n = n_obj_pair.key(); - auto & obj = n_obj_pair.value(); - if(IN(n, out)) + for (const auto& n_obj_pair : in.items()) { + const auto& n = n_obj_pair.key(); + auto& obj = n_obj_pair.value(); + if (IN(n, out)) return false; - if(!obj.is_object()) + if (!obj.is_object()) return false; ClockSpecification::factor f; - auto * high = GetJsonSection(obj, {"high"}); - auto * low = GetJsonSection(obj, {"low"}); - auto * offset = GetJsonSection(obj, {"offset"}); - if(!(high && low)) + auto* high = GetJsonSection(obj, {"high"}); + auto* low = GetJsonSection(obj, {"low"}); + auto* offset = GetJsonSection(obj, {"offset"}); + if (!(high && low)) return false; - if(high) { - if(!high->is_number_unsigned()) + if (high) { + if (!high->is_number_unsigned()) return false; f.high = high->get(); } - if(low) { - if(!low->is_number_unsigned()) + if (low) { + if (!low->is_number_unsigned()) return false; f.low = low->get(); } - if(offset) { - if(!offset->is_number_unsigned()) + if (offset) { + if (!offset->is_number_unsigned()) return false; f.offset = offset->get(); } @@ -301,107 +314,123 @@ bool JsonRfmapParseClockFactor(std::map } // JsonRfmapParseClockFactor unsigned gcd(unsigned a, unsigned b) { - if(b==0) + if (b == 0) return a; - return gcd(b, a%b); + return gcd(b, a % b); } // least common multiplier -unsigned lcm(const std::vector & in) { +unsigned lcm(const std::vector& in) { unsigned ans = in.at(0); - for(size_t i = 1; i < in.size(); ++i) { - ans = ((in.at(i)*ans)/gcd(in.at(i),ans)); + for (size_t i = 1; i < in.size(); ++i) { + ans = ((in.at(i) * ans) / gcd(in.at(i), ans)); } return ans; } bool JsonRfmapConvertFactorToSeq( - const std::map & in, - std::map & out - ) { + const std::map& in, + std::map& out) { if (in.size() == 0) return false; std::map seq_no_dup; std::vector cycles; - for (const auto & n_factor_pair : in) { - const auto & n = n_factor_pair.first; - const auto & factor_obj = n_factor_pair.second; + for (const auto& n_factor_pair : in) { + const auto& n = n_factor_pair.first; + const auto& factor_obj = n_factor_pair.second; auto n_cycle = factor_obj.high + factor_obj.low; cycles.push_back(n_cycle); - seq_no_dup[n].resize(factor_obj.high,true); + seq_no_dup[n].resize(factor_obj.high, true); seq_no_dup[n].insert(seq_no_dup.at(n).end(), factor_obj.low, false); } // for each factor auto len = lcm(cycles); - for (const auto & n_factor_pair : in) { - const auto & n = n_factor_pair.first; - const auto & factor_obj = n_factor_pair.second; + for (const auto& n_factor_pair : in) { + const auto& n = n_factor_pair.first; + const auto& factor_obj = n_factor_pair.second; auto n_cycle = factor_obj.high + factor_obj.low; - assert(len%n_cycle == 0); - auto n_copy = len/n_cycle; + assert(len % n_cycle == 0); + auto n_copy = len / n_cycle; auto offset = factor_obj.offset; - + unsigned idx = offset; unsigned idx_copy = 0; - while(!(idx == offset && idx_copy == n_copy)) { - + while (!(idx == offset && idx_copy == n_copy)) { + out[n].push_back(seq_no_dup[n][idx]); - if(idx + 1 == n_cycle) - ++ idx_copy; - idx = (idx + 1)%n_cycle; + if (idx + 1 == n_cycle) + ++idx_copy; + idx = (idx + 1) % n_cycle; } assert(out[n].size() == len); } return true; } // JsonRfmapConvertFactorToSeq -#define ERRIF(cond, s) do { if(cond) return (s); } while(0) +#define ERRIF(cond, s) \ + do { \ + if (cond) \ + return (s); \ + } while (0) #define ENSURE(cond, s) ERRIF(!(cond), (s)) -std::string JsonRfMapParseVarDefs(std::map & var_defs, nlohmann::json & def_field) { - - ENSURE(def_field.is_array(), "`defs` field should be list of [name, width, type]"); - for (auto & one_def : def_field) { - ENSURE(one_def.is_array(), "`defs` field should be list of [name, width, type]"); +std::string JsonRfMapParseVarDefs( + std::map& var_defs, + nlohmann::json& def_field) { + + ENSURE(def_field.is_array(), + "`defs` field should be list of [name, width, type]"); + for (auto& one_def : def_field) { + ENSURE(one_def.is_array(), + "`defs` field should be list of [name, width, type]"); auto pos = one_def.begin(); - ENSURE( pos != one_def.end() && pos->is_string(), "`defs` field should be list of [name, width, type]"); + ENSURE(pos != one_def.end() && pos->is_string(), + "`defs` field should be list of [name, width, type]"); auto var_name = pos->get(); - ENSURE(!IN(var_name,var_defs), "var " + var_name + " has been defined"); + ENSURE(!IN(var_name, var_defs), "var " + var_name + " has been defined"); - ++ pos; - ENSURE( pos != one_def.end() && pos->is_number_unsigned(), "`defs` field should be list of [name, width, type]"); + ++pos; + ENSURE(pos != one_def.end() && pos->is_number_unsigned(), + "`defs` field should be list of [name, width, type]"); var_defs[var_name].width = pos->get(); - ERRIF(var_defs[var_name].width == 0, "Definition of " + var_name + " has 0 width"); - - ++ pos; - ENSURE( pos != one_def.end() && pos->is_string(), "`defs` field should be list of [name, width, type]"); - auto tp = pos->get(); - ENSURE( SectionNameRelaxedMatch(tp, "reg") || SectionNameRelaxedMatch(tp, "wire") , "`defs` field should be list of [name, width, type (wire/reg)]" ); + ERRIF(var_defs[var_name].width == 0, + "Definition of " + var_name + " has 0 width"); - var_defs[var_name].type = SectionNameRelaxedMatch(tp, "reg") ? - GeneralVerilogMonitor::VarDef::var_type::REG : - GeneralVerilogMonitor::VarDef::var_type::WIRE; - ++ pos; - ENSURE( pos == one_def.end() , "`defs` expects 3-element tuple" ); + ++pos; + ENSURE(pos != one_def.end() && pos->is_string(), + "`defs` field should be list of [name, width, type]"); + auto tp = pos->get(); + ENSURE(SectionNameRelaxedMatch(tp, "reg") || + SectionNameRelaxedMatch(tp, "wire"), + "`defs` field should be list of [name, width, type (wire/reg)]"); + + var_defs[var_name].type = + SectionNameRelaxedMatch(tp, "reg") + ? GeneralVerilogMonitor::VarDef::var_type::REG + : GeneralVerilogMonitor::VarDef::var_type::WIRE; + ++pos; + ENSURE(pos == one_def.end(), "`defs` expects 3-element tuple"); } return ""; } -std::string JsonRfmapParsePhaseTracker( - PhaseTracker & tracker, nlohmann::json & monitor, const std::string & tracker_name) -{ - auto * event_alias = GetJsonSection(monitor, {"event-alias"}); - auto * rules = GetJsonSection(monitor, {"rules"}); - auto * aux_var = GetJsonSection(monitor, {"aux-var"}); +std::string JsonRfmapParsePhaseTracker(PhaseTracker& tracker, + nlohmann::json& monitor, + const std::string& tracker_name) { + auto* event_alias = GetJsonSection(monitor, {"event-alias"}); + auto* rules = GetJsonSection(monitor, {"rules"}); + auto* aux_var = GetJsonSection(monitor, {"aux-var"}); ERRIF(rules == NULL, "`phase tracker` needs `rules` field"); - if(event_alias) { - ERRIF(!event_alias->is_object(), "`event-alias` expects map:name->expr" ); - for (auto & name_val_pair : event_alias->items()) { - const auto & vn = name_val_pair.key(); - ERRIF(IN(vn,tracker.event_alias), "`"+vn+"` is already defined."); - ERRIF(!name_val_pair.value().is_string(), "expecting string in event-alias"); - tracker.event_alias.emplace(vn, ParseRfMapExprJson(name_val_pair.value())); + if (event_alias) { + ERRIF(!event_alias->is_object(), "`event-alias` expects map:name->expr"); + for (auto& name_val_pair : event_alias->items()) { + const auto& vn = name_val_pair.key(); + ERRIF(IN(vn, tracker.event_alias), "`" + vn + "` is already defined."); + ERRIF(!name_val_pair.value().is_string(), + "expecting string in event-alias"); + tracker.event_alias.emplace(vn, + ParseRfMapExprJson(name_val_pair.value())); } } @@ -413,30 +442,34 @@ std::string JsonRfmapParsePhaseTracker( assert(rules); ENSURE(rules->is_array(), "`rules` field should be list of objects"); size_t sidx = 0; - for(auto & stage : *rules) { + for (auto& stage : *rules) { ENSURE(stage.is_object(), "`rules` field should be list of objects"); - auto * enter = GetJsonSection(stage, {"enter"}); - auto * exit = GetJsonSection(stage, {"exit"}); - auto * stage_name = GetJsonSection(stage, {"name"}); - ENSURE(enter && exit, "`rules` object must contain `enter` and `exit` events"); - ENSURE(enter->is_object(), "`enter` should contain `event` and (optional) `action`"); - ENSURE(exit->is_object(), "`exit` should contain `event` and (optional) `action`"); - auto * enter_event = GetJsonSection(*enter, {"event"}); - auto * exit_event = GetJsonSection(*exit, {"event"}); - auto * enter_action = GetJsonSection(*enter, {"action"}); - auto * exit_action = GetJsonSection(*exit, {"action"}); - ENSURE(enter_event, "`enter` should contain `event` and (optional) `action`"); + auto* enter = GetJsonSection(stage, {"enter"}); + auto* exit = GetJsonSection(stage, {"exit"}); + auto* stage_name = GetJsonSection(stage, {"name"}); + ENSURE(enter && exit, + "`rules` object must contain `enter` and `exit` events"); + ENSURE(enter->is_object(), + "`enter` should contain `event` and (optional) `action`"); + ENSURE(exit->is_object(), + "`exit` should contain `event` and (optional) `action`"); + auto* enter_event = GetJsonSection(*enter, {"event"}); + auto* exit_event = GetJsonSection(*exit, {"event"}); + auto* enter_action = GetJsonSection(*enter, {"action"}); + auto* exit_action = GetJsonSection(*exit, {"action"}); + ENSURE(enter_event, + "`enter` should contain `event` and (optional) `action`"); ENSURE(exit_event, "`exit` should contain `event` and (optional) `action`"); ENSURE(enter_event->is_string(), "`enter` -> `event` should be a string"); ENSURE(exit_event->is_string(), "`exit` -> `event` should be a string"); tracker.rules.push_back(PhaseTracker::Rule()); - auto & ws = tracker.rules.back(); - if(stage_name) { + auto& ws = tracker.rules.back(); + if (stage_name) { ENSURE(stage_name->is_string(), "`name` of a phase should be string"); - ws.stage_name = tracker_name+"_"+stage_name->get(); + ws.stage_name = tracker_name + "_" + stage_name->get(); } else { - ws.stage_name = tracker_name + "_stage" + std::to_string(sidx++); + ws.stage_name = tracker_name + "_stage" + std::to_string(sidx++); } ws.enter_rule = ParseRfMapExprJson(*enter_event); ws.exit_rule = ParseRfMapExprJson(*exit_event); @@ -445,100 +478,112 @@ std::string JsonRfmapParsePhaseTracker( ENSURE(enter_action->is_string(), "`action` should be a string"); auto action_str = enter_action->get(); auto actions = Split(action_str, ";"); - for(auto & a : actions) { + for (auto& a : actions) { StrTrim(a); - if(a.empty()) + if (a.empty()) continue; auto pos = a.find("<="); - ERRIF(pos == std::string::npos, "`action` should be `LHS <= RHS ; ...`"); - auto LHS = a.substr(0,pos); - auto RHS = a.substr(pos+2); + ERRIF(pos == std::string::npos, + "`action` should be `LHS <= RHS ; ...`"); + auto LHS = a.substr(0, pos); + auto RHS = a.substr(pos + 2); PhaseTracker::Assignment assign; StrTrim(LHS); // you don't need to trim RHS (parsing will help) assign.LHS = LHS; assign.RHS = ParseRfMapExpr(RHS); ws.enter_action.push_back(assign); } // for each action - } // if (enter_action) + } // if (enter_action) if (exit_action) { ENSURE(exit_action->is_string(), "`action` should be a string"); auto action_str = exit_action->get(); auto actions = Split(action_str, ";"); - for(auto & a : actions) { + for (auto& a : actions) { StrTrim(a); - if(a.empty()) + if (a.empty()) continue; auto pos = a.find("<="); - ERRIF(pos == std::string::npos, "`action` should be `LHS <= RHS ; ...`"); - auto LHS = a.substr(0,pos); - auto RHS = a.substr(pos+2); + ERRIF(pos == std::string::npos, + "`action` should be `LHS <= RHS ; ...`"); + auto LHS = a.substr(0, pos); + auto RHS = a.substr(pos + 2); PhaseTracker::Assignment assign; StrTrim(LHS); assign.LHS = LHS; assign.RHS = ParseRfMapExpr(RHS); ws.exit_action.push_back(assign); } // for each action - } // exit_action - } // for each stage + } // exit_action + } // for each stage return ""; } -std::string JsonRfmapParseValueRecorder(ValueRecorder & tracker, nlohmann::json & monitor) { - auto * cond = GetJsonSection(monitor, {"condition", "cond"}); - auto * val = GetJsonSection(monitor,{"value", "val"}); - auto * width = GetJsonSection(monitor, {"width", "w"}); +std::string JsonRfmapParseValueRecorder(ValueRecorder& tracker, + nlohmann::json& monitor) { + auto* cond = GetJsonSection(monitor, {"condition", "cond"}); + auto* val = GetJsonSection(monitor, {"value", "val"}); + auto* width = GetJsonSection(monitor, {"width", "w"}); ENSURE(cond && cond->is_string(), "`cond` field should be a string"); ENSURE(val && val->is_string(), "`val` field should be a string"); tracker.condition = ParseRfMapExprJson(*cond); tracker.value = ParseRfMapExprJson(*val); - if(width && width->is_number_unsigned()) { + if (width && width->is_number_unsigned()) { tracker.width = width->get(); } // if you don't write width or use a string then it is 0 else tracker.width = 0; - return ""; + return ""; } #undef ENSURE #undef ERRIF - // ------------------------------------------------------------------------------ +#define ERRIF(cond, str) \ + do { \ + ILA_ERROR_IF(cond) << str; \ + if (cond) \ + return; \ + } while (false) +#define ENSURE(cond, str) ERRIF(!(cond), str) -#define ERRIF(cond,str) do{ ILA_ERROR_IF(cond) << str ; if(cond) return; } while(false) -#define ENSURE(cond,str) ERRIF(!(cond), str) +VerilogRefinementMap::VerilogRefinementMap( + const std::string& varmap_json_file, + const std::string& instcond_json_file) { -VerilogRefinementMap::VerilogRefinementMap - (const std::string & varmap_json_file, - const std::string & instcond_json_file) { - ParseRfExprErrFlag = false; // this is the first pass nlohmann::json rf_vmap; nlohmann::json rf_cond; - load_json(varmap_json_file, rf_vmap); + load_json(varmap_json_file, rf_vmap); load_json(instcond_json_file, rf_cond); { // deprecated warning messages - nlohmann::json * model_name = GetJsonSection(rf_vmap, {"model", "models","model name","model names"}); - ERRIF(model_name != NULL, "model names are not supported. Use `ILA` and `RTL`."); - nlohmann::json * instmap = GetJsonSection(rf_vmap, {"instruction mapping", "instruction map"}); + nlohmann::json* model_name = GetJsonSection( + rf_vmap, {"model", "models", "model name", "model names"}); + ERRIF(model_name != NULL, + "model names are not supported. Use `ILA` and `RTL`."); + nlohmann::json* instmap = + GetJsonSection(rf_vmap, {"instruction mapping", "instruction map"}); ERRIF(instmap != NULL, "instruction mapping is no longer supported"); - nlohmann::json * interface = GetJsonSection(rf_vmap, {"interface mapping", "interface map"}); - ERRIF(interface != NULL, "interface mapping is no longer supported. Use `input mapping` and `RTL interface connection`"); + nlohmann::json* interface = + GetJsonSection(rf_vmap, {"interface mapping", "interface map"}); + ERRIF(interface != NULL, "interface mapping is no longer supported. Use " + "`input mapping` and `RTL interface connection`"); } // now json to -> Rfmap { // state mapping - nlohmann::json * state_mapping = GetJsonSection(rf_vmap,{"state mapping", "state map"}); - ERRIF(state_mapping == NULL , "state var mapping is duplicated or missing"); + nlohmann::json* state_mapping = + GetJsonSection(rf_vmap, {"state mapping", "state map"}); + ERRIF(state_mapping == NULL, "state var mapping is duplicated or missing"); for (auto& i : state_mapping->items()) { IlaVarMapping svmp; auto sname = i.key(); // ila state name - if(i.value().is_string()) { + if (i.value().is_string()) { svmp.type = IlaVarMapping::StateVarMapType::SINGLE; svmp.single_map.single_map = ParseRfMapExprJson(i.value()); } else if (i.value().is_object()) { @@ -546,312 +591,377 @@ VerilogRefinementMap::VerilogRefinementMap svmp.type = IlaVarMapping::StateVarMapType::EXTERNMEM; svmp.externmem_map.push_back(ExternalMemPortMap()); - auto & extmem_ports = i.value(); + auto& extmem_ports = i.value(); bool succ = JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); ENSURE(succ, "fail to parse external memory map"); } else if (i.value().is_array()) { - ERRIF( i.value().empty(), ("Empty list for " + sname) ); + ERRIF(i.value().empty(), ("Empty list for " + sname)); bool are_memports = false; - if ( i.value().begin()->is_object() ) { + if (i.value().begin()->is_object()) { are_memports = true; - } else if (i.value().begin()->is_array() ) { + } else if (i.value().begin()->is_array()) { are_memports = false; } else ERRIF(true, "Expecting array of list or objects for " + sname); if (are_memports) { svmp.type = IlaVarMapping::StateVarMapType::EXTERNMEM; - for (const auto & idx_obj_pair : i.value().items()) { - ENSURE( idx_obj_pair.value().is_object() , "Expecting array of objects for " + sname); + for (const auto& idx_obj_pair : i.value().items()) { + ENSURE(idx_obj_pair.value().is_object(), + "Expecting array of objects for " + sname); svmp.externmem_map.push_back(ExternalMemPortMap()); - auto & extmem_ports = idx_obj_pair.value(); - bool succ = JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); + auto& extmem_ports = idx_obj_pair.value(); + bool succ = + JsonRfmapParseMem(svmp.externmem_map.back(), extmem_ports); ENSURE(succ, "fail to parse external memory map"); } } else { svmp.type = IlaVarMapping::StateVarMapType::CONDITIONAL; - JsonRfmapParseCond(svmp.single_map, i.value() ); + JsonRfmapParseCond(svmp.single_map, i.value()); } } // if array of array / array of object - ILA_ERROR_IF( IN(sname, ila_state_var_map) ) << "ILA state var : " << sname << " has duplicated mapping"; - ila_state_var_map.emplace(sname, svmp); + ILA_ERROR_IF(IN(sname, ila_state_var_map)) + << "ILA state var : " << sname << " has duplicated mapping"; + ila_state_var_map.emplace(sname, svmp); } // for each state - } // state mapping + } // state mapping { // input mapping // TODO: add things here - nlohmann::json * input_mapping = GetJsonSection(rf_vmap,{"input mapping", "input map"}); - if(input_mapping) { + nlohmann::json* input_mapping = + GetJsonSection(rf_vmap, {"input mapping", "input map"}); + if (input_mapping) { for (auto& i : input_mapping->items()) { IlaVarMapping ivmp; auto sname = i.key(); // ila state name ERRIF(i.value().is_object(), "input array is not supported"); - if(i.value().is_string()) { + if (i.value().is_string()) { ivmp.type = IlaVarMapping::StateVarMapType::SINGLE; ivmp.single_map.single_map = ParseRfMapExprJson(i.value()); } else if (i.value().is_array()) { - ERRIF( i.value().empty(), ("Empty list for " + sname) ); + ERRIF(i.value().empty(), ("Empty list for " + sname)); ENSURE(i.value().begin()->is_array(), "Expect array of array"); ivmp.type = IlaVarMapping::StateVarMapType::CONDITIONAL; - JsonRfmapParseCond(ivmp.single_map, i.value() ); + JsonRfmapParseCond(ivmp.single_map, i.value()); } // if array of array / array of object - ILA_ERROR_IF( IN(sname, ila_input_var_map) ) << "ILA state var : " << sname << " has duplicated mapping"; - ila_input_var_map.emplace(sname, ivmp); + ILA_ERROR_IF(IN(sname, ila_input_var_map)) + << "ILA state var : " << sname << " has duplicated mapping"; + ila_input_var_map.emplace(sname, ivmp); } // for each input var } } // input mapping { // interface map - nlohmann::json * rtl_if_map = GetJsonSection(rf_vmap,{"RTL interface connection", "RTL interface connect"}); - ERRIF(rtl_if_map == nullptr, "`RTL interface connection` is duplicated or missing" ); - nlohmann::json * clock_domains = GetJsonSection(*rtl_if_map,{"CLOCK"},true); - nlohmann::json * reset_list = GetJsonSection(*rtl_if_map,{"RESET"},true); - nlohmann::json * nreset_list = GetJsonSection(*rtl_if_map,{"NRESET"},true); - nlohmann::json * reset_domains = GetJsonSection(*rtl_if_map,{"CUSTOMRESET"},true); - if(clock_domains) { - ENSURE(clock_domains->is_array() || clock_domains->is_string() || clock_domains->is_object(), - "clock specification in RTL interface connection should be string/list of string/map:string->list(string)"); - if(clock_domains->is_string()) - rtl_interface_connection.clock_domain_defs["default"].insert(clock_domains->get()); - else if(clock_domains->is_array()){ + nlohmann::json* rtl_if_map = GetJsonSection( + rf_vmap, {"RTL interface connection", "RTL interface connect"}); + ERRIF(rtl_if_map == nullptr, + "`RTL interface connection` is duplicated or missing"); + nlohmann::json* clock_domains = + GetJsonSection(*rtl_if_map, {"CLOCK"}, true); + nlohmann::json* reset_list = GetJsonSection(*rtl_if_map, {"RESET"}, true); + nlohmann::json* nreset_list = GetJsonSection(*rtl_if_map, {"NRESET"}, true); + nlohmann::json* reset_domains = + GetJsonSection(*rtl_if_map, {"CUSTOMRESET"}, true); + if (clock_domains) { + ENSURE(clock_domains->is_array() || clock_domains->is_string() || + clock_domains->is_object(), + "clock specification in RTL interface connection should be " + "string/list of string/map:string->list(string)"); + if (clock_domains->is_string()) + rtl_interface_connection.clock_domain_defs["default"].insert( + clock_domains->get()); + else if (clock_domains->is_array()) { auto clk_pins = clock_domains->get>(); - for (const auto & clk_pin : clk_pins) - rtl_interface_connection.clock_domain_defs["default"].insert(clk_pin); + for (const auto& clk_pin : clk_pins) + rtl_interface_connection.clock_domain_defs["default"].insert(clk_pin); } else { // is_object - for(const auto & n_l_pair : clock_domains->items()) { - const auto & domain_name = n_l_pair.key(); + for (const auto& n_l_pair : clock_domains->items()) { + const auto& domain_name = n_l_pair.key(); std::set pins; - ENSURE(n_l_pair.value().is_string() || n_l_pair.value().is_array(), "expect string/array in RTL interface connection"); + ENSURE(n_l_pair.value().is_string() || n_l_pair.value().is_array(), + "expect string/array in RTL interface connection"); if (n_l_pair.value().is_string()) { pins.insert(n_l_pair.value().get()); } else { auto pin_vec = n_l_pair.value().get>(); pins = std::set(pin_vec.begin(), pin_vec.end()); } - rtl_interface_connection.clock_domain_defs.emplace( - domain_name, pins - ); + rtl_interface_connection.clock_domain_defs.emplace(domain_name, pins); } } // if is_object - } // if (clock_domain) + } // if (clock_domain) - if(reset_list) { - if(reset_list->is_string()) - rtl_interface_connection.reset_pins.insert(reset_list->get()); - else if(reset_list->is_array()){ + if (reset_list) { + if (reset_list->is_string()) + rtl_interface_connection.reset_pins.insert( + reset_list->get()); + else if (reset_list->is_array()) { auto reset_pins = reset_list->get>(); - for (const auto & pin : reset_pins) + for (const auto& pin : reset_pins) rtl_interface_connection.reset_pins.insert(pin); } } - if(nreset_list) { - if(nreset_list->is_string()) - rtl_interface_connection.nreset_pins.insert(nreset_list->get()); - else if(nreset_list->is_array()){ + if (nreset_list) { + if (nreset_list->is_string()) + rtl_interface_connection.nreset_pins.insert( + nreset_list->get()); + else if (nreset_list->is_array()) { auto nreset_pins = nreset_list->get>(); - for (const auto & pin : nreset_pins) + for (const auto& pin : nreset_pins) rtl_interface_connection.nreset_pins.insert(pin); } } - if(reset_domains) { - ENSURE(reset_domains->is_array() || reset_domains->is_string() || reset_domains->is_object(), - "clock specification in RTL interface connection should be string/list of string/map:string->list(string)"); - if(reset_domains->is_string()) - rtl_interface_connection.custom_reset_domain_defs["default"].push_back(reset_domains->get()); - else if(reset_domains->is_array()){ + if (reset_domains) { + ENSURE(reset_domains->is_array() || reset_domains->is_string() || + reset_domains->is_object(), + "clock specification in RTL interface connection should be " + "string/list of string/map:string->list(string)"); + if (reset_domains->is_string()) + rtl_interface_connection.custom_reset_domain_defs["default"].push_back( + reset_domains->get()); + else if (reset_domains->is_array()) { rtl_interface_connection.custom_reset_domain_defs.insert( - std::make_pair(std::string("default"), reset_domains->get>())); + std::make_pair(std::string("default"), + reset_domains->get>())); } else { // is_object - for(const auto & n_l_pair : reset_domains->items()) { - const auto & domain_name = n_l_pair.key(); + for (const auto& n_l_pair : reset_domains->items()) { + const auto& domain_name = n_l_pair.key(); std::vector pins; - ENSURE(n_l_pair.value().is_string() || n_l_pair.value().is_array(), "expect string/array in RTL interface connection"); + ENSURE(n_l_pair.value().is_string() || n_l_pair.value().is_array(), + "expect string/array in RTL interface connection"); if (n_l_pair.value().is_string()) { pins.push_back(n_l_pair.value().get()); } else { pins = n_l_pair.value().get>(); } - rtl_interface_connection.custom_reset_domain_defs.emplace( - domain_name, pins - ); + rtl_interface_connection.custom_reset_domain_defs.emplace(domain_name, + pins); } } // if is_object - } // if reset custom domain - } // interface map + } // if reset custom domain + } // interface map { // reset section parsing - nlohmann::json * reset_section = GetJsonSection(rf_vmap,{"reset"}); - if(reset_section) { - nlohmann::json * initial_state = GetJsonSection(*reset_section,{"initial-state"}); - nlohmann::json * cycle = GetJsonSection(*reset_section,{"cycles"}); - nlohmann::json * customreset = GetJsonSection(*reset_section,{"custom-seq"}); + nlohmann::json* reset_section = GetJsonSection(rf_vmap, {"reset"}); + if (reset_section) { + nlohmann::json* initial_state = + GetJsonSection(*reset_section, {"initial-state"}); + nlohmann::json* cycle = GetJsonSection(*reset_section, {"cycles"}); + nlohmann::json* customreset = + GetJsonSection(*reset_section, {"custom-seq"}); if (initial_state) { - ENSURE(initial_state->is_object() , "initial state should be map:name->value"); - for(const auto & n_v_pair : initial_state->items()) { - const auto & sn = n_v_pair.key(); + ENSURE(initial_state->is_object(), + "initial state should be map:name->value"); + for (const auto& n_v_pair : initial_state->items()) { + const auto& sn = n_v_pair.key(); RfExpr val = ParseRfMapExprJson(n_v_pair.value()); - ERRIF(IN(sn, reset_specification.initial_state), "duplicated sname for initial-state in reset" ); + ERRIF(IN(sn, reset_specification.initial_state), + "duplicated sname for initial-state in reset"); reset_specification.initial_state[sn] = val; } } // initial state if (cycle) { - ENSURE(cycle->is_number_unsigned(), "cycles in reset should be unsigned integer"); + ENSURE(cycle->is_number_unsigned(), + "cycles in reset should be unsigned integer"); reset_specification.reset_cycle = cycle->get(); } else reset_specification.reset_cycle = 1; if (customreset) { - bool succ = JsonRfmapParseSequence(reset_specification.custom_reset_sequence, *customreset); + bool succ = JsonRfmapParseSequence( + reset_specification.custom_reset_sequence, *customreset); ENSURE(succ, "Custom Reset Sequence error!"); } } // if reset_section - } // reset + } // reset { // clock section - nlohmann::json * clock_section = GetJsonSection(rf_vmap,{"clock"}); + nlohmann::json* clock_section = GetJsonSection(rf_vmap, {"clock"}); if (clock_section) { - nlohmann::json * factor_section = GetJsonSection(*clock_section, {"factor"}, true); - nlohmann::json * custom_section = GetJsonSection(*clock_section, {"custom"}, true); - ENSURE(factor_section || custom_section, "clock section must contain factor/custom field"); - ERRIF(factor_section && custom_section, "Cannot have both `factor` and `custom` section"); + nlohmann::json* factor_section = + GetJsonSection(*clock_section, {"factor"}, true); + nlohmann::json* custom_section = + GetJsonSection(*clock_section, {"custom"}, true); + ENSURE(factor_section || custom_section, + "clock section must contain factor/custom field"); + ERRIF(factor_section && custom_section, + "Cannot have both `factor` and `custom` section"); if (custom_section) { - nlohmann::json * length = GetJsonSection(*custom_section, {"length"}); + nlohmann::json* length = GetJsonSection(*custom_section, {"length"}); ENSURE(length, "`length` field is needed for custom section"); - ENSURE(length->is_number_unsigned(), "length field must be unsigned integer"); + ENSURE(length->is_number_unsigned(), + "length field must be unsigned integer"); clock_specification.gcm_period = length->get(); - nlohmann::json * clocks = GetJsonSection(*custom_section, {"clocks"}); + nlohmann::json* clocks = GetJsonSection(*custom_section, {"clocks"}); ENSURE(clocks, "`clocks` field is needed for custom section"); - bool succ = JsonRfmapParseSequence(clock_specification.custom_clock_sequence, *clocks); + bool succ = JsonRfmapParseSequence( + clock_specification.custom_clock_sequence, *clocks); ENSURE(succ, "Custom Clock error!"); } else { // factor_section - bool succ = - JsonRfmapParseClockFactor(clock_specification.custom_clock_factor, *factor_section ); - succ = succ && - JsonRfmapConvertFactorToSeq( - clock_specification.custom_clock_factor, - clock_specification.custom_clock_sequence); + bool succ = JsonRfmapParseClockFactor( + clock_specification.custom_clock_factor, *factor_section); + succ = succ && JsonRfmapConvertFactorToSeq( + clock_specification.custom_clock_factor, + clock_specification.custom_clock_sequence); ENSURE(succ, "Custom clock sequence error"); } } // if clock section - } // clock + } // clock { // uf section - nlohmann::json * func_section = GetJsonSection(rf_vmap,{"functions","function","uf","ufs","uninterpreted function","uninterpreted functions"}); + nlohmann::json* func_section = GetJsonSection( + rf_vmap, {"functions", "function", "uf", "ufs", + "uninterpreted function", "uninterpreted functions"}); if (func_section) { - ENSURE(func_section->is_object(), "Expect `functions` to be map:name->list of invocation "); - for(auto & n_invocation_pair : func_section->items()) { - const auto & n = n_invocation_pair.key(); - auto & invocations = n_invocation_pair.value(); - auto ret = uf_application.insert(std::make_pair(n, UninterpretedFunctionApplication())); - auto & apply_obj = ret.first->second; // point to the UninterpretedFunctionApplication object - ENSURE(invocations.is_array(), "Expect `functions` to be map:name->list of invocation"); - for (auto & elem : invocations) { - ENSURE(elem.is_object(), "Expect `functions` to be map:name->list of invocation(object)"); - auto * result = GetJsonSection(elem,{"result"}); - auto * arg = GetJsonSection(elem, {"arg","args"}); - ENSURE(result && arg, "Expect invocation object has `result` and `arg` field"); - ENSURE(result->is_string(), "Expect type string in `result` field of invocation object"); - ENSURE(arg->is_array(), "Expect type list(string) in `arg` field of invocation object"); - apply_obj.func_applications.push_back(UninterpretedFunctionApplication::Apply()); - auto & curr_invocation = apply_obj.func_applications.back(); + ENSURE(func_section->is_object(), + "Expect `functions` to be map:name->list of invocation "); + for (auto& n_invocation_pair : func_section->items()) { + const auto& n = n_invocation_pair.key(); + auto& invocations = n_invocation_pair.value(); + auto ret = uf_application.insert( + std::make_pair(n, UninterpretedFunctionApplication())); + auto& apply_obj = + ret.first->second; // point to the UninterpretedFunctionApplication + // object + ENSURE(invocations.is_array(), + "Expect `functions` to be map:name->list of invocation"); + for (auto& elem : invocations) { + ENSURE( + elem.is_object(), + "Expect `functions` to be map:name->list of invocation(object)"); + auto* result = GetJsonSection(elem, {"result"}); + auto* arg = GetJsonSection(elem, {"arg", "args"}); + ENSURE(result && arg, + "Expect invocation object has `result` and `arg` field"); + ENSURE(result->is_string(), + "Expect type string in `result` field of invocation object"); + ENSURE( + arg->is_array(), + "Expect type list(string) in `arg` field of invocation object"); + apply_obj.func_applications.push_back( + UninterpretedFunctionApplication::Apply()); + auto& curr_invocation = apply_obj.func_applications.back(); curr_invocation.result_map = ParseRfMapExprJson(*result); - std::vector argList = arg->get>(); - for (const auto & arg : argList) + std::vector argList = + arg->get>(); + for (const auto& arg : argList) curr_invocation.arg_map.push_back(ParseRfMapExpr(arg)); } } // for each invocation - } // if func_section - } // uf section - { // additional mapping & assumptions + } // if func_section + } // uf section + { // additional mapping & assumptions { - nlohmann::json * mapping_control = GetJsonSection(rf_vmap,{"mapping control"}); - ERRIF(mapping_control!=NULL, "please rename `mapping control` to `additional mapping`"); + nlohmann::json* mapping_control = + GetJsonSection(rf_vmap, {"mapping control"}); + ERRIF(mapping_control != NULL, + "please rename `mapping control` to `additional mapping`"); } - nlohmann::json * additonal_section = GetJsonSection(rf_vmap,{"additional mapping"}); - if(additonal_section) { - ENSURE(additonal_section->is_array(), "`additional mapping` section should be a list of string"); - for(auto & pstr : *additonal_section) { - ENSURE(pstr.is_string(), "`additional mapping` section should be a list of string"); + nlohmann::json* additonal_section = + GetJsonSection(rf_vmap, {"additional mapping"}); + if (additonal_section) { + ENSURE(additonal_section->is_array(), + "`additional mapping` section should be a list of string"); + for (auto& pstr : *additonal_section) { + ENSURE(pstr.is_string(), + "`additional mapping` section should be a list of string"); additional_mapping.push_back(ParseRfMapExprJson(pstr)); } } // if additional mapping - nlohmann::json * assumption_section = GetJsonSection(rf_vmap,{"assumptions"}); - if(assumption_section) { - ENSURE(assumption_section->is_array(), "`assumptions` section should be a list of string"); - for(auto & pstr : *assumption_section) { - ENSURE(pstr.is_string(), "`assumptions` section should be a list of string"); + nlohmann::json* assumption_section = + GetJsonSection(rf_vmap, {"assumptions"}); + if (assumption_section) { + ENSURE(assumption_section->is_array(), + "`assumptions` section should be a list of string"); + for (auto& pstr : *assumption_section) { + ENSURE(pstr.is_string(), + "`assumptions` section should be a list of string"); assumptions.push_back(ParseRfMapExprJson(pstr)); } } } // additional mapping & assumptions { // phase tracker, value recorder, customized ones - nlohmann::json * monitor_section = GetJsonSection(rf_vmap,{"monitor"}); - if(monitor_section) { + nlohmann::json* monitor_section = GetJsonSection(rf_vmap, {"monitor"}); + if (monitor_section) { ENSURE(monitor_section->is_object(), "`monitor` section should be a map"); - for(auto & name_monitor_pair : monitor_section->items()) { + for (auto& name_monitor_pair : monitor_section->items()) { auto name = name_monitor_pair.key(); - - ERRIF(IN(name,customized_monitor), "monitor `"+name+"` has been defined."); - ERRIF(IN(name,phase_tracker), "monitor `"+name+"` has been defined."); - ERRIF(IN(name,value_recorder), "monitor `"+name+"` has been defined."); - - auto & monitor = name_monitor_pair.value(); - auto * template_field = GetJsonSection(monitor,{"template"}); - if(template_field) { - ENSURE(template_field->is_string(), "`template` field should be string"); + + ERRIF(IN(name, customized_monitor), + "monitor `" + name + "` has been defined."); + ERRIF(IN(name, phase_tracker), + "monitor `" + name + "` has been defined."); + ERRIF(IN(name, value_recorder), + "monitor `" + name + "` has been defined."); + + auto& monitor = name_monitor_pair.value(); + auto* template_field = GetJsonSection(monitor, {"template"}); + if (template_field) { + ENSURE(template_field->is_string(), + "`template` field should be string"); auto template_name = template_field->get(); - if(SectionNameRelaxedMatch(template_name,"phase tracker")) { + if (SectionNameRelaxedMatch(template_name, "phase tracker")) { phase_tracker.emplace(name, PhaseTracker()); std::string errmsg = JsonRfmapParsePhaseTracker( - phase_tracker.at(name), monitor, name); + phase_tracker.at(name), monitor, name); ENSURE(errmsg.empty(), errmsg); - } else if (SectionNameRelaxedMatch(template_name,"value recorder")) { + } else if (SectionNameRelaxedMatch(template_name, "value recorder")) { value_recorder.emplace(name, ValueRecorder()); - std::string errmsg = JsonRfmapParseValueRecorder(value_recorder.at(name), monitor); + std::string errmsg = + JsonRfmapParseValueRecorder(value_recorder.at(name), monitor); ENSURE(errmsg.empty(), errmsg); } else { - ERRIF(true, "template name `" +template_name+"` is not recognized." ); + ERRIF(true, + "template name `" + template_name + "` is not recognized."); } - // end if has template field + // end if has template field } else { customized_monitor.emplace(name, GeneralVerilogMonitor()); - auto & mnt_ref = customized_monitor.at(name); + auto& mnt_ref = customized_monitor.at(name); { // inline verilog // has no template - auto * verilog_field = GetJsonSection(monitor,{"verilog"}); - auto * verilog_file_field = GetJsonSection(monitor,{"verilog-from-file"}); - auto * keep_inv = GetJsonSection(monitor,{"keep-for-invariant", "keep-for-invariants"}); - - ERRIF(verilog_field && verilog_file_field, "`verilog` or `verilog-from-file` fields are mutual exclusive"); - if(keep_inv) { - ENSURE(keep_inv->is_boolean(), "`keep-for-invariant` should be Boolean"); + auto* verilog_field = GetJsonSection(monitor, {"verilog"}); + auto* verilog_file_field = + GetJsonSection(monitor, {"verilog-from-file"}); + auto* keep_inv = GetJsonSection( + monitor, {"keep-for-invariant", "keep-for-invariants"}); + + ERRIF( + verilog_field && verilog_file_field, + "`verilog` or `verilog-from-file` fields are mutual exclusive"); + if (keep_inv) { + ENSURE(keep_inv->is_boolean(), + "`keep-for-invariant` should be Boolean"); mnt_ref.keep_for_invariant = keep_inv->get(); } - - if(verilog_field) { - if( verilog_field->is_string() ) { + + if (verilog_field) { + if (verilog_field->is_string()) { mnt_ref.verilog_inline = verilog_field->get(); } else { - ENSURE(verilog_field->is_array() , "`verilog` field should be a list of string" ); - for (auto & ps : *verilog_field) { - ENSURE(ps.is_string(), "`verilog` field should be a list of string"); + ENSURE(verilog_field->is_array(), + "`verilog` field should be a list of string"); + for (auto& ps : *verilog_field) { + ENSURE(ps.is_string(), + "`verilog` field should be a list of string"); mnt_ref.verilog_inline += ps.get() + "\n"; } } } else if (verilog_file_field) { - ENSURE(verilog_file_field->is_string(), "`verilog-from-file` expects a string (file name)"); + ENSURE(verilog_file_field->is_string(), + "`verilog-from-file` expects a string (file name)"); auto fname = verilog_file_field->get(); std::ifstream fin(fname); ENSURE(fin.is_open(), "Cannot read from " + fname); @@ -861,27 +971,34 @@ VerilogRefinementMap::VerilogRefinementMap mnt_ref.verilog_inline = buffer.str(); } } // verilog_file_field : from file - } // inline verilog + } // inline verilog { // append verilog outside the module // has no template - auto * verilog_field = GetJsonSection(monitor,{"append-verilog"}); - auto * verilog_file_field = GetJsonSection(monitor,{"append-verilog-from-file"}); - - ERRIF(verilog_field && verilog_file_field, "`append-verilog` or `append-verilog-from-file` fields are mutual exclusive"); - - if(verilog_field) { - if( verilog_field->is_string() ) { - mnt_ref.verilog_append = verilog_field->get() + "\n"; + auto* verilog_field = GetJsonSection(monitor, {"append-verilog"}); + auto* verilog_file_field = + GetJsonSection(monitor, {"append-verilog-from-file"}); + + ERRIF(verilog_field && verilog_file_field, + "`append-verilog` or `append-verilog-from-file` fields are " + "mutual exclusive"); + + if (verilog_field) { + if (verilog_field->is_string()) { + mnt_ref.verilog_append = + verilog_field->get() + "\n"; } else { - ENSURE(verilog_field->is_array() , "`append-verilog` field should be a list of string" ); - for (auto & ps : *verilog_field) { - ENSURE(ps.is_string(), "`append-verilog` field should be a list of string"); + ENSURE(verilog_field->is_array(), + "`append-verilog` field should be a list of string"); + for (auto& ps : *verilog_field) { + ENSURE(ps.is_string(), + "`append-verilog` field should be a list of string"); mnt_ref.verilog_append += ps.get() + "\n"; } } } else if (verilog_file_field) { - ENSURE(verilog_file_field->is_string(), "`append-verilog-from-file` expects a string (file name)"); + ENSURE(verilog_file_field->is_string(), + "`append-verilog-from-file` expects a string (file name)"); auto fname = verilog_file_field->get(); std::ifstream fin(fname); ENSURE(fin.is_open(), "Cannot read from " + fname); @@ -891,117 +1008,125 @@ VerilogRefinementMap::VerilogRefinementMap mnt_ref.verilog_append = buffer.str() + "\n"; } } // append-verilog_file_field : from file - } // verilog_append verilog + } // verilog_append verilog - auto * ref_field = GetJsonSection(monitor,{"refs"}); - if (ref_field) - { // refs - ENSURE(ref_field->is_array(), "`refs` field should be a list of string"); - for ( auto & p : *ref_field) { + auto* ref_field = GetJsonSection(monitor, {"refs"}); + if (ref_field) { // refs + ENSURE(ref_field->is_array(), + "`refs` field should be a list of string"); + for (auto& p : *ref_field) { ENSURE(p.is_string(), "`refs` field should be a list of string"); auto var_name = p.get(); - ILA_WARN_IF(IN(var_name, mnt_ref.var_uses)) << "`" + var_name+"` has been declared already"; - mnt_ref.var_uses.insert( p.get() ); + ILA_WARN_IF(IN(var_name, mnt_ref.var_uses)) + << "`" + var_name + "` has been declared already"; + mnt_ref.var_uses.insert(p.get()); } } // if ref_field - auto * def_field = GetJsonSection(monitor,{"defs"}); - if (def_field) - { // defs - auto err_msg = JsonRfMapParseVarDefs( mnt_ref.var_defs , *def_field); + auto* def_field = GetJsonSection(monitor, {"defs"}); + if (def_field) { // defs + auto err_msg = JsonRfMapParseVarDefs(mnt_ref.var_defs, *def_field); ENSURE(err_msg.empty(), err_msg); } // if def_field - } // else if it is verilog monitor (general) - } // for each monitor - } // if has monitor field - } // monitor block - + } // else if it is verilog monitor (general) + } // for each monitor + } // if has monitor field + } // monitor block + // ---------------- inst_cond ------------------------ // { - auto * instrs = GetJsonSection(rf_cond, {"instructions"}); - auto * invariants = GetJsonSection(rf_cond, {"global invariants"}); - if(instrs) { + auto* instrs = GetJsonSection(rf_cond, {"instructions"}); + auto* invariants = GetJsonSection(rf_cond, {"global invariants"}); + if (instrs) { ENSURE(instrs->is_array(), "`instructions` should be array of object"); - for(auto & instr : *instrs) { - ENSURE(instr.is_object() , "`instructions` should be array of object"); - auto * instr_name = GetJsonSection(instr, {"instruction"}); - auto * ready_bnd = GetJsonSection(instr, {"ready-bound"}); - auto * ready_signal = GetJsonSection(instr, {"ready-signal"}); - auto * max_bound = GetJsonSection(instr, {"max-bound"}); - auto * start_condition = GetJsonSection(instr, {"start-condition"}); - ENSURE(instr_name && instr_name->is_string(), "`instruction` field should be a string"); - ERRIF(ready_bnd && ready_signal, "`ready bound` and `ready signal` are mutual exclusive"); - ENSURE(ready_bnd || ready_signal , "You must specify one of `ready bound` and `ready signal`"); + for (auto& instr : *instrs) { + ENSURE(instr.is_object(), "`instructions` should be array of object"); + auto* instr_name = GetJsonSection(instr, {"instruction"}); + auto* ready_bnd = GetJsonSection(instr, {"ready-bound"}); + auto* ready_signal = GetJsonSection(instr, {"ready-signal"}); + auto* max_bound = GetJsonSection(instr, {"max-bound"}); + auto* start_condition = GetJsonSection(instr, {"start-condition"}); + ENSURE(instr_name && instr_name->is_string(), + "`instruction` field should be a string"); + ERRIF(ready_bnd && ready_signal, + "`ready bound` and `ready signal` are mutual exclusive"); + ENSURE(ready_bnd || ready_signal, + "You must specify one of `ready bound` and `ready signal`"); auto iname = instr_name->get(); - inst_complete_cond.emplace(iname,InstructionCompleteCondition()); - auto & ws = inst_complete_cond.at(iname); - + inst_complete_cond.emplace(iname, InstructionCompleteCondition()); + auto& ws = inst_complete_cond.at(iname); + ws.instruction_name = iname; - if(ready_bnd) { - ENSURE(ready_bnd->is_number_unsigned(), "`ready-bound` should be an unsigned number"); + if (ready_bnd) { + ENSURE(ready_bnd->is_number_unsigned(), + "`ready-bound` should be an unsigned number"); ws.ready_bound = ready_bnd->get(); ws.type = InstructionCompleteCondition::ConditionType::BOUND; } else { // ready_signal - ENSURE(ready_signal->is_string(), "`ready-signal` should be a string"); + ENSURE(ready_signal->is_string(), + "`ready-signal` should be a string"); ws.ready_signal = ParseRfMapExprJson(*ready_signal); ws.type = InstructionCompleteCondition::ConditionType::SIGNAL; } - if(max_bound) { - ENSURE(max_bound->is_number_unsigned(), "`max_bound` should be an unsigned number"); + if (max_bound) { + ENSURE(max_bound->is_number_unsigned(), + "`max_bound` should be an unsigned number"); ws.max_bound = max_bound->get(); - } else + } else ws.max_bound = 0; if (start_condition) { if (start_condition->is_string()) { - ws.start_condition.push_back( ParseRfMapExprJson(*start_condition) ); + ws.start_condition.push_back(ParseRfMapExprJson(*start_condition)); } else { - ENSURE(start_condition->is_array(), "`start_condition` should be a string or array of strings"); - for (auto & cond : *start_condition) { - ENSURE(cond.is_string(), "`start_condition` should be a string or array of strings"); - ws.start_condition.push_back( ParseRfMapExprJson(cond)); + ENSURE(start_condition->is_array(), + "`start_condition` should be a string or array of strings"); + for (auto& cond : *start_condition) { + ENSURE( + cond.is_string(), + "`start_condition` should be a string or array of strings"); + ws.start_condition.push_back(ParseRfMapExprJson(cond)); } } // end if start condition is string - } // end if start condition - } // for each instr` - } // if instrs + } // end if start condition + } // for each instr` + } // if instrs if (invariants) { - ENSURE(invariants->is_array(), "`global-invariants` should be an array of strings"); - for(auto & inv : *invariants) { - ENSURE(inv.is_string(), "`global-invariants` should be an array of strings"); + ENSURE(invariants->is_array(), + "`global-invariants` should be an array of strings"); + for (auto& inv : *invariants) { + ENSURE(inv.is_string(), + "`global-invariants` should be an array of strings"); global_invariants.push_back(ParseRfMapExprJson(inv)); } } // if invariant - } // inst cond - + } // inst cond // ---------------- supplementary_info ------------------------ // { - auto * annotation = GetJsonSection(rf_vmap, {"annotation","annotations"}); - if(annotation) { - auto * width_anno = GetJsonSection(*annotation, {"width"}); - if(width_anno && width_anno->is_object()){ + auto* annotation = GetJsonSection(rf_vmap, {"annotation", "annotations"}); + if (annotation) { + auto* width_anno = GetJsonSection(*annotation, {"width"}); + if (width_anno && width_anno->is_object()) { for (auto&& nw : width_anno->items()) { width_info.insert(std::make_pair(nw.key(), nw.value().get())); } } } // end of annotation - } // end of supplementary_info - - + } // end of supplementary_info ERRIF(ParseRfExprErrFlag, "error occur in refinement expression parsing"); } // VerilogRefinementMap::VerilogRefinementMap -bool is_valid_id_name(const std::string & in) { - if(in.empty()) +bool is_valid_id_name(const std::string& in) { + if (in.empty()) return false; - if(!isalpha(in.at(0)) && in.at(0)!='_') + if (!isalpha(in.at(0)) && in.at(0) != '_') return false; - for(size_t idx = 1; idx < in.size(); ++ idx) + for (size_t idx = 1; idx < in.size(); ++idx) if (!isalnum(in.at(idx))) return false; return true; @@ -1009,82 +1134,103 @@ bool is_valid_id_name(const std::string & in) { #undef ERRIF #undef ENSURE -#define ERRIF(cond,str) do{ ILA_ERROR_IF(cond) << str ; if(cond) return false; } while(false) -#define ENSURE(cond,str) ERRIF(!(cond),str) +#define ERRIF(cond, str) \ + do { \ + ILA_ERROR_IF(cond) << str; \ + if (cond) \ + return false; \ + } while (false) +#define ENSURE(cond, str) ERRIF(!(cond), str) bool VerilogRefinementMap::SelfCheckField() const { // check module name - ERRIF(ParseRfExprErrFlag, "Error in parsing refinement expressions" ); - - for (const auto & n_map: ila_state_var_map) { - ENSURE( !(n_map.second.externmem_map.empty()) || - (n_map.second.single_map.single_map.get() != nullptr) || - !(n_map.second.single_map.cond_map.empty()) , "state var map cannot be empty for " + n_map.first); - ERRIF( !(n_map.second.externmem_map.empty()) && - (n_map.second.single_map.single_map.get() != nullptr) , "duplicate state var map for " + n_map.first ); - ERRIF( !(n_map.second.single_map.cond_map.empty()) && - (n_map.second.single_map.single_map.get() != nullptr) , "duplicate state var map for " + n_map.first ); - ERRIF( !(n_map.second.externmem_map.empty()) && - (!n_map.second.single_map.cond_map.empty()) , "duplicate state var map for " + n_map.first ); + ERRIF(ParseRfExprErrFlag, "Error in parsing refinement expressions"); + + for (const auto& n_map : ila_state_var_map) { + ENSURE(!(n_map.second.externmem_map.empty()) || + (n_map.second.single_map.single_map.get() != nullptr) || + !(n_map.second.single_map.cond_map.empty()), + "state var map cannot be empty for " + n_map.first); + ERRIF(!(n_map.second.externmem_map.empty()) && + (n_map.second.single_map.single_map.get() != nullptr), + "duplicate state var map for " + n_map.first); + ERRIF(!(n_map.second.single_map.cond_map.empty()) && + (n_map.second.single_map.single_map.get() != nullptr), + "duplicate state var map for " + n_map.first); + ERRIF(!(n_map.second.externmem_map.empty()) && + (!n_map.second.single_map.cond_map.empty()), + "duplicate state var map for " + n_map.first); } std::set custom_reset_seq_name; std::set custom_clock_seq_name; { // for reset, valid name, domain names are defs unsigned seq_len = 0; - for (const auto & n_seq : reset_specification.custom_reset_sequence) { - ERRIF( !is_valid_id_name(n_seq.first), - "Custom reset sequence name " - << n_seq.first - << " is not valid" ); - ERRIF( IN(n_seq.first, custom_reset_seq_name) , "reset sequence name " + n_seq.first + "has been used multiple times" ); - + for (const auto& n_seq : reset_specification.custom_reset_sequence) { + ERRIF(!is_valid_id_name(n_seq.first), + "Custom reset sequence name " << n_seq.first << " is not valid"); + ERRIF(IN(n_seq.first, custom_reset_seq_name), + "reset sequence name " + n_seq.first + + "has been used multiple times"); + custom_reset_seq_name.insert(n_seq.first); - ERRIF( n_seq.second.size() == 0, "Empty reset sequence for " + n_seq.first ); + ERRIF(n_seq.second.size() == 0, + "Empty reset sequence for " + n_seq.first); if (seq_len == 0) seq_len = n_seq.second.size(); - ERRIF( seq_len != reset_specification.reset_cycle , "Customized reset sequence does not match the cycle count" ); + ERRIF(seq_len != reset_specification.reset_cycle, + "Customized reset sequence does not match the cycle count"); - ERRIF( seq_len != n_seq.second.size(), "Reset sequence should be of same length" ); + ERRIF(seq_len != n_seq.second.size(), + "Reset sequence should be of same length"); } } - { // for clock, valid name, check no empty sequence, sequence of the same length + { // for clock, valid name, check no empty sequence, sequence of the same + // length unsigned seq_len = 0; - for (const auto & n_seq : clock_specification.custom_clock_sequence) { - ERRIF( !is_valid_id_name(n_seq.first), - "Custom clock sequence name " - << n_seq.first - << " is not valid" ); - ERRIF( IN(n_seq.first, custom_clock_seq_name) , "clock sequence name " + n_seq.first + "has been used multiple times" ); - + for (const auto& n_seq : clock_specification.custom_clock_sequence) { + ERRIF(!is_valid_id_name(n_seq.first), + "Custom clock sequence name " << n_seq.first << " is not valid"); + ERRIF(IN(n_seq.first, custom_clock_seq_name), + "clock sequence name " + n_seq.first + + "has been used multiple times"); + custom_clock_seq_name.insert(n_seq.first); - ERRIF( n_seq.second.size() == 0, "Empty clock sequence for " + n_seq.first ); + ERRIF(n_seq.second.size() == 0, + "Empty clock sequence for " + n_seq.first); if (seq_len == 0) seq_len = n_seq.second.size(); - ERRIF( seq_len != clock_specification.gcm_period, "Customized clock does not match the specified length requirement" ); + ERRIF(seq_len != clock_specification.gcm_period, + "Customized clock does not match the specified length requirement"); - ERRIF( seq_len != n_seq.second.size(), "Clock sequence should be of same length" ); + ERRIF(seq_len != n_seq.second.size(), + "Clock sequence should be of same length"); } } { - for (const auto & clkd : custom_clock_seq_name) { - ERRIF( IN(clkd, custom_reset_seq_name) , "Name " + clkd + " has been used multiple times" ); + for (const auto& clkd : custom_clock_seq_name) { + ERRIF(IN(clkd, custom_reset_seq_name), + "Name " + clkd + " has been used multiple times"); } - for (const auto & rstd : custom_reset_seq_name) { - ERRIF( IN(rstd, custom_clock_seq_name) , "Name " + rstd + " has been used multiple times" ); + for (const auto& rstd : custom_reset_seq_name) { + ERRIF(IN(rstd, custom_clock_seq_name), + "Name " + rstd + " has been used multiple times"); } } { // for each interface check domain names are good - for (const auto & n_clks : rtl_interface_connection.clock_domain_defs) { - ERRIF( !IN(n_clks.first, custom_clock_seq_name), "clock domain " + n_clks.first + " is not found" ); + for (const auto& n_clks : rtl_interface_connection.clock_domain_defs) { + ERRIF(!IN(n_clks.first, custom_clock_seq_name), + "clock domain " + n_clks.first + " is not found"); } - for (const auto & n_rsts : rtl_interface_connection.custom_reset_domain_defs) { - ERRIF( !IN(n_rsts.first, custom_reset_seq_name), "reset domain " + n_rsts.first + " is not found" ); + for (const auto& n_rsts : + rtl_interface_connection.custom_reset_domain_defs) { + ERRIF(!IN(n_rsts.first, custom_reset_seq_name), + "reset domain " + n_rsts.first + " is not found"); } } @@ -1092,35 +1238,42 @@ bool VerilogRefinementMap::SelfCheckField() const { { // GeneralVerilogMonitor, for ids are okay, no bad names std::set var_def_names; - for (const auto & n_st : phase_tracker) { - - for (const auto & var_def : n_st.second.event_alias ) { - ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); + for (const auto& n_st : phase_tracker) { + + for (const auto& var_def : n_st.second.event_alias) { + ERRIF(IN(var_def.first, var_def_names), + "Variable " + n_st.first + " has been defined already"); var_def_names.insert(var_def.first); } - for (const auto & var_def : n_st.second.var_defs ) { - ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); + for (const auto& var_def : n_st.second.var_defs) { + ERRIF(IN(var_def.first, var_def_names), + "Variable " + n_st.first + " has been defined already"); var_def_names.insert(var_def.first); } } - for (const auto & n_st : value_recorder) { - ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); - ERRIF( IN(n_st.first, var_def_names) , "Monitor name " + n_st.first + " has been used" ); + for (const auto& n_st : value_recorder) { + ERRIF(!is_valid_id_name(n_st.first), + "Monitor name " + n_st.first + " is not valid"); + ERRIF(IN(n_st.first, var_def_names), + "Monitor name " + n_st.first + " has been used"); var_def_names.insert(n_st.first); } - for (const auto & n_st : customized_monitor) { - ERRIF( !is_valid_id_name(n_st.first) , "Monitor name " + n_st.first + " is not valid" ); - ERRIF( IN(n_st.first, var_def_names) , "Monitor name " + n_st.first + " has been used" ); + for (const auto& n_st : customized_monitor) { + ERRIF(!is_valid_id_name(n_st.first), + "Monitor name " + n_st.first + " is not valid"); + ERRIF(IN(n_st.first, var_def_names), + "Monitor name " + n_st.first + " has been used"); var_def_names.insert(n_st.first); - - for (const auto & var_def : n_st.second.var_defs ) { - ERRIF( IN(var_def.first, var_def_names) , "Variable " + n_st.first + " has been defined already" ); + + for (const auto& var_def : n_st.second.var_defs) { + ERRIF(IN(var_def.first, var_def_names), + "Variable " + n_st.first + " has been defined already"); var_def_names.insert(var_def.first); } } } return true; - // no need to check for inst_cond + // no need to check for inst_cond } // bool VerilogRefinementMap::SelfCheck() const #undef ERRIF diff --git a/src/vtarget-out/directive.cc b/src/vtarget-out/directive.cc index 67525b345..734aa8b0f 100644 --- a/src/vtarget-out/directive.cc +++ b/src/vtarget-out/directive.cc @@ -13,7 +13,7 @@ namespace ilang { #define VLG_TRUE "`true" // ---------------------- class IntefaceDirectiveRecorder -// ------------------------------- +// ------------------------------- void IntefaceDirectiveRecorder::ConnectModuleInputAddWire( const std::string& short_name, unsigned width) { @@ -94,8 +94,8 @@ void IntefaceDirectiveRecorder::ModuleInstSanityCheck( } ILA_CHECK(false) << "Connecting signal: " << the_wire_connected_to_the_port - << " tp: " << conn_tp - << " is not declared. Implementation bug!"; + << " tp: " << conn_tp + << " is not declared. Implementation bug!"; } } // register extra state out name @@ -145,7 +145,7 @@ void IntefaceDirectiveRecorder::RegisterInterface(const SignalInfoBase& vlg_sig, input_wires.push_back({"__VLG_I_" + short_name, width}); mod_inst_rec.insert( {short_name, - inf_connector_t({inf_dir_t::INPUT, "__VLG_I_" + short_name})}); + inf_connector_t({inf_dir_t::INPUT, "__VLG_I_" + short_name})}); } } if (is_output) { @@ -155,16 +155,18 @@ void IntefaceDirectiveRecorder::RegisterInterface(const SignalInfoBase& vlg_sig, output_wires.push_back({"__VLG_O_" + short_name, width}); mod_inst_rec.insert( {short_name, - inf_connector_t({inf_dir_t::SO, "__VLG_O_" + short_name})}); + inf_connector_t({inf_dir_t::SO, "__VLG_O_" + short_name})}); } } } else if (refstr == "**START**") { - ILA_ERROR_IF(!is_input || width != 1) << "Expecting `" << short_name << "` to be input of width 1"; + ILA_ERROR_IF(!is_input || width != 1) + << "Expecting `" << short_name << "` to be input of width 1"; mod_inst_rec.insert( {short_name, - inf_connector_t({inf_dir_t::START, "__START__ | __STARTED__"})}); + inf_connector_t({inf_dir_t::START, "__START__ | __STARTED__"})}); } else if (refstr == "**RESET**") { - ILA_ERROR_IF(!is_input || width != 1) << "Expecting `" << short_name << "` to be input of width 1"; + ILA_ERROR_IF(!is_input || width != 1) + << "Expecting `" << short_name << "` to be input of width 1"; if (_reset_vlg) mod_inst_rec.insert( {short_name, inf_connector_t({inf_dir_t::RESET, "rst"})}); @@ -172,7 +174,8 @@ void IntefaceDirectiveRecorder::RegisterInterface(const SignalInfoBase& vlg_sig, mod_inst_rec.insert( {short_name, inf_connector_t({inf_dir_t::RESET, "dummy_reset"})}); } else if (refstr == "**NRESET**") { - ILA_ERROR_IF(!is_input || width != 1) << "Expecting `" << short_name << "` to be input of width 1"; + ILA_ERROR_IF(!is_input || width != 1) + << "Expecting `" << short_name << "` to be input of width 1"; if (_reset_vlg) mod_inst_rec.insert( {short_name, inf_connector_t({inf_dir_t::RESET, "~rst"})}); @@ -180,13 +183,14 @@ void IntefaceDirectiveRecorder::RegisterInterface(const SignalInfoBase& vlg_sig, mod_inst_rec.insert( {short_name, inf_connector_t({inf_dir_t::RESET, "~dummy_reset"})}); } else if (refstr == "**CLOCK**") { - ILA_ERROR_IF(!is_input || width != 1) << "Expecting `" << short_name << "` to be input of width 1"; + ILA_ERROR_IF(!is_input || width != 1) + << "Expecting `" << short_name << "` to be input of width 1"; mod_inst_rec.insert( {short_name, inf_connector_t({inf_dir_t::CLOCK, "clk"})}); } else ILA_ASSERT(false) << "Implementation error. Should not be reachable."; // decide how to connect and signals to create - return; + return; } // IntefaceDirectiveRecorder::RegisterInterface void IntefaceDirectiveRecorder::Clear(bool reset_vlg) { @@ -198,6 +202,4 @@ void IntefaceDirectiveRecorder::Clear(bool reset_vlg) { _reset_vlg = reset_vlg; } - - } // namespace ilang diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 6f160a474..83f35daf5 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -13,7 +13,7 @@ #include #include -#include +#include namespace ilang { @@ -110,7 +110,6 @@ bool VlgSglTgtGen::TryFindVlgState(const std::string& sname) { return false; } - // static function unsigned VlgSglTgtGen::TypeMatched(const ExprPtr& ila_var, const SignalInfoBase& vlg_var) { @@ -156,23 +155,22 @@ unsigned VlgSglTgtGen::get_width(const ExprPtr& n) { return VerilogGeneratorBase::get_width(n); } +rfmap::RfVarTypeOrig +VlgSglTgtGen::VarTypeCheckForRfExprParsing(const std::string& vname) { -rfmap::RfVarTypeOrig VlgSglTgtGen::VarTypeCheckForRfExprParsing(const std::string & vname) { - - if(StrStartsWith(vname,"ILA.")) { + if (StrStartsWith(vname, "ILA.")) { rfmap::RfVarTypeOrig ret; - if(TryFindIlaInput(vname)) { + if (TryFindIlaInput(vname)) { const ExprPtr ila_input_ptr = IlaGetInput(vname.substr(4)); ret.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::ILAI; - + ret.type = rfmap::RfMapVarType( - ila_input_ptr->is_bool() ? - 1 : ila_input_ptr->sort()->bit_width()); + ila_input_ptr->is_bool() ? 1 : ila_input_ptr->sort()->bit_width()); return ret; - } else if(TryFindIlaState(vname)) { + } else if (TryFindIlaState(vname)) { const ExprPtr ila_sv_ptr = IlaGetState(vname.substr(4)); ret.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::ILAS; - if(ila_sv_ptr->is_bool()) + if (ila_sv_ptr->is_bool()) ret.type = rfmap::RfMapVarType(1); else if (ila_sv_ptr->is_bv()) ret.type = rfmap::RfMapVarType(ila_sv_ptr->sort()->bit_width()); @@ -186,44 +184,44 @@ rfmap::RfVarTypeOrig VlgSglTgtGen::VarTypeCheckForRfExprParsing(const std::strin ILA_ERROR << "Cannot find ila var: " << vname; return ret; } // else if - if (StrStartsWith(vname,"RTL.")) { + if (StrStartsWith(vname, "RTL.")) { ILA_ERROR_IF(!TryFindVlgState(vname)) << "Cannot find rtl var: " << vname; auto sig_info = vlg_info_ptr->get_signal(vname); auto aw_range = sig_info.get_addr_range_size(); auto dw = sig_info.get_width(); - + rfmap::RfVarTypeOrig ret; ret.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::RTLV; - if(aw_range == 0) // not an array + if (aw_range == 0) // not an array ret.type = rfmap::RfMapVarType(dw); else { unsigned aw = (unsigned)(std::ceil(std::log2(aw_range))); // [15:0] -> aw_range == 16 -> 4 -> ceil (4) == 4 - ret.type = rfmap::RfMapVarType(aw,dw); + ret.type = rfmap::RfMapVarType(aw, dw); } - return ret; + return ret; } - //if(!StrStartsWith(vname,"ILA.") && !StrStartsWith(vname,"RTL.")) + // if(!StrStartsWith(vname,"ILA.") && !StrStartsWith(vname,"RTL.")) return rfmap::RfVarTypeOrig(); // unknown } // VarTypeCheckForRfExprParsing -rfmap::VarReplacement VlgSglTgtGen::CreateVarReplacement( - const rfmap::RfVar & var, bool replace_internal_names) -{ +rfmap::VarReplacement +VlgSglTgtGen::CreateVarReplacement(const rfmap::RfVar& var, + bool replace_internal_names) { const auto n = var->get_name(); - + rfmap::RfVarTypeOrig tp; { // retrieve its old type auto anno = var->get_annotation(); - if(anno) + if (anno) tp = *anno; } auto pos_def_var = refinement_map.all_var_def_types.find(n.first); - - if(n.second) { // if it is special name - if(pos_def_var != refinement_map.all_var_def_types.end()) { + + if (n.second) { // if it is special name + if (pos_def_var != refinement_map.all_var_def_types.end()) { tp.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR; tp.type = rfmap::RfMapVarType(pos_def_var->second.width); } else { @@ -232,19 +230,20 @@ rfmap::VarReplacement VlgSglTgtGen::CreateVarReplacement( } } else { // if it is not special name auto rtl_ila_tp = VarTypeCheckForRfExprParsing(n.first); - if(!rtl_ila_tp.type.is_unknown()) + if (!rtl_ila_tp.type.is_unknown()) tp = rtl_ila_tp; - else if(pos_def_var != refinement_map.all_var_def_types.end()) { + else if (pos_def_var != refinement_map.all_var_def_types.end()) { tp.var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR; tp.type = rfmap::RfMapVarType(pos_def_var->second.width); } } - ILA_WARN_IF(tp.type.is_unknown()) << "type of var: " << (n.second?"#":"") << n.first << " is still unknown."; + ILA_WARN_IF(tp.type.is_unknown()) << "type of var: " << (n.second ? "#" : "") + << n.first << " is still unknown."; - if(tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::RTLV) { + if (tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::RTLV) { bool is_array = tp.type.is_array(); // you can never connect an array out - if(!replace_internal_names || is_array) { + if (!replace_internal_names || is_array) { auto ret_copy = std::make_shared(*var); ret_copy->set_annotation(std::make_shared(tp)); return rfmap::VarReplacement(var, ret_copy); @@ -256,100 +255,101 @@ rfmap::VarReplacement VlgSglTgtGen::CreateVarReplacement( return rfmap::VarReplacement(var, new_node); } else if (tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::ILAI) { - const auto & ila_sn = n.first; + const auto& ila_sn = n.first; auto dotpos = ila_sn.find('.'); - ILA_ASSERT(ila_sn.substr(0,dotpos+1) == "ILA."); + ILA_ASSERT(ila_sn.substr(0, dotpos + 1) == "ILA."); bool is_array = tp.type.is_array(); // you can never connect an array out - ILA_CHECK(!is_array) << "Implementation bug: currently does not support array as input"; + ILA_CHECK(!is_array) + << "Implementation bug: currently does not support array as input"; - - auto new_name = "__ILA_I_" + ila_sn.substr(dotpos+1); + auto new_name = "__ILA_I_" + ila_sn.substr(dotpos + 1); auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); new_node->set_annotation(std::make_shared(tp)); return rfmap::VarReplacement(var, new_node); } else if (tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::ILAS) { - const auto & ila_sn = n.first; + const auto& ila_sn = n.first; auto dotpos = ila_sn.find('.'); - ILA_ASSERT(ila_sn.substr(0,dotpos+1) == "ILA."); + ILA_ASSERT(ila_sn.substr(0, dotpos + 1) == "ILA."); bool is_array = tp.type.is_array(); // you can never connect an array out - // so there should not be such things like: __ILA_SO_array - if(is_array) { // basically no replacement + // so there should not be such things like: __ILA_SO_array + if (is_array) { // basically no replacement auto ret_copy = std::make_shared(*var); ret_copy->set_annotation(std::make_shared(tp)); return rfmap::VarReplacement(var, ret_copy); } - auto new_name = "__ILA_SO_" + ila_sn.substr(dotpos+1); + auto new_name = "__ILA_SO_" + ila_sn.substr(dotpos + 1); auto new_node = verilog_expr::VExprAst::MakeSpecialName(new_name); new_node->set_annotation(std::make_shared(tp)); return rfmap::VarReplacement(var, new_node); - } else if ( - tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::INTERNAL || - tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR - ) { - ILA_ERROR_IF(StrStartsWith(n.first,"$")) << "Creating non replace-able var " << n.first; - if(var->get_annotation() == nullptr) { + } else if (tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::INTERNAL || + tp.var_ref_type == rfmap::RfVarTypeOrig::VARTYPE::DEFINE_VAR) { + ILA_ERROR_IF(StrStartsWith(n.first, "$")) + << "Creating non replace-able var " << n.first; + if (var->get_annotation() == nullptr) { var->set_annotation(std::make_shared(tp)); } return rfmap::VarReplacement(var, var); } - + ILA_ERROR << "Unknown how to replace var: " << n.first << " will keep it"; auto ret_copy = std::make_shared(*var); ret_copy->set_annotation(std::make_shared(tp)); return rfmap::VarReplacement(var, ret_copy); } -rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr & in) { +rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr& in) { bool replace_dot = _backend != VlgSglTgtGen::backend_selector::JASPERGOLD; std::unordered_map vars; refinement_map.GetVars(in, vars); - for (const auto & v : vars) { - rfmap::VarReplacement * repl = refinement_map.CheckReplacement(v.first); + for (const auto& v : vars) { + rfmap::VarReplacement* repl = refinement_map.CheckReplacement(v.first); if (repl == NULL) { - rfmap::VarReplacement new_repl = CreateVarReplacement(v.second, replace_dot); + rfmap::VarReplacement new_repl = + CreateVarReplacement(v.second, replace_dot); - ILA_DLOG("gen_util.create_var_replacement") << new_repl.origvar->to_verilog() - << " --> " << new_repl.newvar->to_verilog(); + ILA_DLOG("gen_util.create_var_replacement") + << new_repl.origvar->to_verilog() << " --> " + << new_repl.newvar->to_verilog(); - refinement_map.RegisterInternalVariableWithMapping( - v.first, new_repl); + refinement_map.RegisterInternalVariableWithMapping(v.first, new_repl); repl = refinement_map.CheckReplacement(v.first); } ILA_NOT_NULL(repl); - ILA_DLOG("gen_util.use_var_replacement") << repl->origvar->to_verilog() - << " --> " << repl->newvar->to_verilog(); + ILA_DLOG("gen_util.use_var_replacement") + << repl->origvar->to_verilog() << " --> " << repl->newvar->to_verilog(); } - + auto new_node = refinement_map.ReplacingRtlIlaVar(in); - // AnnotateType requires all + // AnnotateType requires all refinement_map.AnnotateType(new_node); return new_node; } -rfmap::RfExpr VlgSglTgtGen::TranslateMap(const rfmap::RfExpr & in, const std::string & ila_vn) { - if(refinement_map.IsLastLevelBooleanOp(in)) +rfmap::RfExpr VlgSglTgtGen::TranslateMap(const rfmap::RfExpr& in, + const std::string& ila_vn) { + if (refinement_map.IsLastLevelBooleanOp(in)) return in; - auto vnode = rfmap_var("ILA."+ila_vn); + auto vnode = rfmap_var("ILA." + ila_vn); auto eq_node = rfmap_eq(vnode, in); return eq_node; } rfmap::RfExpr VlgSglTgtGen::condition_map_to_rfexpr( - const std::vector> & cond_map, - const std::string & ila_state_name) -{ + const std::vector>& cond_map, + const std::string& ila_state_name) { std::vector all_mappings; rfmap::RfExpr prev_neg; // make sure it is a priority condition lists - for (const auto & cond_map_pair : cond_map) { + for (const auto& cond_map_pair : cond_map) { rfmap::RfExpr cond = cond_map_pair.first; if (prev_neg != nullptr) cond = rfmap_and(prev_neg, cond); - rfmap::RfExpr single_map = TranslateMap(cond_map_pair.second, ila_state_name); - all_mappings.push_back( rfmap_imply(cond, single_map) ); + rfmap::RfExpr single_map = + TranslateMap(cond_map_pair.second, ila_state_name); + all_mappings.push_back(rfmap_imply(cond, single_map)); if (prev_neg == nullptr) prev_neg = rfmap_not(cond); else @@ -359,13 +359,11 @@ rfmap::RfExpr VlgSglTgtGen::condition_map_to_rfexpr( return rfmap_and(all_mappings); } // end of condition_map_to_str - rfmap::RfExpr VlgSglTgtGen::condition_map_bv_to_rfexpr( - const std::vector> & cond_map) -{ + const std::vector>& cond_map) { rfmap::RfExpr ret; - for(auto pos = cond_map.rbegin(); pos != cond_map.rend(); ++pos) { - if(ret == nullptr) + for (auto pos = cond_map.rbegin(); pos != cond_map.rend(); ++pos) { + if (ret == nullptr) ret = pos->second; else ret = rfmap_ite(pos->first, pos->second, ret); @@ -373,24 +371,22 @@ rfmap::RfExpr VlgSglTgtGen::condition_map_bv_to_rfexpr( return ret; } // end of condition_map_to_str - -rfmap::RfExpr VlgSglTgtGen::singlemap_bv_to_rfexpr( - const rfmap::SingleVarMap & single_map) { - if(single_map.single_map != nullptr) { +rfmap::RfExpr +VlgSglTgtGen::singlemap_bv_to_rfexpr(const rfmap::SingleVarMap& single_map) { + if (single_map.single_map != nullptr) { return single_map.single_map; } else { return condition_map_bv_to_rfexpr(single_map.cond_map); } // end map type } -rfmap::RfExpr VlgSglTgtGen::singlemap_to_rfexpr( - const rfmap::SingleVarMap & single_map, - const std::string & ila_state_name) -{ - if(single_map.single_map != nullptr) { +rfmap::RfExpr +VlgSglTgtGen::singlemap_to_rfexpr(const rfmap::SingleVarMap& single_map, + const std::string& ila_state_name) { + if (single_map.single_map != nullptr) { return (TranslateMap(single_map.single_map, ila_state_name)); } else { - auto map_str = condition_map_to_rfexpr( single_map.cond_map, ila_state_name); + auto map_str = condition_map_to_rfexpr(single_map.cond_map, ila_state_name); return (map_str); } // end map type } // non_mem_map_to_str @@ -399,149 +395,153 @@ rfmap::RfExpr VlgSglTgtGen::singlemap_to_rfexpr( // problem_name, true_for_assumpt_false_for_assert // prefix, suffix are all fixed void VlgSglTgtGen::Gen_input_map_assumpt(const std::string& ila_input_name, - const rfmap::IlaVarMapping &imap, const std::string & problem_name) { + const rfmap::IlaVarMapping& imap, + const std::string& problem_name) { bool is_mem = _host->input(ila_input_name)->is_mem(); ILA_ERROR_IF(is_mem) << "Mem as input is not supported yet"; ILA_ERROR_IF(imap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) - << "ila sv " << ila_input_name << " cannot be mapped as external mem!"; + << "ila sv " << ila_input_name << " cannot be mapped as external mem!"; // NOTE: non_mem_map_to_str will use translate map // but it should be able to distinguish input from state var auto map_rfexpr = singlemap_to_rfexpr(imap.single_map, ila_input_name); add_an_assumption(rfmap_imply(rfmap_var("decode"), map_rfexpr), problem_name); } -void VlgSglTgtGen::Gen_varmap_assumpt_assert(const std::string& ila_state_name, - const rfmap::IlaVarMapping &vmap, - const std::string & problem_name, - bool true_for_assumpt_false_for_assert) { +void VlgSglTgtGen::Gen_varmap_assumpt_assert( + const std::string& ila_state_name, const rfmap::IlaVarMapping& vmap, + const std::string& problem_name, bool true_for_assumpt_false_for_assert) { // NOTE: prefix has ( ~ __START__ || ... // and suffix has .. ) - -#define ADD_CONSTR(p1) do{ \ - if(true_for_assumpt_false_for_assert) \ - add_an_assumption(rfmap_imply(rfmap_var("decode"), (p1) ), problem_name); \ - else \ - add_an_assertion(rfmap_imply(rfmap_var("commit"), (p1) ), problem_name); \ - }while(0) - + +#define ADD_CONSTR(p1) \ + do { \ + if (true_for_assumpt_false_for_assert) \ + add_an_assumption(rfmap_imply(rfmap_var("decode"), (p1)), problem_name); \ + else \ + add_an_assertion(rfmap_imply(rfmap_var("commit"), (p1)), problem_name); \ + } while (0) + bool is_mem = _host->state(ila_state_name)->is_mem(); - if(vmap.type != rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { + if (vmap.type != rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { auto map_str = singlemap_to_rfexpr(vmap.single_map, ila_state_name); ADD_CONSTR(map_str); } else { // if(vmap.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) { - // TODO: (note: multiple ports!) - // assume : START |-> - // ( ila.ren && rtl.renexpr && (ila.raddr == rtl.raddrexpr) |-> - // (ila.rdata === rtl.rdataexpr) ) + // TODO: (note: multiple ports!) + // assume : START |-> + // ( ila.ren && rtl.renexpr && (ila.raddr == rtl.raddrexpr) |-> + // (ila.rdata === rtl.rdataexpr) ) - ILA_ERROR_IF(!is_mem) - << "ila sv " << ila_state_name << " is not memory!"; + ILA_ERROR_IF(!is_mem) << "ila sv " << ila_state_name << " is not memory!"; - if(true_for_assumpt_false_for_assert) { + if (true_for_assumpt_false_for_assert) { // mem read assumption - if(vlg_ila.ila_rports.find(ila_state_name) != vlg_ila.ila_rports.end()) { - const auto & read_ports = vlg_ila.ila_rports.at(ila_state_name); + if (vlg_ila.ila_rports.find(ila_state_name) != vlg_ila.ila_rports.end()) { + const auto& read_ports = vlg_ila.ila_rports.at(ila_state_name); unsigned rfmap_node_idx = 0; - for(const auto & rport : read_ports) { + for (const auto& rport : read_ports) { size_t no = rport.first; - auto ila_raddr = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_raddr"); - auto ila_rdata = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_rdata"); + auto ila_raddr = rfmap_var("__IMEM_" + ila_state_name + "_" + + IntToStr(no) + "_raddr"); + auto ila_rdata = rfmap_var("__IMEM_" + ila_state_name + "_" + + IntToStr(no) + "_rdata"); - while(!(vmap.externmem_map.at(rfmap_node_idx).rport_mapped) - && rfmap_node_idx < vmap.externmem_map.size()) - ++ rfmap_node_idx; + while (!(vmap.externmem_map.at(rfmap_node_idx).rport_mapped) && + rfmap_node_idx < vmap.externmem_map.size()) + ++rfmap_node_idx; ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) - <<"#ila.read-port=" << read_ports.size() << " does not match #rfmap.read-port" - <<", and this is a mismatch for sname:" << ila_state_name; - - const auto & rfmap_rport = vmap.externmem_map.at(rfmap_node_idx); - + << "#ila.read-port=" << read_ports.size() + << " does not match #rfmap.read-port" + << ", and this is a mismatch for sname:" << ila_state_name; + + const auto& rfmap_rport = vmap.externmem_map.at(rfmap_node_idx); + // expect bit-vector rather than booleans auto rtl_ren = singlemap_bv_to_rfexpr(rfmap_rport.ren_map); auto rtl_raddr = singlemap_bv_to_rfexpr(rfmap_rport.raddr_map); auto rtl_rdata = singlemap_bv_to_rfexpr(rfmap_rport.rdata_map); - - auto constr = rfmap_imply( rfmap_and( - {rtl_ren, rfmap_eq(ila_raddr, rtl_raddr)}), - rfmap_eq(ila_rdata, rtl_rdata)); + + auto constr = + rfmap_imply(rfmap_and({rtl_ren, rfmap_eq(ila_raddr, rtl_raddr)}), + rfmap_eq(ila_rdata, rtl_rdata)); ADD_CONSTR(constr); - ++ rfmap_node_idx; + ++rfmap_node_idx; } // for each read port - } // if there is such port + } // if there is such port } else { // assert : IEND |-> - // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> - // (ila.wdata_d1 == rtl.wdataexpr) && (ila.waddr_d1 == rtl.waddrexpr) ) ) - + // ( ila.wen_d1 == rtl.wenexpr && ( ila.wen |-> + // (ila.wdata_d1 == rtl.wdataexpr) && (ila.waddr_d1 == + // rtl.waddrexpr) ) ) + // mem write assertion // vlg_ila.ila_wports - if(vlg_ila.ila_wports.find(ila_state_name) != vlg_ila.ila_wports.end()) { - const auto & write_ports = vlg_ila.ila_wports.at(ila_state_name); + if (vlg_ila.ila_wports.find(ila_state_name) != vlg_ila.ila_wports.end()) { + const auto& write_ports = vlg_ila.ila_wports.at(ila_state_name); unsigned rfmap_node_idx = 0; - for(const auto & wport : write_ports) { + for (const auto& wport : write_ports) { // the reason for _d1: see ConstructWrapper_get_ila_module_inst // in single_target_connect.cc size_t no = wport.first; - auto ila_wen = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_wen" + "_d1"); - auto ila_waddr = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_waddr" + "_d1"); - auto ila_wdata = rfmap_var("__IMEM_" + ila_state_name + "_" + IntToStr(no) + "_wdata" + "_d1"); + auto ila_wen = rfmap_var("__IMEM_" + ila_state_name + "_" + + IntToStr(no) + "_wen" + "_d1"); + auto ila_waddr = rfmap_var("__IMEM_" + ila_state_name + "_" + + IntToStr(no) + "_waddr" + "_d1"); + auto ila_wdata = rfmap_var("__IMEM_" + ila_state_name + "_" + + IntToStr(no) + "_wdata" + "_d1"); - while(!(vmap.externmem_map.at(rfmap_node_idx).wport_mapped) - && rfmap_node_idx < vmap.externmem_map.size()) - ++ rfmap_node_idx; + while (!(vmap.externmem_map.at(rfmap_node_idx).wport_mapped) && + rfmap_node_idx < vmap.externmem_map.size()) + ++rfmap_node_idx; ILA_ERROR_IF(rfmap_node_idx >= vmap.externmem_map.size()) - <<"#ila.write-port=" << write_ports.size() << " does not match #rfmap.write-port" - <<", and this is a mismatch for sname:" << ila_state_name; - - const auto & rfmap_wport = vmap.externmem_map.at(rfmap_node_idx); - + << "#ila.write-port=" << write_ports.size() + << " does not match #rfmap.write-port" + << ", and this is a mismatch for sname:" << ila_state_name; + + const auto& rfmap_wport = vmap.externmem_map.at(rfmap_node_idx); + auto rtl_wen = singlemap_bv_to_rfexpr(rfmap_wport.wen_map); auto rtl_waddr = singlemap_bv_to_rfexpr(rfmap_wport.waddr_map); auto rtl_wdata = singlemap_bv_to_rfexpr(rfmap_wport.wdata_map); - - auto constr = - rfmap_and( - rfmap_eq(ila_wen , rtl_wen), - rfmap_imply(ila_wen, - rfmap_and( - rfmap_eq(ila_waddr, rtl_waddr), - rfmap_eq(ila_wdata, rtl_wdata)))); - + + auto constr = rfmap_and( + rfmap_eq(ila_wen, rtl_wen), + rfmap_imply(ila_wen, rfmap_and(rfmap_eq(ila_waddr, rtl_waddr), + rfmap_eq(ila_wdata, rtl_wdata)))); + ADD_CONSTR(constr); - ++ rfmap_node_idx; + ++rfmap_node_idx; } // for each write port - } // end of if wport found - } // end of if assume else assert + } // end of if wport found + } // end of if assume else assert } #undef ADD_CONSTR } // end of Gen_varmap_assumpt_assert - -void VlgSglTgtGen::handle_start_condition(const std::vector & dc) { - for (const auto & c : dc) { - //cond = ReplaceAll(ReplaceAll(cond, "$decode", vlg_ila.decodeNames[0]), +void VlgSglTgtGen::handle_start_condition( + const std::vector& dc) { + for (const auto& c : dc) { + // cond = ReplaceAll(ReplaceAll(cond, "$decode", vlg_ila.decodeNames[0]), // "$valid", vlg_ila.validName); - add_an_assumption( - rfmap_imply(rfmap_var("__START__"), c), "start_condition"); + add_an_assumption(rfmap_imply(rfmap_var("__START__"), c), + "start_condition"); } } // handle_start_condition - - /// register a reg in refinement_map.all_var_def_type -void VlgSglTgtGen::rfmap_add_internal_reg(const std::string &n, unsigned width) { +void VlgSglTgtGen::rfmap_add_internal_reg(const std::string& n, + unsigned width) { rfmap::TypedVerilogRefinementMap::VarDef def; def.type = rfmap::TypedVerilogRefinementMap::VarDef::var_type::REG; def.width = width; @@ -549,7 +549,8 @@ void VlgSglTgtGen::rfmap_add_internal_reg(const std::string &n, unsigned width) } /// register a wire in refinement_map.all_var_def_type -void VlgSglTgtGen::rfmap_add_internal_wire(const std::string &n, unsigned width) { +void VlgSglTgtGen::rfmap_add_internal_wire(const std::string& n, + unsigned width) { rfmap::TypedVerilogRefinementMap::VarDef def; def.type = rfmap::TypedVerilogRefinementMap::VarDef::var_type::WIRE; def.width = width; @@ -561,14 +562,15 @@ void VlgSglTgtGen::rfmap_add_internal_wire(const std::string &n, unsigned width) /// (Note 1: ReplExpr will also create replacement, but it will not use /// this function. 2: will require that the new one has been registered /// in refinement_map.all_var_def_type) -/// !!! should only be used to add +/// !!! should only be used to add /// decode -> __START__ /// commit -> __IEND__ /// $decode -> vlg_ila.decode_signal -/// $valid -> vlg_ila.valid_signal +/// $valid -> vlg_ila.valid_signal /// !!! whose var_def are include in refinement_map -void VlgSglTgtGen::rfmap_add_replacement(const std::string &old, const std::string &n) { +void VlgSglTgtGen::rfmap_add_replacement(const std::string& old, + const std::string& n) { auto def_pos = refinement_map.all_var_def_types.find(n); ILA_CHECK(def_pos != refinement_map.all_var_def_types.end()); auto oldexpr = rfmap_var(old); @@ -578,8 +580,7 @@ void VlgSglTgtGen::rfmap_add_replacement(const std::string &old, const std::stri tp->var_ref_type = rfmap::RfVarTypeOrig::VARTYPE::INTERNAL; newexpr->set_annotation(tp); refinement_map.RegisterInternalVariableWithMapping( - old, rfmap::VarReplacement(oldexpr, newexpr)); + old, rfmap::VarReplacement(oldexpr, newexpr)); } // rfmap_add_replacement - }; // namespace ilang diff --git a/src/vtarget-out/inv-syn/grain_inv_parse.cc b/src/vtarget-out/inv-syn/grain_inv_parse.cc index fd4c2b264..15bcb5fc1 100644 --- a/src/vtarget-out/inv-syn/grain_inv_parse.cc +++ b/src/vtarget-out/inv-syn/grain_inv_parse.cc @@ -71,7 +71,6 @@ bool GrainInvariantParser::ParseInvResultFromFile(const std::string& fname) { // -------------------------CALL BACK // FUNS-------------------------------------------------------------------- - /// this is actually declare variables void GrainInvariantParser::declare_function(const std::string& name, SortPtrT sort) { @@ -104,27 +103,26 @@ void GrainInvariantParser::declare_function(const std::string& name, } else { converted_name = "__TOP_dot_" + vlg_name + "__"; } - free_vars.insert(std::make_pair(converted_name, get_sort(sort).GetBoolBvWidth())); + free_vars.insert( + std::make_pair(converted_name, get_sort(sort).GetBoolBvWidth())); } else // else do not convert converted_name = vlg_name; } // save it term_pool.push_back(SmtTermInfoVerilog(converted_name, get_sort(sort), this)); - quantifier_def_stack.back().emplace(name, term_pool.size()-1); + quantifier_def_stack.back().emplace(name, term_pool.size() - 1); } // declare_function // --------------------- DISABLE THESE FUNCTIONS ------------------------ // /// call back function to handle (forall -GrainInvariantParser::TermPtrT -GrainInvariantParser::push_quantifier_scope() { +GrainInvariantParser::TermPtrT GrainInvariantParser::push_quantifier_scope() { ILA_CHECK(false) << "push_quantifier_scope should not appear in Grain CHC result"; return 0; } /// call back function to handle ) of forall -GrainInvariantParser::TermPtrT -GrainInvariantParser::pop_quantifier_scope() { +GrainInvariantParser::TermPtrT GrainInvariantParser::pop_quantifier_scope() { ILA_CHECK(false) << "pop_quantifier_scope should not appear in Grain CHC result"; return 0; @@ -145,10 +143,9 @@ void GrainInvariantParser::declare_quantified_variable(const std::string& name, /// or (pred (pred state)) ... you need to pass the right instance name allow /// side GrainInvariantParser::TermPtrT -GrainInvariantParser::mk_function( - const std::string& name, SortPtrT sort, - const std::vector& idx, - const std::vector& args) { +GrainInvariantParser::mk_function(const std::string& name, SortPtrT sort, + const std::vector& idx, + const std::vector& args) { // we don't really rely on the sort here: actually it should be NULL ILA_DLOG("GrainInvariantParser.mk_function") << "make func:" << name << ", #arg" << args.size() << std::endl; @@ -165,11 +162,10 @@ GrainInvariantParser::mk_function( return 0; // should not be reachable } // mk_function -void GrainInvariantParser::define_function( - const std::string& func_name, - const std::vector& args, - SortPtrT ret_type, - TermPtrT func_body) { +void GrainInvariantParser::define_function(const std::string& func_name, + const std::vector& args, + SortPtrT ret_type, + TermPtrT func_body) { ILA_CHECK(false) << "define_function should not appear in Grain CHC result, func:" << func_name; diff --git a/src/vtarget-out/inv-syn/inv_abc_parse.cc b/src/vtarget-out/inv-syn/inv_abc_parse.cc index 0d3193b59..f3f8801ad 100644 --- a/src/vtarget-out/inv-syn/inv_abc_parse.cc +++ b/src/vtarget-out/inv-syn/inv_abc_parse.cc @@ -64,12 +64,12 @@ void AbcInvariantParser::parseAigerResultWoGLA( const auto new_name = vec.at(3) + "[" + bit_no + ":" + bit_no + "]"; const auto blif_ref_name = vec.at(3) + "[" + bit_no + "]"; ILA_CHECK(aig_state_order.size() == latch_no || - aig_state_order.size() == latch_no + 1) + aig_state_order.size() == latch_no + 1) << new_name << " " << latch_no << " " << aig_state_order.size(); if (IN(blif_ref_name, blif_valid_state_names) || (IN(vec.at(3), blif_valid_state_names) && bit_no == "0")) { ILA_CHECK(aig_state_order.size() == - latch_no); // insert to the right index + latch_no); // insert to the right index aig_state_order.push_back(new_name); aig_literal.push_back(std::make_pair(vec.at(3), StrToInt(bit_no))); } @@ -102,7 +102,7 @@ void AbcInvariantParser::parseAigerResultWoGLA( unsigned long long flopno = flop >> 1; std::string literal; ILA_CHECK(aig_state_order.size() >= - flopno) // remeber : the last one should be one + flopno) // remeber : the last one should be one << "Referring #" << flopno << " flop, while size of blifstates:" << aig_state_order.size(); @@ -155,7 +155,7 @@ void AbcInvariantParser::parseAigerResultWoGLA( // void the cube if abnormal if (remove_this_cube) // cube_has_abnormal_var || cube = "1'b0"; // cube = "1'b0"; // under-approximate it : total - // under-approximate + // under-approximate else { // if at least the cube has a normal var, it is a normal cube has_a_normal_cube = true; // only if this cube is not removed, we will add it @@ -223,12 +223,12 @@ void AbcInvariantParser::parseAigerResultWithGLA( const auto new_name = vec.at(3) + "[" + bit_no + ":" + bit_no + "]"; const auto blif_ref_name = vec.at(3) + "[" + bit_no + "]"; ILA_CHECK(aig_state_order.size() == latch_no || - aig_state_order.size() == latch_no + 1) + aig_state_order.size() == latch_no + 1) << new_name << " " << latch_no << " " << aig_state_order.size(); if (IN(blif_ref_name, blif_valid_state_names) || (IN(vec.at(3), blif_valid_state_names) && bit_no == "0")) { ILA_CHECK(aig_state_order.size() == - latch_no); // insert to the right index + latch_no); // insert to the right index aig_state_order.push_back(new_name); aig_literal.push_back(std::make_pair(vec.at(3), StrToInt(bit_no))); } @@ -336,7 +336,7 @@ void AbcInvariantParser::parseAigerResultWithGLA( // void the cube if abnormal if (remove_this_cube) // cube_has_abnormal_var || cube = "1'b0"; // cube = "1'b0"; // under-approximate it : total - // under-approximate + // under-approximate else { // if at least the cube has a normal var, it is a normal cube has_a_normal_cube = true; // only if this cube is not removed, we will add it @@ -469,7 +469,7 @@ void AbcInvariantParser::parse(const std::string& blif_name, // void the cube if abnormal if (remove_this_cube) // cube_has_abnormal_var || cube = "1'b0"; // cube = "1'b0"; // under-approximate it : total - // under-approximate + // under-approximate else { // if at least the cube has a normal var, it is a normal cube has_a_normal_cube = true; // only if this cube is not removed, we will add it @@ -610,7 +610,7 @@ void AbcInvariantParser::parse(const std::string& blif_name, // void the cube if abnormal if (remove_this_cube) // cube_has_abnormal_var || cube = "1'b0"; // cube = "1'b0"; // under-approximate it : total - // under-approximate + // under-approximate else { has_a_normal_cube = true; if (parse_result.empty()) diff --git a/src/vtarget-out/inv-syn/inv_obj.cc b/src/vtarget-out/inv-syn/inv_obj.cc index 7734c69b7..a0cebf209 100644 --- a/src/vtarget-out/inv-syn/inv_obj.cc +++ b/src/vtarget-out/inv-syn/inv_obj.cc @@ -113,10 +113,9 @@ bool InvariantObject::AddInvariantFromChcResultFile( smt_formula_vec.push_back(raw_smt); for (auto&& name_vlg_pair : parser.GetLocalVarDefs()) { - const auto & t = parser.get_term(name_vlg_pair.second); - inv_extra_vlg_vars.push_back( - std::make_tuple(name_vlg_pair.first, t._translate, - t._type.GetBoolBvWidth())); + const auto& t = parser.get_term(name_vlg_pair.second); + inv_extra_vlg_vars.push_back(std::make_tuple( + name_vlg_pair.first, t._translate, t._type.GetBoolBvWidth())); } for (auto&& name_w_pair : parser.GetFreeVarDefs()) { if (IN(name_w_pair.first, inv_extra_free_vars)) @@ -155,10 +154,9 @@ void InvariantObject::AddInvariantFromGrainResultFile( smt_formula_vec.push_back(""); // although we get it, we remove it here for (auto&& name_vlg_pair : parser.GetLocalVarDefs()) { - const auto & t = parser.get_term(name_vlg_pair.second); - inv_extra_vlg_vars.push_back( - std::make_tuple(name_vlg_pair.first, t._translate, - t._type.GetBoolBvWidth())); + const auto& t = parser.get_term(name_vlg_pair.second); + inv_extra_vlg_vars.push_back(std::make_tuple( + name_vlg_pair.first, t._translate, t._type.GetBoolBvWidth())); } for (auto&& name_w_pair : parser.GetFreeVarDefs()) { if (IN(name_w_pair.first, inv_extra_free_vars)) diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index 1a5f38326..50e0fc69a 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -33,16 +33,14 @@ VlgSglTgtGen::VlgSglTgtGen( const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants const InstrLvlAbsPtr& ila_ptr, - const rfmap::VerilogRefinementMap & refinement, - VerilogInfo* _vlg_info_ptr, + const rfmap::VerilogRefinementMap& refinement, VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, const vtg_config_t& vtg_config, backend_selector backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr) : _output_path(output_path), _instr_ptr(instr_ptr), _host(ila_ptr), - _vlg_mod_inst_name("RTL"), - _ila_mod_inst_name("ILA"), + _vlg_mod_inst_name("RTL"), _ila_mod_inst_name("ILA"), // default option on wrapper vlg_wrapper( VerilogGenerator::VlgGenConfig(true, // ExternalMem @@ -57,12 +55,13 @@ VlgSglTgtGen::VlgSglTgtGen( // use given, except for core options vlg_ila(VerilogGeneratorBase::VlgGenConfig( false, // default case: internal memory - VerilogGeneratorBase::VlgGenConfig::funcOption::External, // external function - true, // w. start signal + VerilogGeneratorBase::VlgGenConfig::funcOption::External, // external + // function + true, // w. start signal vtg_config.VerilogGenPassNodeName, // pass node name - false, // no rand init - false, // no expand memory - false // no collecte ITE unknown + false, // no rand init + false, // no expand memory + false // no collecte ITE unknown )), // interface mapping directive // -------- CONTROLLING THE RESET CONNECTION ------------- // @@ -80,16 +79,17 @@ VlgSglTgtGen::VlgSglTgtGen( //_vext( // [this](const std::string& n) -> bool { return TryFindIlaState(n); }, // [this](const std::string& n) -> bool { return TryFindIlaInput(n); }, - // [this](const std::string& n) -> bool { return TryFindVlgState(n); }), + // [this](const std::string& n) -> bool { return TryFindVlgState(n); + // }), // ref to refmaps refinement_map(refinement, /*type checker*/ - [this](const std::string& n) -> rfmap::RfVarTypeOrig { - return this->VarTypeCheckForRfExprParsing(n); }), + [this](const std::string& n) -> rfmap::RfVarTypeOrig { + return this->VarTypeCheckForRfExprParsing(n); + }), target_type(target_tp), // whether it is // invariant/instructions - max_bound(127), - cnt_width(1), _advanced_param_ptr(adv_ptr), + max_bound(127), cnt_width(1), _advanced_param_ptr(adv_ptr), has_gussed_synthesized_invariant( adv_ptr && adv_ptr->_candidate_inv_ptr && !adv_ptr->_candidate_inv_ptr->GetVlgConstraints().empty()), @@ -100,8 +100,7 @@ VlgSglTgtGen::VlgSglTgtGen( mapping_counter(0), property_counter(0), top_mod_name(wrapper_name), vlg_design_files(implementation_srcs), vlg_include_files_path(implementation_include_path), - _vtg_config(vtg_config), _backend(backend), - _bad_state(false) { + _vtg_config(vtg_config), _backend(backend), _bad_state(false) { ILA_NOT_NULL(_host); @@ -110,7 +109,6 @@ VlgSglTgtGen::VlgSglTgtGen( target_type == target_type_t::INV_SYN_DESIGN_ONLY) << "Implementation bug: unrecognized target type!"; - if (target_type == target_type_t::INSTRUCTIONS) { ILA_NOT_NULL(instr_ptr); @@ -118,18 +116,18 @@ VlgSglTgtGen::VlgSglTgtGen( // TODO: insert the memory export directive VerilogGeneratorBase::memory_export_annotation_t mem_annotation; - for(unsigned sidx = 0; sidx < _host->state_num(); ++ sidx) { - const auto & s = _host->state(sidx); - if(!s->is_mem()) + for (unsigned sidx = 0; sidx < _host->state_num(); ++sidx) { + const auto& s = _host->state(sidx); + if (!s->is_mem()) continue; - const auto & n = s->name().str(); + const auto& n = s->name().str(); auto pos = refinement_map.ila_state_var_map.find(n); if (pos == refinement_map.ila_state_var_map.end()) continue; - if(pos->second.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) - mem_annotation.emplace(n,true); + if (pos->second.type == rfmap::IlaVarMapping::StateVarMapType::EXTERNMEM) + mem_annotation.emplace(n, true); else - mem_annotation.emplace(n,false); + mem_annotation.emplace(n, false); } // end - for each mem state vlg_ila.AnnotateMemory(mem_annotation); // need to change this @@ -147,7 +145,7 @@ VlgSglTgtGen::VlgSglTgtGen( // the ports are connected to wires with names like // __IMEM_xxx_... // this is in single_target_connect.cc - + } // END of target_type == INSTRUCTION else if (target_type == target_type_t::INVARIANTS) { ILA_WARN_IF(instr_ptr != nullptr) @@ -169,9 +167,9 @@ void VlgSglTgtGen::ConstructWrapper_add_inputmap_assumptions() { for (size_t input_idx = 0; input_idx < _host->input_num(); ++input_idx) ila_input_names.insert(_host->input(input_idx)->name().str()); - for (const auto & iv_rfmap : refinement_map.ila_input_var_map) { - const auto & iname = iv_rfmap.first; - if(ila_input_names.find(iname) == ila_input_names.end()) { + for (const auto& iv_rfmap : refinement_map.ila_input_var_map) { + const auto& iname = iv_rfmap.first; + if (ila_input_names.find(iname) == ila_input_names.end()) { ILA_ERROR << "Cannot find ILA input with name: " << iname; continue; } @@ -180,9 +178,9 @@ void VlgSglTgtGen::ConstructWrapper_add_inputmap_assumptions() { Gen_input_map_assumpt(iname, iv_rfmap.second, "input_map_assume_"); } - if(!ila_input_names.empty()) { + if (!ila_input_names.empty()) { ILA_ERROR << "Lack input var map for the following variables:"; - for(const auto & in : ila_input_names) + for (const auto& in : ila_input_names) ILA_ERROR << in; } } @@ -197,9 +195,9 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assumptions() { for (size_t state_idx = 0; state_idx < _host->state_num(); ++state_idx) ila_state_names.insert(_host->state(state_idx)->name().str()); - for (const auto & sv_rfmap : refinement_map.ila_state_var_map) { - const auto & sname = sv_rfmap.first; - if(!IN(sname, ila_state_names)) { + for (const auto& sv_rfmap : refinement_map.ila_state_var_map) { + const auto& sname = sv_rfmap.first; + if (!IN(sname, ila_state_names)) { ILA_ERROR << sname << " is not a state of the ILA:" << _host->name().str(); continue; @@ -215,8 +213,8 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assumptions() { ILA_DLOG("VtargetGen.ConstructWrapper_add_varmap_assumptions") << sname; std::string problem_name = "variable_map_assume_"; - - Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, true ); + + Gen_varmap_assumpt_assert(sname, sv_rfmap.second, problem_name, true); } // end for each state variable ILA_DLOG("VtargetGen") << "STEP:" @@ -243,9 +241,9 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { for (size_t state_idx = 0; state_idx < _host->state_num(); ++state_idx) ila_state_names.insert(_host->state(state_idx)->name().str()); - for (const auto & sv_rfmap : refinement_map.ila_state_var_map) { - const auto & sname = sv_rfmap.first; - if(!IN(sname, ila_state_names)) { + for (const auto& sv_rfmap : refinement_map.ila_state_var_map) { + const auto& sname = sv_rfmap.first; + if (!IN(sname, ila_state_names)) { ILA_ERROR << sname << " is not a state of the ILA:" << _host->name().str(); continue; @@ -254,12 +252,12 @@ void VlgSglTgtGen::ConstructWrapper_add_varmap_assertions() { if (_vtg_config.OnlyCheckInstUpdatedVars && _instr_ptr->update(sname) == nullptr) { - ILA_DLOG("VtargetGen") << "Skip assume EQ on variable:" << sname - << " for instruction:" << _instr_ptr->name().str(); - continue; + ILA_DLOG("VtargetGen") << "Skip assume EQ on variable:" << sname + << " for instruction:" << _instr_ptr->name().str(); + continue; } ILA_DLOG("VtargetGen.ConstructWrapper_add_varmap_assertions") << sname; - + // just check if we miss any function in uf section FunctionApplicationFinder func_app_finder(_instr_ptr->update(sname)); for (auto&& func_ptr : func_app_finder.GetReferredFunc()) { @@ -320,7 +318,6 @@ void VlgSglTgtGen::ConstructWrapper() { } else ConstructWrapper_inv_syn_cond_signals(); - // 1. dealing with reset ConstructWrapper_reset_setup(); // will use __RESETED__ @@ -353,18 +350,17 @@ void VlgSglTgtGen::ConstructWrapper() { ConstructWrapper_add_rf_assumptions(); - ILA_DLOG("VtargetGen") << "STEP:" << 8; // post value holder --- ABC cannot work on this if (target_type == target_type_t::INSTRUCTIONS) { - // the vars defined here are already + // the vars defined here are already // presented in refinement_map.all_var_def_type ConstructWrapper_add_post_value_holder(); ConstructWrapper_add_delay_unit(); ConstructWrapper_add_stage_tracker(); } - + ConstructWrapper_add_vlg_monitor(); // add monitor -- inside the monitor, there will be // disable logic if it is for invariant type target @@ -372,7 +368,7 @@ void VlgSglTgtGen::ConstructWrapper() { // 7. uni-functions if (target_type == target_type_t::INSTRUCTIONS) ConstructWrapper_add_uf_constraints(); - + // instantiate ila module if (target_type == target_type_t::INSTRUCTIONS) { auto ila_mod_inst = ConstructWrapper_get_ila_module_inst(); @@ -382,8 +378,8 @@ void VlgSglTgtGen::ConstructWrapper() { // read assumption/assertion, decide where to put them rtl/smt // perform the reg[n] optimize // populate the RtlExtraWire data structure - ConstructWrapper_translate_property_and_collect_all_rtl_connection_var(); - // 1. varname 2. hierarchy 3. what to connect inside + ConstructWrapper_translate_property_and_collect_all_rtl_connection_var(); + // 1. varname 2. hierarchy 3. what to connect inside // 5.0 add the extra wires to the top module wrapper // will use var_replacement, and will set _idr @@ -395,7 +391,6 @@ void VlgSglTgtGen::ConstructWrapper() { // for the vlg inst: will use _idr ConstructWrapper_add_module_instantiation(); - // 2. add some monitors (bound cnt) // 3. add assumptions & assertions } // Construct_wrapper @@ -412,11 +407,11 @@ void VlgSglTgtGen::Export_wrapper(const std::string& wrapper_name) { vlg_wrapper.DumpToFile(fout); // for append verilog - for(const auto & vlg_monitor : refinement_map.customized_monitor) { - if(vlg_monitor.second.verilog_append.empty()) + for (const auto& vlg_monitor : refinement_map.customized_monitor) { + if (vlg_monitor.second.verilog_append.empty()) continue; - if(!vlg_monitor.second.keep_for_invariant && - target_type != target_type_t::INSTRUCTIONS) + if (!vlg_monitor.second.keep_for_invariant && + target_type != target_type_t::INSTRUCTIONS) continue; fout << "/***** BEGIN of Monitor for " << vlg_monitor.first << " *****/\n"; @@ -468,7 +463,7 @@ void VlgSglTgtGen::ExportAll(const std::string& wrapper_name, Export_modify_verilog(); // this must be after Export_wrapper Export_problem(extra_name); // for JG this is do.tcl - // for Pono: this is the yosys.script and + // for Pono: this is the yosys.script and Export_script(script_name); } // end of ExportAll diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index 18a065348..6a5b03b86 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -11,12 +11,12 @@ #include #include +#include +#include #include #include #include #include -#include -#include namespace ilang { @@ -28,324 +28,312 @@ void VlgSglTgtGen::add_reg_cassign_assumption(const std::string& varname, const rfmap::RfExpr& cond, const std::string& dspt) { rfmap::RfExprAstUtility::RfMapNoNullNode(expression); - rfmap::RfExprAstUtility::RfMapNoNullNode(cond); - + rfmap::RfExprAstUtility::RfMapNoNullNode(cond); + std::string rand_in_name = "__" + varname + "_init__"; vlg_wrapper.add_input(rand_in_name, width); vlg_wrapper.add_wire(rand_in_name, width); vlg_wrapper.add_init_stmt(varname + " <= " + rand_in_name + ";"); vlg_wrapper.add_always_stmt(varname + " <= " + varname + ";"); - add_an_assumption( - rfmap_imply(cond, rfmap_eq(rfmap_var(varname), expression)), dspt); + add_an_assumption(rfmap_imply(cond, rfmap_eq(rfmap_var(varname), expression)), + dspt); } // add_reg_cassign_assumption - -void VlgSglTgtGen::add_smt_assumption( - const rfmap::RfExpr & body, - const std::string & dspt) -{ - rfmap::RfExprAstUtility::RfMapNoNullNode(body); +void VlgSglTgtGen::add_smt_assumption(const rfmap::RfExpr& body, + const std::string& dspt) { + rfmap::RfExprAstUtility::RfMapNoNullNode(body); std::unordered_map vars; rfmap::RfExprAstUtility::GetVars(body, vars); - std::string body_smt2 = - rfmap::RfExpr2Smt::to_smt2(body, rfmap::SmtType() /*Bool type*/ ); + std::string body_smt2 = + rfmap::RfExpr2Smt::to_smt2(body, rfmap::SmtType() /*Bool type*/); std::vector arg; - for(const auto & n_expr_pair : vars) { - auto tp = refinement_map.GetType( n_expr_pair.second ); + for (const auto& n_expr_pair : vars) { + auto tp = refinement_map.GetType(n_expr_pair.second); auto smt_tp = rfmap::SmtType(tp.type, false); - const auto & n = n_expr_pair.first; - arg.push_back("(|"+n + "| " + smt_tp.type_to_smt2() + ")"); - } - add_a_direct_smt_assumption( - "("+Join(arg, " ")+")", "Bool", body_smt2, dspt); + const auto& n = n_expr_pair.first; + arg.push_back("(|" + n + "| " + smt_tp.type_to_smt2() + ")"); + } + add_a_direct_smt_assumption("(" + Join(arg, " ") + ")", "Bool", body_smt2, + dspt); } // Add SMT assertion (using rfexpr) -void VlgSglTgtGen::add_smt_assertion( - const rfmap::RfExpr & body, - const std::string & dspt) -{ - rfmap::RfExprAstUtility::RfMapNoNullNode(body); +void VlgSglTgtGen::add_smt_assertion(const rfmap::RfExpr& body, + const std::string& dspt) { + rfmap::RfExprAstUtility::RfMapNoNullNode(body); std::unordered_map vars; rfmap::RfExprAstUtility::GetVars(body, vars); - std::string body_smt2 = - rfmap::RfExpr2Smt::to_smt2(body, rfmap::SmtType() /*Bool type*/ ); + std::string body_smt2 = + rfmap::RfExpr2Smt::to_smt2(body, rfmap::SmtType() /*Bool type*/); std::vector arg; - for(const auto & n_expr_pair : vars) { - auto tp = refinement_map.GetType( n_expr_pair.second ); + for (const auto& n_expr_pair : vars) { + auto tp = refinement_map.GetType(n_expr_pair.second); auto smt_tp = rfmap::SmtType(tp.type, false); - const auto & n = n_expr_pair.first; - arg.push_back("(|"+n + "| " + smt_tp.type_to_smt2() + ")"); - } - add_a_direct_smt_assertion( - "("+Join(arg, " ")+")", "Bool", body_smt2, dspt); + const auto& n = n_expr_pair.first; + arg.push_back("(|" + n + "| " + smt_tp.type_to_smt2() + ")"); + } + add_a_direct_smt_assertion("(" + Join(arg, " ") + ")", "Bool", body_smt2, + dspt); } - void VlgSglTgtGen::add_an_assumption(const rfmap::RfExpr& aspt, - const std::string& dspt) { + const std::string& dspt) { - rfmap::RfExprAstUtility::RfMapNoNullNode(aspt); + rfmap::RfExprAstUtility::RfMapNoNullNode(aspt); all_assumptions[dspt].push_back(aspt); } void VlgSglTgtGen::add_an_assertion(const rfmap::RfExpr& asst, - const std::string& dspt) { - rfmap::RfExprAstUtility::RfMapNoNullNode(asst); + const std::string& dspt) { + rfmap::RfExprAstUtility::RfMapNoNullNode(asst); all_assertions[dspt].push_back(asst); } void VlgSglTgtGen::add_a_santiy_assertion(const rfmap::RfExpr& asst, - const std::string& dspt) { - if(dspt == "post_value_holder" && - !_vtg_config.SanityCheck_ValueRecorderOverlyConstrained) + const std::string& dspt) { + if (dspt == "post_value_holder" && + !_vtg_config.SanityCheck_ValueRecorderOverlyConstrained) return; - - rfmap::RfExprAstUtility::RfMapNoNullNode( asst ); + + rfmap::RfExprAstUtility::RfMapNoNullNode(asst); all_sanity_assertions[dspt].push_back(asst); } -static std::string const_to_unified_str(const rfmap::RfExpr & in) { +static std::string const_to_unified_str(const rfmap::RfExpr& in) { auto cnst = verilog_expr::VExprAstConstant::cast_ptr(in); ILA_NOT_NULL(cnst); auto b_w_lit = cnst->get_constant(); auto base = std::get<0>(b_w_lit); auto lit = std::get<2>(b_w_lit); - if(base == 10 || base == 0) + if (base == 10 || base == 0) return lit; // else other base - auto n = StrToULongLong(lit, base); - if(lit != "0" && n == 0) + auto n = StrToULongLong(lit, base); + if (lit != "0" && n == 0) return "error"; return IntToStrCustomBase(n, 10, false); } static void find_and_replace_array_const( - rfmap::RfExpr & expr, - std::map & array_const_set, // RTL.a.b.c[const] - std::unordered_map & extra_wire) { - auto fd_rp_array_const_func = [ - &array_const_set,&extra_wire - ](rfmap::RfExpr & inout) { - if(inout->get_op() == verilog_expr::voperator::INDEX && - inout->get_child_cnt() == 2 && - inout->child(0)->is_var() && - inout->child(1)->is_constant() && - rfmap::RfExprAstUtility::GetType(inout->child(0)).type.is_array() - ) { - auto hier_name = inout->child(0)->to_verilog(); - auto cnst = const_to_unified_str(inout->child(1)); - if(cnst == "error" ) // if cannot convert - return; - - auto new_name = ReplaceAll(hier_name,".","__DOT__"); - new_name += "_"+cnst+"_"; - if(array_const_set.find(new_name) != array_const_set.end()) { - inout = array_const_set.at(new_name); - return; - } - - const auto last_dot_pos = hier_name.rfind("."); - ILA_CHECK(last_dot_pos != std::string::npos); - const auto hierarchy = hier_name.substr(0,last_dot_pos); - const auto internal = hier_name.substr(last_dot_pos+1) + "["+cnst+"]"; - ILA_CHECK(!IN(new_name, extra_wire)); - - - auto tp = rfmap::RfExprAstUtility::GetType(inout->child(0)).type; - auto w = tp.unified_width(); - - extra_wire.emplace(new_name, - RtlExtraWire(new_name, hierarchy, internal, w)); - // new_name is the wire name - - // replace var - auto repl = verilog_expr::VExprAst::MakeSpecialName(new_name); - auto new_tp = std::make_shared(); - new_tp->var_ref_type = rfmap::TypeAnnotation::VARTYPE::INTERNAL; - new_tp->type = rfmap::RfMapVarType(w); - repl->set_annotation(new_tp); - inout = repl; - - array_const_set.emplace(new_name,repl); + rfmap::RfExpr& expr, + std::map& array_const_set, // RTL.a.b.c[const] + std::unordered_map& extra_wire) { + auto fd_rp_array_const_func = [&array_const_set, + &extra_wire](rfmap::RfExpr& inout) { + if (inout->get_op() == verilog_expr::voperator::INDEX && + inout->get_child_cnt() == 2 && inout->child(0)->is_var() && + inout->child(1)->is_constant() && + rfmap::RfExprAstUtility::GetType(inout->child(0)).type.is_array()) { + auto hier_name = inout->child(0)->to_verilog(); + auto cnst = const_to_unified_str(inout->child(1)); + if (cnst == "error") // if cannot convert + return; + + auto new_name = ReplaceAll(hier_name, ".", "__DOT__"); + new_name += "_" + cnst + "_"; + if (array_const_set.find(new_name) != array_const_set.end()) { + inout = array_const_set.at(new_name); + return; } - }; - rfmap::RfExprAstUtility::TraverseRfExpr(expr, fd_rp_array_const_func); + + const auto last_dot_pos = hier_name.rfind("."); + ILA_CHECK(last_dot_pos != std::string::npos); + const auto hierarchy = hier_name.substr(0, last_dot_pos); + const auto internal = + hier_name.substr(last_dot_pos + 1) + "[" + cnst + "]"; + ILA_CHECK(!IN(new_name, extra_wire)); + + auto tp = rfmap::RfExprAstUtility::GetType(inout->child(0)).type; + auto w = tp.unified_width(); + + extra_wire.emplace(new_name, + RtlExtraWire(new_name, hierarchy, internal, w)); + // new_name is the wire name + + // replace var + auto repl = verilog_expr::VExprAst::MakeSpecialName(new_name); + auto new_tp = std::make_shared(); + new_tp->var_ref_type = rfmap::TypeAnnotation::VARTYPE::INTERNAL; + new_tp->type = rfmap::RfMapVarType(w); + repl->set_annotation(new_tp); + inout = repl; + + array_const_set.emplace(new_name, repl); + } + }; + rfmap::RfExprAstUtility::TraverseRfExpr(expr, fd_rp_array_const_func); } // find_and_replace_array_const void VlgSglTgtGen::add_wire_assign_assumption(const std::string& varname, - const rfmap::RfExpr &aspt, - const std::string& dspt) { - - rfmap::RfExprAstUtility::RfMapNoNullNode(aspt); - assign_or_assumptions.push_back(std::make_tuple(dspt, varname, aspt, nullptr)); + const rfmap::RfExpr& aspt, + const std::string& dspt) { + + rfmap::RfExprAstUtility::RfMapNoNullNode(aspt); + assign_or_assumptions.push_back( + std::make_tuple(dspt, varname, aspt, nullptr)); } - // read assumption/assertion, decide where to put them rtl/smt - // perform the reg[n] optimize - // populate the RtlExtraWire data structure -void VlgSglTgtGen::ConstructWrapper_translate_property_and_collect_all_rtl_connection_var() { +// read assumption/assertion, decide where to put them rtl/smt +// perform the reg[n] optimize +// populate the RtlExtraWire data structure +void VlgSglTgtGen:: + ConstructWrapper_translate_property_and_collect_all_rtl_connection_var() { bool is_jg = _backend == VlgSglTgtGen::backend_selector::JASPERGOLD; - for(auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { - const auto & vn = std::get<1>(dspt_vn_rfexpr_eq); - const auto & rfe = std::get<2>(dspt_vn_rfexpr_eq); + for (auto& dspt_vn_rfexpr_eq : assign_or_assumptions) { + const auto& vn = std::get<1>(dspt_vn_rfexpr_eq); + const auto& rfe = std::get<2>(dspt_vn_rfexpr_eq); - ILA_DLOG("VTG.ReplWireEq") << vn << " := " << rfe->to_verilog(); - std::get<3>(dspt_vn_rfexpr_eq) = - ReplExpr(rfmap_eq( rfmap_var(vn), rfe)); + ILA_DLOG("VTG.ReplWireEq") << vn << " := " << rfe->to_verilog(); + std::get<3>(dspt_vn_rfexpr_eq) = ReplExpr(rfmap_eq(rfmap_var(vn), rfe)); } // for each assign/assumption - for(auto & dspt_aspt : all_assumptions) { - for(auto & aspt : dspt_aspt.second) { - ILA_DLOG("VTG.ReplAssume") << aspt->to_verilog() ; + for (auto& dspt_aspt : all_assumptions) { + for (auto& aspt : dspt_aspt.second) { + ILA_DLOG("VTG.ReplAssume") << aspt->to_verilog(); aspt = ReplExpr(aspt); } } - - for (auto & dspt_asst : all_assertions) { - for (auto & asst : dspt_asst.second) { - ILA_DLOG("VTG.ReplAssert") << asst->to_verilog() ; + + for (auto& dspt_asst : all_assertions) { + for (auto& asst : dspt_asst.second) { + ILA_DLOG("VTG.ReplAssert") << asst->to_verilog(); asst = ReplExpr(asst); } } - for (auto & dspt_asst : all_sanity_assertions) { - for (auto & asst : dspt_asst.second) { - ILA_DLOG("VTG.ReplAssert") << asst->to_verilog() ; + for (auto& dspt_asst : all_sanity_assertions) { + for (auto& asst : dspt_asst.second) { + ILA_DLOG("VTG.ReplAssert") << asst->to_verilog(); asst = ReplExpr(asst); } } - if(is_jg) { - for(auto & dspt_aspt : all_assumptions) { - for(auto & aspt : dspt_aspt.second) - add_a_direct_assumption( aspt->to_verilog(), dspt_aspt.first ); + if (is_jg) { + for (auto& dspt_aspt : all_assumptions) { + for (auto& aspt : dspt_aspt.second) + add_a_direct_assumption(aspt->to_verilog(), dspt_aspt.first); } - for(auto & dspt_asst : all_assertions) { - for(auto & asst : dspt_asst.second) - add_a_direct_assertion( asst->to_verilog(), dspt_asst.first ); + for (auto& dspt_asst : all_assertions) { + for (auto& asst : dspt_asst.second) + add_a_direct_assertion(asst->to_verilog(), dspt_asst.first); } - for(auto & dspt_asst : all_sanity_assertions) { - for(auto & asst : dspt_asst.second) - add_a_direct_sanity_assertion( asst->to_verilog(), dspt_asst.first ); + for (auto& dspt_asst : all_sanity_assertions) { + for (auto& asst : dspt_asst.second) + add_a_direct_sanity_assertion(asst->to_verilog(), dspt_asst.first); } - - - for (auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { - const auto & vn = std::get<1>(dspt_vn_rfexpr_eq); - const auto & eq = std::get<3>(dspt_vn_rfexpr_eq); + for (auto& dspt_vn_rfexpr_eq : assign_or_assumptions) { + const auto& vn = std::get<1>(dspt_vn_rfexpr_eq); + const auto& eq = std::get<3>(dspt_vn_rfexpr_eq); // we know it is eq(vn, rhs); vlg_wrapper.add_assign_stmt(vn, eq->child(1)->to_verilog()); } return; } - for(const auto & repl : refinement_map.GetVarReplacement()) { - ILA_CHECK( - StrStartsWith(repl.second.get_orig_name(), "RTL." ) == - repl.second.is_orig_rtlv() - ); + for (const auto& repl : refinement_map.GetVarReplacement()) { + ILA_CHECK(StrStartsWith(repl.second.get_orig_name(), "RTL.") == + repl.second.is_orig_rtlv()); - if(!repl.second.is_orig_rtlv()) + if (!repl.second.is_orig_rtlv()) continue; - if(repl.second.is_orig_var_array()) + if (repl.second.is_orig_var_array()) continue; // do not connect array - + ILA_CHECK(StrStartsWith(repl.second.get_new_name(), "RTL__DOT__")) - << repl.second.get_new_name() << "is not replaced"; + << repl.second.get_new_name() << "is not replaced"; // jaspergold should not reach here const auto full_name = repl.second.get_orig_name(); const auto last_dot_pos = full_name.rfind("."); - const auto hierarchy = full_name.substr(0,last_dot_pos); - const auto internal = full_name.substr(last_dot_pos+1); + const auto hierarchy = full_name.substr(0, last_dot_pos); + const auto internal = full_name.substr(last_dot_pos + 1); unsigned width = repl.second.get_type_orig().type.unified_width(); - rtl_extra_wire.emplace(repl.second.get_new_name(), - RtlExtraWire(repl.second.get_new_name(), hierarchy, internal, width)); + rtl_extra_wire.emplace( + repl.second.get_new_name(), + RtlExtraWire(repl.second.get_new_name(), hierarchy, internal, width)); } std::map array_const_set; // below will also update `rtl_extra_wire` - for(auto & dspt_aspt : all_assumptions) { - for(auto & aspt : dspt_aspt.second) { + for (auto& dspt_aspt : all_assumptions) { + for (auto& aspt : dspt_aspt.second) { find_and_replace_array_const(aspt, array_const_set, rtl_extra_wire); } } - for(auto & dspt_asst : all_assertions) { - for(auto & asst : dspt_asst.second) { + for (auto& dspt_asst : all_assertions) { + for (auto& asst : dspt_asst.second) { find_and_replace_array_const(asst, array_const_set, rtl_extra_wire); } } - for(auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { - auto & eq = std::get<3>(dspt_vn_rfexpr_eq); + for (auto& dspt_vn_rfexpr_eq : assign_or_assumptions) { + auto& eq = std::get<3>(dspt_vn_rfexpr_eq); find_and_replace_array_const(eq, array_const_set, rtl_extra_wire); } // last step - // if a=b[c] contains array not handled, then we need to have + // if a=b[c] contains array not handled, then we need to have // smt assumptions // otherwise, we can add it as an assign - for (const auto & dspt_vn_rfexpr_eq : assign_or_assumptions) { - const auto & eq = std::get<3>(dspt_vn_rfexpr_eq); - const auto & dspt = std::get<0>(dspt_vn_rfexpr_eq); - const auto & wn = std::get<1>(dspt_vn_rfexpr_eq); + for (const auto& dspt_vn_rfexpr_eq : assign_or_assumptions) { + const auto& eq = std::get<3>(dspt_vn_rfexpr_eq); + const auto& dspt = std::get<0>(dspt_vn_rfexpr_eq); + const auto& wn = std::get<1>(dspt_vn_rfexpr_eq); ILA_DLOG("VTG.AddWireEq") << eq->to_verilog(); - std::map array_var; - if(rfmap::RfExprAstUtility::HasArrayVar(eq, array_var)) + std::map array_var; + if (rfmap::RfExprAstUtility::HasArrayVar(eq, array_var)) add_smt_assumption(eq, dspt); else vlg_wrapper.add_assign_stmt(wn, eq->child(1)->to_verilog()); } - for(const auto & dspt_aspt : all_assumptions) { - for(const auto & aspt : dspt_aspt.second) { + for (const auto& dspt_aspt : all_assumptions) { + for (const auto& aspt : dspt_aspt.second) { ILA_DLOG("VTG.AddAssume") << aspt->to_verilog(); - std::map array_var; - if(rfmap::RfExprAstUtility::HasArrayVar(aspt, array_var)) + std::map array_var; + if (rfmap::RfExprAstUtility::HasArrayVar(aspt, array_var)) add_smt_assumption(aspt, dspt_aspt.first); else add_a_direct_assumption(aspt->to_verilog(), dspt_aspt.first); } } - for(const auto & dspt_asst : all_assertions) { - for(const auto & asst : dspt_asst.second) { + for (const auto& dspt_asst : all_assertions) { + for (const auto& asst : dspt_asst.second) { ILA_DLOG("VTG.AddAssert") << asst->to_verilog(); - std::map array_var; - if(rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) + std::map array_var; + if (rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) add_smt_assertion(asst, dspt_asst.first); else add_a_direct_assertion(asst->to_verilog(), dspt_asst.first); } } - for(const auto & dspt_asst : all_sanity_assertions) { - for(const auto & asst : dspt_asst.second) { - std::map array_var; + for (const auto& dspt_asst : all_sanity_assertions) { + for (const auto& asst : dspt_asst.second) { + std::map array_var; ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) - << "Implementation bug: sanity checking assertion should not contain arrays"; - + << "Implementation bug: sanity checking assertion should not contain " + "arrays"; + add_a_direct_sanity_assertion(asst->to_verilog(), dspt_asst.first); } } - } // ConstructWrapper_translate_property_and_collect_all_rtl_connection_var - }; // namespace ilang diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index abd065033..50bb5c55e 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -37,7 +37,6 @@ namespace ilang { // 6 IEND ---> check varmap // 7 ENDED - /// setup reset, add assumptions if necessary void VlgSglTgtGen::ConstructWrapper_reset_setup() { if (target_type == target_type_t::INSTRUCTIONS) { @@ -45,14 +44,13 @@ void VlgSglTgtGen::ConstructWrapper_reset_setup() { vlg_wrapper.add_wire("dummy_reset", 1, true); rfmap_add_internal_wire("dummy_reset", 1); if (_vtg_config.InstructionNoReset) { - add_an_assumption( - rfmap_imply( - rfmap_var("__RESETED__"), - rfmap_not(rfmap_var("dummy_reset"))), "noreset"); + add_an_assumption(rfmap_imply(rfmap_var("__RESETED__"), + rfmap_not(rfmap_var("dummy_reset"))), + "noreset"); } } else if (target_type == target_type_t::INVARIANTS || target_type == target_type_t::INV_SYN_DESIGN_ONLY) { - if (_vtg_config.InvariantCheckNoReset) { + if (_vtg_config.InvariantCheckNoReset) { if (_backend == backend_selector::JASPERGOLD) { // no need to any thing } else if (VlgVerifTgtGenBase::backend_needs_yosys(_backend)) { @@ -70,11 +68,11 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { const auto& instr = get_current_instruction_rf(); - if(instr.is_readybound()) + if (instr.is_readybound()) max_bound = instr.ready_bound; else max_bound = _vtg_config.MaxBound; - if(instr.max_bound > max_bound) + if (instr.max_bound > max_bound) max_bound = instr.max_bound; cnt_width = (int)std::ceil(std::log2(max_bound + 20)); @@ -94,10 +92,10 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { rfmap_add_replacement("decode", "__START__"); vlg_wrapper.add_stmt("always @(posedge clk) begin"); // how start is triggered - - vlg_wrapper.add_stmt("if (rst) __START__ <= 1;"); - vlg_wrapper.add_stmt("else if (__START__ || __STARTED__) __START__ <= 0;"); - + + vlg_wrapper.add_stmt("if (rst) __START__ <= 1;"); + vlg_wrapper.add_stmt("else if (__START__ || __STARTED__) __START__ <= 0;"); + vlg_wrapper.add_stmt("end"); vlg_wrapper.add_reg("__STARTED__", 1); @@ -158,25 +156,26 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { // __IEND__ rfmap::RfExpr iend_cond; // bool no_started_signal = false; - if(instr.is_readysignal()) { - iend_cond = instr.ready_signal ; + if (instr.is_readysignal()) { + iend_cond = instr.ready_signal; } else { ILA_ASSERT(instr.is_readybound()); unsigned bound = instr.ready_bound; - ILA_ERROR_IF(bound == 0) - << "Does not support bound : 0, please use a buffer to hold " - "the signal."; - iend_cond = rfmap_eq( rfmap_var("__CYCLE_CNT__") , rfmap_const(10, cnt_width, bound)); + ILA_ERROR_IF(bound == 0) + << "Does not support bound : 0, please use a buffer to hold " + "the signal."; + iend_cond = + rfmap_eq(rfmap_var("__CYCLE_CNT__"), rfmap_const(10, cnt_width, bound)); // "( __CYCLE_CNT__ == " + IntToStr(cnt_width) + "'d" // + IntToStr(bound) + ")"; } // max bound for max checking range rfmap::RfExpr max_bound_constr = rfmap_true(); - if(instr.max_bound != 0) { - max_bound_constr = - rfmap_le( rfmap_var("__CYCLE_CNT__"), rfmap_const(10, cnt_width, instr.max_bound)); - // "&& ( __CYCLE_CNT__ <= " + IntToStr(instr.max_bound) + ")"; + if (instr.max_bound != 0) { + max_bound_constr = rfmap_le(rfmap_var("__CYCLE_CNT__"), + rfmap_const(10, cnt_width, instr.max_bound)); + // "&& ( __CYCLE_CNT__ <= " + IntToStr(instr.max_bound) + ")"; } vlg_wrapper.add_wire("__IEND__", 1, true); @@ -186,30 +185,24 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { rfmap_add_internal_wire("__EDCOND__", 1); rfmap_add_replacement("commit", "__IEND__"); - auto end_no_recur = rfmap_not( rfmap_var("__ENDED__") ); + auto end_no_recur = rfmap_not(rfmap_var("__ENDED__")); - add_wire_assign_assumption("__EDCOND__", - rfmap_and(iend_cond, rfmap_var("__STARTED__")), "EDCOND"); + add_wire_assign_assumption( + "__EDCOND__", rfmap_and(iend_cond, rfmap_var("__STARTED__")), "EDCOND"); - add_wire_assign_assumption("__IEND__", - rfmap_and( - {iend_cond, - rfmap_var("__STARTED__"), - rfmap_var("__RESETED__"), - end_no_recur, - max_bound_constr - }), - "IEND"); + add_wire_assign_assumption( + "__IEND__", + rfmap_and({iend_cond, rfmap_var("__STARTED__"), rfmap_var("__RESETED__"), + end_no_recur, max_bound_constr}), + "IEND"); // handle start decode - + if (!instr.start_condition.empty()) { handle_start_condition(instr.start_condition); } else { - add_an_assumption( - rfmap_imply(rfmap_var("__START__"), rfmap_var("$decode")), + add_an_assumption(rfmap_imply(rfmap_var("__START__"), rfmap_var("$decode")), "issue_decode"); // __ISSUE__ |-> decode - add_an_assumption( - rfmap_imply(rfmap_var("__START__"), rfmap_var("$valid")), + add_an_assumption(rfmap_imply(rfmap_var("__START__"), rfmap_var("$valid")), "issue_valid"); // __ISSUE__ |-> valid } diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index dc27d37a4..eede7568f 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -99,7 +99,7 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { std::string func_reg_w = func_app.func_name + "_" + IntToStr(func_no) + "_result_wire"; - + vlg_wrapper.add_wire(func_reg_w, func_app.result.second, true); rfmap_add_internal_wire(func_reg_w, func_app.result.second); // add as a module input, also @@ -245,9 +245,12 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { rfmap_add_internal_reg(wdw_delay, dw); rfmap_add_internal_reg(waw_delay, aw); rfmap_add_internal_reg(wew_delay, 1); - vlg_wrapper.add_always_stmt("if (__START__) " + wdw_delay + " <= " + wdw + ";"); - vlg_wrapper.add_always_stmt("if (__START__) " + waw_delay + " <= " + waw + ";"); - vlg_wrapper.add_always_stmt("if (__START__) " + wew_delay + " <= " + wew + ";"); + vlg_wrapper.add_always_stmt("if (__START__) " + wdw_delay + " <= " + wdw + + ";"); + vlg_wrapper.add_always_stmt("if (__START__) " + waw_delay + " <= " + waw + + ";"); + vlg_wrapper.add_always_stmt("if (__START__) " + wew_delay + " <= " + wew + + ";"); retStr += " ." + port.wdata + "(" + wdw + "),\n"; retStr += " ." + port.waddr + "(" + waw + "),\n"; @@ -288,32 +291,31 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { void VlgSglTgtGen::ConstructWrapper_add_vlg_input_output() { - auto vlg_inputs = - vlg_info_ptr->get_top_module_io(refinement_map.width_info); - + auto vlg_inputs = vlg_info_ptr->get_top_module_io(refinement_map.width_info); + ILA_CHECK( - refinement_map.rtl_interface_connection.clock_domain_defs.size() == 1 - && IN("default", refinement_map.rtl_interface_connection.clock_domain_defs)) - << "Not implemented. Cannot handle multi-clock."; - + refinement_map.rtl_interface_connection.clock_domain_defs.size() == 1 && + IN("default", refinement_map.rtl_interface_connection.clock_domain_defs)) + << "Not implemented. Cannot handle multi-clock."; + ILA_CHECK( - refinement_map.rtl_interface_connection.custom_reset_domain_defs.empty() - ) << "Not implemented. Cannot handle customized reset."; + refinement_map.rtl_interface_connection.custom_reset_domain_defs.empty()) + << "Not implemented. Cannot handle customized reset."; - const auto & clock_pins = refinement_map.rtl_interface_connection.clock_domain_defs.at("default"); - const auto & reset_pins = refinement_map.rtl_interface_connection.reset_pins; - const auto & nreset_pins= refinement_map.rtl_interface_connection.nreset_pins; + const auto& clock_pins = + refinement_map.rtl_interface_connection.clock_domain_defs.at("default"); + const auto& reset_pins = refinement_map.rtl_interface_connection.reset_pins; + const auto& nreset_pins = refinement_map.rtl_interface_connection.nreset_pins; for (auto&& name_siginfo_pair : vlg_inputs) { std::string refstr = "**KEEP**"; - if(IN(name_siginfo_pair.first, clock_pins)) + if (IN(name_siginfo_pair.first, clock_pins)) refstr = "**CLOCK**"; else if (IN(name_siginfo_pair.first, reset_pins)) refstr = "**RESET**"; else if (IN(name_siginfo_pair.first, nreset_pins)) refstr = "**NRESET**"; - - _idr.RegisterInterface( - name_siginfo_pair.second, refstr); + + _idr.RegisterInterface(name_siginfo_pair.second, refstr); } } // ConstructWrapper_add_vlg_input_output @@ -333,8 +335,8 @@ void VlgSglTgtGen::ConstructWrapper_add_module_instantiation() { // ------------------------ OTERHS (refs) ----------------------------- // void VlgSglTgtGen::ConstructWrapper_register_extra_io_wire() { - for (auto && extra_wire : rtl_extra_wire) { - const auto & wire_name = extra_wire.first; + for (auto&& extra_wire : rtl_extra_wire) { + const auto& wire_name = extra_wire.first; unsigned width = extra_wire.second.width; vlg_wrapper.add_wire(wire_name, width, 1); // keep diff --git a/src/vtarget-out/single_target_inv_syn_support.cc b/src/vtarget-out/single_target_inv_syn_support.cc index 10bbd9868..4330c92d5 100644 --- a/src/vtarget-out/single_target_inv_syn_support.cc +++ b/src/vtarget-out/single_target_inv_syn_support.cc @@ -75,18 +75,18 @@ void VlgSglTgtGen::add_inv_obj_as_assertion(InvariantObject* inv_obj) { vlg_wrapper.add_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair), true); rfmap_add_internal_wire(std::get<0>(name_expr_pair), - std::get<2>(name_expr_pair)); - add_wire_assign_assumption(std::get<0>(name_expr_pair), - refinement_map.ParseRfExprFromString( - std::get<1>(name_expr_pair)), "invariant_aux_var"); + std::get<2>(name_expr_pair)); + add_wire_assign_assumption( + std::get<0>(name_expr_pair), + refinement_map.ParseRfExprFromString(std::get<1>(name_expr_pair)), + "invariant_aux_var"); } for (auto&& name_w_pair : inv_obj->GetExtraFreeVarDefs()) { vlg_wrapper.add_wire(name_w_pair.first, name_w_pair.second, true); vlg_wrapper.add_input(name_w_pair.first, name_w_pair.second); } for (auto&& inv_expr : inv_obj->GetVlgConstraints()) { - auto new_cond = - refinement_map.ParseRfExprFromString(inv_expr); + auto new_cond = refinement_map.ParseRfExprFromString(inv_expr); add_an_assertion(new_cond, "invariant_assert"); } } // add_inv_obj_as_assertion @@ -97,18 +97,18 @@ void VlgSglTgtGen::add_inv_obj_as_assumption(InvariantObject* inv_obj) { vlg_wrapper.add_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair), true); rfmap_add_internal_wire(std::get<0>(name_expr_pair), - std::get<2>(name_expr_pair)); - add_wire_assign_assumption(std::get<0>(name_expr_pair), + std::get<2>(name_expr_pair)); + add_wire_assign_assumption( + std::get<0>(name_expr_pair), refinement_map.ParseRfExprFromString(std::get<1>(name_expr_pair)), - "invariant_aux_var"); + "invariant_aux_var"); } for (auto&& name_w_pair : inv_obj->GetExtraFreeVarDefs()) { vlg_wrapper.add_wire(name_w_pair.first, name_w_pair.second, true); vlg_wrapper.add_input(name_w_pair.first, name_w_pair.second); } for (auto&& inv_expr : inv_obj->GetVlgConstraints()) { - auto new_cond = - refinement_map.ParseRfExprFromString(inv_expr); + auto new_cond = refinement_map.ParseRfExprFromString(inv_expr); add_an_assumption(new_cond, "invariant_assume"); } } // add_inv_obj_as_assumption @@ -207,9 +207,8 @@ void VlgSglTgtGen:: if (_advanced_param_ptr && _advanced_param_ptr->_cex_obj_ptr) { // this is cex reachability checking // -- assertions -- // - auto new_cond = - refinement_map.ParseRfExprFromString( - _advanced_param_ptr->_cex_obj_ptr->GenInvAssert("")); // force vlg state + auto new_cond = refinement_map.ParseRfExprFromString( + _advanced_param_ptr->_cex_obj_ptr->GenInvAssert("")); // force vlg state add_an_assertion(rfmap_not(new_cond), "cex_nonreachable_assert"); // -- assumption -- // if (_vtg_config.InvariantSynthesisReachableCheckKeepOldInvariant) { @@ -250,5 +249,4 @@ void VlgSglTgtGen::ConstructWrapper_inv_syn_cond_signals() { rfmap_add_internal_wire("__STARTED__", 1); } - } // namespace ilang diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index a791b8a5d..7656f7c53 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -9,11 +9,11 @@ #include #include +#include #include #include #include #include -#include namespace ilang { @@ -32,40 +32,50 @@ bool VlgSglTgtGen::bad_state_return(void) { } // bad_state_return void VlgSglTgtGen::RfmapIlaStateSanityCheck() { -#define ERR_IF(cond,s) do { ILA_ERROR_IF(cond) << (s); if(cond) { _bad_state = true; return;} } while(0) - - for(unsigned sidx = 0; sidx < _host->state_num(); ++ sidx) { - const auto & s = _host->state(sidx); - const auto & n = s->name().str(); - ERR_IF(!IN(n, refinement_map.ila_state_var_map), "state `" + n + "` not in refinement map" ); +#define ERR_IF(cond, s) \ + do { \ + ILA_ERROR_IF(cond) << (s); \ + if (cond) { \ + _bad_state = true; \ + return; \ + } \ + } while (0) + + for (unsigned sidx = 0; sidx < _host->state_num(); ++sidx) { + const auto& s = _host->state(sidx); + const auto& n = s->name().str(); + ERR_IF(!IN(n, refinement_map.ila_state_var_map), + "state `" + n + "` not in refinement map"); } - for(unsigned sidx = 0; sidx < _host->input_num(); ++ sidx) { - const auto & s = _host->input(sidx); - const auto & n = s->name().str(); - ERR_IF(!IN(n, refinement_map.ila_input_var_map), "input `" + n + "` not in refinement map" ); + for (unsigned sidx = 0; sidx < _host->input_num(); ++sidx) { + const auto& s = _host->input(sidx); + const auto& n = s->name().str(); + ERR_IF(!IN(n, refinement_map.ila_input_var_map), + "input `" + n + "` not in refinement map"); } - for(const auto & n_map_pair : refinement_map.ila_state_var_map) { - ERR_IF(_host->find_state(n_map_pair.first) == nullptr, "state `" + n_map_pair.first + "` not defined in ILA"); + for (const auto& n_map_pair : refinement_map.ila_state_var_map) { + ERR_IF(_host->find_state(n_map_pair.first) == nullptr, + "state `" + n_map_pair.first + "` not defined in ILA"); } - for(const auto & n_map_pair : refinement_map.ila_input_var_map) { - ERR_IF(_host->find_input(n_map_pair.first) == nullptr, "input `" + n_map_pair.first + "` not defined in ILA"); + for (const auto& n_map_pair : refinement_map.ila_input_var_map) { + ERR_IF(_host->find_input(n_map_pair.first) == nullptr, + "input `" + n_map_pair.first + "` not defined in ILA"); } #undef ERR_IF } - void VlgSglTgtGen::ConstructWrapper_add_additional_mapping_control() { - for(const auto & mapc : refinement_map.additional_mapping) { + for (const auto& mapc : refinement_map.additional_mapping) { add_an_assumption(mapc, "additional_mapping_control_assume"); } } // ConstructWrapper_add_additional_mapping_control void VlgSglTgtGen::ConstructWrapper_add_rf_assumptions() { - for (const auto & assumpt : refinement_map.assumptions) { + for (const auto& assumpt : refinement_map.assumptions) { add_an_assumption(assumpt, "rfassumptions"); } } // ConstructWrapper_add_rf_assumptions @@ -81,10 +91,10 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { name_to_fnapp_vec[func_app.func_name].push_back(func_app); } - for (const auto & uf_app : refinement_map.uf_application) { + for (const auto& uf_app : refinement_map.uf_application) { const auto& funcName = uf_app.first; const auto& list_of_time_of_apply = uf_app.second.func_applications; - if(!IN(funcName, name_to_fnapp_vec)) { + if (!IN(funcName, name_to_fnapp_vec)) { // ILA_WARN << "uninterpreted function mapping:" << funcName // << " does not exist. Skipped."; continue; @@ -103,41 +113,42 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { auto& ila_app_item = ila_app_list[idx]; idx++; if (each_apply.arg_map.size() != ila_app_item.args.size()) { - ILA_ERROR << "ila func app expect: " - << ila_app_item.args.size() << " (args)." + ILA_ERROR << "ila func app expect: " << ila_app_item.args.size() + << " (args)." << " Given:" << each_apply.arg_map.size() << " items, for func: " << funcName; continue; } - const auto & arg_apply = each_apply.arg_map; - const auto & result_apply = each_apply.result_map; - std::string func_result_wire = funcName + "_" + IntToStr(idx - 1) + "_result_wire"; + const auto& arg_apply = each_apply.arg_map; + const auto& result_apply = each_apply.result_map; + std::string func_result_wire = + funcName + "_" + IntToStr(idx - 1) + "_result_wire"; - auto res_map = rfmap_imply(rfmap_var("decode"), - rfmap_eq(rfmap_var(func_result_wire), result_apply)); + auto res_map = + rfmap_imply(rfmap_var("decode"), + rfmap_eq(rfmap_var(func_result_wire), result_apply)); std::vector prep; size_t arg_idx = 0; - for (const auto & each_arg : arg_apply) { + for (const auto& each_arg : arg_apply) { std::string func_arg = funcName + "_" + IntToStr(idx - 1) + "_arg" + IntToStr(arg_idx++) + "_wire"; - prep.push_back( - rfmap_imply(rfmap_var("decode"), - rfmap_eq(rfmap_var(func_arg), each_arg))); + prep.push_back(rfmap_imply(rfmap_var("decode"), + rfmap_eq(rfmap_var(func_arg), each_arg))); } // ( - // (decode |-> arg0_output == ??@?? ) && (decode |-> arg1_output == ??@?? ) + // (decode |-> arg0_output == ??@?? ) && (decode |-> arg1_output == + // ??@?? ) // && ... // ) |-> ( // (decode |-> result_input == ??@??) // ) - auto pre_cond = prep.empty() ? rfmap_true(): rfmap_and(prep); - add_an_assumption( - rfmap_imply(pre_cond, res_map), "funcmap"); + auto pre_cond = prep.empty() ? rfmap_true() : rfmap_and(prep); + add_an_assumption(rfmap_imply(pre_cond, res_map), "funcmap"); } // for each apply in the list of apply - name_to_fnapp_vec.erase(funcName); // remove from it + name_to_fnapp_vec.erase(funcName); // remove from it } // check for unmapped func @@ -145,60 +156,62 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { ILA_ERROR << "lacking function map for func:" << nf.first; } // ConstructWrapper_add_uf_constraints - void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { - for(const auto & delay_unit : refinement_map.aux_delays) { - const auto & name = delay_unit.first; - const auto & du = delay_unit.second; + for (const auto& delay_unit : refinement_map.aux_delays) { + const auto& name = delay_unit.first; + const auto& du = delay_unit.second; unsigned width = du.width; auto rhs = du.signal; - if (du.delay_type != rfmap::SignalDelay::delay_typeT::SINGLE && du.width > 1) { + if (du.delay_type != rfmap::SignalDelay::delay_typeT::SINGLE && + du.width > 1) { width = 1; - rhs = rfmap_reduce_or( rhs ); + rhs = rfmap_reduce_or(rhs); } - + ILA_ERROR_IF(du.num_cycle == 0) << "Cannot delay 0 cycle"; std::string last_reg; - for(size_t didx = 1; didx <= du.num_cycle; ++ didx) { - auto curr_name = name+"_d_"+std::to_string(didx); - auto prev_name = name+"_d_"+std::to_string(didx-1); + for (size_t didx = 1; didx <= du.num_cycle; ++didx) { + auto curr_name = name + "_d_" + std::to_string(didx); + auto prev_name = name + "_d_" + std::to_string(didx - 1); vlg_wrapper.add_reg(curr_name, width); - if(didx == 1) { + if (didx == 1) { // delay from signal - vlg_wrapper.add_wire(prev_name, width , true); + vlg_wrapper.add_wire(prev_name, width, true); rfmap_add_internal_wire(prev_name, width); add_wire_assign_assumption(prev_name, rhs, "delay_unit"); } vlg_wrapper.add_always_stmt(curr_name + " <= " + prev_name + " ;"); vlg_wrapper.add_init_stmt(curr_name + "<= 0;"); - if(didx == du.num_cycle) + if (didx == du.num_cycle) last_reg = curr_name; } // end - for each delay - if(du.delay_type == rfmap::SignalDelay::delay_typeT::SINGLE) { + if (du.delay_type == rfmap::SignalDelay::delay_typeT::SINGLE) { vlg_wrapper.add_wire(name, width); vlg_wrapper.add_assign_stmt(name, last_reg); continue; } // else - if(du.delay_type == rfmap::SignalDelay::delay_typeT::TO_INFINITE) { - auto summary_var = name+"_inf_"; + if (du.delay_type == rfmap::SignalDelay::delay_typeT::TO_INFINITE) { + auto summary_var = name + "_inf_"; vlg_wrapper.add_reg(summary_var, 1); vlg_wrapper.add_init_stmt(summary_var + "<= 1'b0;"); - vlg_wrapper.add_always_stmt("if( " + last_reg + ") " + summary_var + " <= 1'b1;"); + vlg_wrapper.add_always_stmt("if( " + last_reg + ") " + summary_var + + " <= 1'b1;"); vlg_wrapper.add_wire(name, 1); vlg_wrapper.add_assign_stmt(name, summary_var + " || " + last_reg); continue; } // finally the range // if (du.delay_type == rfmap::SignalDelay::delay_typeT::RANGE) - ILA_ERROR_IF(du.upper_bnd <= du.num_cycle) << "in `##[l:u]`, we need `l < u` "; + ILA_ERROR_IF(du.upper_bnd <= du.num_cycle) + << "in `##[l:u]`, we need `l < u` "; std::string or_reduce = last_reg; - for(size_t didx = du.num_cycle+1; didx <= du.upper_bnd; ++ didx) { - auto curr_name = name+"_d_"+std::to_string(didx); - auto prev_name = name+"_d_"+std::to_string(didx-1); + for (size_t didx = du.num_cycle + 1; didx <= du.upper_bnd; ++didx) { + auto curr_name = name + "_d_" + std::to_string(didx); + auto prev_name = name + "_d_" + std::to_string(didx - 1); vlg_wrapper.add_reg(curr_name, 1); vlg_wrapper.add_init_stmt(curr_name + " <= 0;"); vlg_wrapper.add_always_stmt(curr_name + " <= " + prev_name + " ;"); - + or_reduce += " || " + curr_name; } vlg_wrapper.add_wire(name, 1); @@ -207,72 +220,79 @@ void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { } // end ConstructWrapper_add_delay_unit void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { - for(const auto & n_tracker : refinement_map.phase_tracker) { - const auto & tracker_name = n_tracker.first; - const auto & tracker = n_tracker.second; + for (const auto& n_tracker : refinement_map.phase_tracker) { + const auto& tracker_name = n_tracker.first; + const auto& tracker = n_tracker.second; - for (const auto & vardef : tracker.var_defs) { + for (const auto& vardef : tracker.var_defs) { // already in refinement_map.all_var_def_types - const auto & vn = vardef.first; - if ( vardef.second.type == rfmap::GeneralVerilogMonitor::VarDef::var_type::REG ) + const auto& vn = vardef.first; + if (vardef.second.type == + rfmap::GeneralVerilogMonitor::VarDef::var_type::REG) vlg_wrapper.add_reg(vn, vardef.second.width); else vlg_wrapper.add_wire(vn, vardef.second.width); } - for ( const auto & event_alias : tracker.event_alias) { - vlg_wrapper.add_wire( event_alias.first, 1); - rfmap_add_internal_wire( event_alias.first, 1); + for (const auto& event_alias : tracker.event_alias) { + vlg_wrapper.add_wire(event_alias.first, 1); + rfmap_add_internal_wire(event_alias.first, 1); // add_wire_assign_assumption - add_wire_assign_assumption(event_alias.first, event_alias.second, "stage_tracker"); + add_wire_assign_assumption(event_alias.first, event_alias.second, + "stage_tracker"); } unsigned sidx = 0; - for (const auto & stage : tracker.rules) { - const std::string & stage_name = stage.stage_name; - ILA_CHECK(!stage_name.empty()) << "stage name is empty for " << tracker_name; - vlg_wrapper.add_reg(stage_name , 1); + for (const auto& stage : tracker.rules) { + const std::string& stage_name = stage.stage_name; + ILA_CHECK(!stage_name.empty()) + << "stage name is empty for " << tracker_name; + vlg_wrapper.add_reg(stage_name, 1); std::string enter_cond_wire_name = stage_name + "_enter_cond"; std::string exit_cond_wire_name = stage_name + "_exit_cond"; std::string enter_action_wire_name = stage_name + "_enter_action"; std::string exit_action_wire_name = stage_name + "_exit_action"; - + vlg_wrapper.add_init_stmt(stage_name + "<= 1'b0;"); - vlg_wrapper.add_always_stmt("if(" + enter_cond_wire_name + ") begin " + stage_name + " <= 1'b1;" ); + vlg_wrapper.add_always_stmt("if(" + enter_cond_wire_name + ") begin " + + stage_name + " <= 1'b1;"); vlg_wrapper.add_wire(enter_cond_wire_name, 1, true); rfmap_add_internal_wire(enter_cond_wire_name, 1); - add_wire_assign_assumption(enter_cond_wire_name, stage.enter_rule, "phase_tracker" ); + add_wire_assign_assumption(enter_cond_wire_name, stage.enter_rule, + "phase_tracker"); unsigned idx = 0; - for(const auto & action : stage.enter_action) { + for (const auto& action : stage.enter_action) { auto pos_def_var = refinement_map.all_var_def_types.find(action.LHS); ILA_ERROR_IF(pos_def_var == refinement_map.all_var_def_types.end()) - << "Cannot find var def for " << action.LHS << " used in LHS of phase tracker " - << tracker_name; + << "Cannot find var def for " << action.LHS + << " used in LHS of phase tracker " << tracker_name; - std::string action_name = enter_action_wire_name+std::to_string(idx++); + std::string action_name = + enter_action_wire_name + std::to_string(idx++); vlg_wrapper.add_always_stmt(action.LHS + " <= " + action_name + ";"); - - + vlg_wrapper.add_wire(action_name, pos_def_var->second.width, true); rfmap_add_internal_wire(action_name, pos_def_var->second.width); add_wire_assign_assumption(action_name, action.RHS, "phase_tracker"); } vlg_wrapper.add_always_stmt("end"); - vlg_wrapper.add_always_stmt("else if(" + exit_cond_wire_name + ") begin " + stage_name + " <= 1'b0;"); + vlg_wrapper.add_always_stmt("else if(" + exit_cond_wire_name + + ") begin " + stage_name + " <= 1'b0;"); vlg_wrapper.add_wire(exit_cond_wire_name, 1, true); rfmap_add_internal_wire(exit_cond_wire_name, 1); - add_wire_assign_assumption(exit_cond_wire_name, stage.exit_rule, "phase_tracker" ); + add_wire_assign_assumption(exit_cond_wire_name, stage.exit_rule, + "phase_tracker"); idx = 0; - for(const auto & action : stage.exit_action){ + for (const auto& action : stage.exit_action) { auto pos_def_var = refinement_map.all_var_def_types.find(action.LHS); ILA_ERROR_IF(pos_def_var == refinement_map.all_var_def_types.end()) - << "Cannot find var def for " << action.LHS << " used in LHS of phase tracker " - << tracker_name; + << "Cannot find var def for " << action.LHS + << " used in LHS of phase tracker " << tracker_name; - std::string action_name = exit_action_wire_name+std::to_string(idx++); + std::string action_name = exit_action_wire_name + std::to_string(idx++); vlg_wrapper.add_always_stmt(action.LHS + " <= " + action_name + ";"); vlg_wrapper.add_wire(action_name, pos_def_var->second.width, true); rfmap_add_internal_wire(action_name, pos_def_var->second.width); @@ -281,84 +301,79 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { vlg_wrapper.add_always_stmt("end"); - sidx ++; + sidx++; } // for each stage - } // for each tracker + } // for each tracker } // ConstructWrapper_add_stage_tracker void VlgSglTgtGen::ConstructWrapper_add_post_value_holder() { - for(const auto & post_val_holder : refinement_map.value_recorder) { - const auto & pv_name = post_val_holder.first; + for (const auto& post_val_holder : refinement_map.value_recorder) { + const auto& pv_name = post_val_holder.first; vlg_wrapper.add_reg(pv_name, post_val_holder.second.width); rfmap_add_internal_reg(pv_name, post_val_holder.second.width); - auto eq_cond = _vtg_config.EnforcingValueRecorderForOnlyOneCycle ? - rfmap_and({ - rfmap_or( rfmap_var("__START__"), rfmap_var("__STARTED__") ), - rfmap_not(rfmap_var(pv_name+"_sn_condmet")), - post_val_holder.second.condition - }) - : - post_val_holder.second.condition; - - add_reg_cassign_assumption(pv_name, - post_val_holder.second.value, - post_val_holder.second.width, - eq_cond, - "post_value_holder"); + auto eq_cond = + _vtg_config.EnforcingValueRecorderForOnlyOneCycle + ? rfmap_and( + {rfmap_or(rfmap_var("__START__"), rfmap_var("__STARTED__")), + rfmap_not(rfmap_var(pv_name + "_sn_condmet")), + post_val_holder.second.condition}) + : post_val_holder.second.condition; + + add_reg_cassign_assumption(pv_name, post_val_holder.second.value, + post_val_holder.second.width, eq_cond, + "post_value_holder"); // for sanity check - vlg_wrapper.add_reg(pv_name+"_sn_vhold", post_val_holder.second.width); - rfmap_add_internal_reg(pv_name+"_sn_vhold", post_val_holder.second.width); - vlg_wrapper.add_wire(pv_name+"_sn_value", post_val_holder.second.width); - rfmap_add_internal_wire(pv_name+"_sn_value", post_val_holder.second.width); - - vlg_wrapper.add_reg(pv_name+"_sn_condmet", 1); - rfmap_add_internal_reg(pv_name+"_sn_condmet", 1); - vlg_wrapper.add_wire(pv_name+"_sn_cond", 1); - rfmap_add_internal_wire(pv_name+"_sn_cond", 1); - vlg_wrapper.add_init_stmt(pv_name+"_sn_condmet <= 1'b0;"); - vlg_wrapper.add_always_stmt("if (" + pv_name+"_sn_cond ) begin " - + pv_name+"_sn_condmet <= 1'b1; " - + pv_name+"_sn_vhold <= " + pv_name+ "_sn_value; end" - ); + vlg_wrapper.add_reg(pv_name + "_sn_vhold", post_val_holder.second.width); + rfmap_add_internal_reg(pv_name + "_sn_vhold", post_val_holder.second.width); + vlg_wrapper.add_wire(pv_name + "_sn_value", post_val_holder.second.width); + rfmap_add_internal_wire(pv_name + "_sn_value", + post_val_holder.second.width); + + vlg_wrapper.add_reg(pv_name + "_sn_condmet", 1); + rfmap_add_internal_reg(pv_name + "_sn_condmet", 1); + vlg_wrapper.add_wire(pv_name + "_sn_cond", 1); + rfmap_add_internal_wire(pv_name + "_sn_cond", 1); + vlg_wrapper.add_init_stmt(pv_name + "_sn_condmet <= 1'b0;"); + vlg_wrapper.add_always_stmt("if (" + pv_name + "_sn_cond ) begin " + + pv_name + "_sn_condmet <= 1'b1; " + pv_name + + "_sn_vhold <= " + pv_name + "_sn_value; end"); // pv_sn_cond = && ( __START__ || __STARTED__ ) - add_wire_assign_assumption(pv_name+"_sn_cond", - rfmap_and( - post_val_holder.second.condition, - rfmap_or( rfmap_var("__START__"), rfmap_var("__STARTED__") )), - "pvholder_cond_assign"); - + add_wire_assign_assumption( + pv_name + "_sn_cond", + rfmap_and(post_val_holder.second.condition, + rfmap_or(rfmap_var("__START__"), rfmap_var("__STARTED__"))), + "pvholder_cond_assign"); + // pv_sn_value = - add_wire_assign_assumption(pv_name+"_sn_value", - post_val_holder.second.value, - "pvholder_cond_assign"); + add_wire_assign_assumption(pv_name + "_sn_value", + post_val_holder.second.value, + "pvholder_cond_assign"); add_a_santiy_assertion( - // cond && cond_met |-> value == value_stored - rfmap_imply( - rfmap_and(rfmap_var(pv_name+"_sn_condmet"), - rfmap_var(pv_name+"_sn_cond")), - rfmap_eq( rfmap_var(pv_name+"_sn_value"), - rfmap_var(pv_name+"_sn_vhold"))), - "post_value_holder"); - + // cond && cond_met |-> value == value_stored + rfmap_imply(rfmap_and(rfmap_var(pv_name + "_sn_condmet"), + rfmap_var(pv_name + "_sn_cond")), + rfmap_eq(rfmap_var(pv_name + "_sn_value"), + rfmap_var(pv_name + "_sn_vhold"))), + "post_value_holder"); // you need to add checker - // check no + // check no } } // ConstructWrapper_add_post_value_holder void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { - if(refinement_map.customized_monitor.empty()) + if (refinement_map.customized_monitor.empty()) return; - + const auto& monitor_rec = refinement_map.customized_monitor; for (auto&& m_rec : monitor_rec) { - + const auto& mname = m_rec.first; const auto& mdef = m_rec.second; // generalMonitor @@ -370,9 +385,10 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { !keep_for_non_instruction_target) continue; - for (const auto & n_def : mdef.var_defs) { + for (const auto& n_def : mdef.var_defs) { // already in refinement_map.all_var_def - if(n_def.second.type == rfmap::GeneralVerilogMonitor::VarDef::var_type::REG) + if (n_def.second.type == + rfmap::GeneralVerilogMonitor::VarDef::var_type::REG) vlg_wrapper.add_reg(n_def.first, n_def.second.width); else vlg_wrapper.add_wire(n_def.first, n_def.second.width); @@ -380,41 +396,41 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { unsigned idx = 0; std::vector> replace_list; - for (const auto & vref : mdef.var_uses) { + for (const auto& vref : mdef.var_uses) { auto vref_node = rfmap::VerilogRefinementMap::ParseRfExprFromString(vref); - auto new_name = mname + "_auxvar" + std::to_string(idx ++); - + auto new_name = mname + "_auxvar" + std::to_string(idx++); auto tp = refinement_map.TypeInferTravserRfExpr(vref_node); - ILA_ERROR_IF(tp.is_unknown()) << "Cannot determine width of " - << vref << " in monitor " << mname; + ILA_ERROR_IF(tp.is_unknown()) + << "Cannot determine width of " << vref << " in monitor " << mname; - auto width = tp.unified_width(); + auto width = tp.unified_width(); vlg_wrapper.add_wire(new_name, width, true); rfmap_add_internal_wire(new_name, width); - add_wire_assign_assumption(new_name, vref_node, "monitor_auxvar"); + add_wire_assign_assumption(new_name, vref_node, "monitor_auxvar"); replace_list.push_back(std::make_pair(vref, new_name)); } auto vlog_inline = mdef.verilog_inline; - for (const auto & old_new_pair : replace_list) { - vlog_inline = ReplaceAll(vlog_inline, old_new_pair.first, old_new_pair.second); + for (const auto& old_new_pair : replace_list) { + vlog_inline = + ReplaceAll(vlog_inline, old_new_pair.first, old_new_pair.second); } vlg_wrapper.add_stmt(vlog_inline); - + } // for monitor_rec.items() } // ConstructWrapper_add_vlg_monitor - -const rfmap::InstructionCompleteCondition & VlgSglTgtGen::get_current_instruction_rf() { +const rfmap::InstructionCompleteCondition& +VlgSglTgtGen::get_current_instruction_rf() { ILA_NOT_NULL(_instr_ptr); - const auto & inst_name = _instr_ptr->name().str(); + const auto& inst_name = _instr_ptr->name().str(); auto pos = refinement_map.inst_complete_cond.find(inst_name); ILA_ERROR_IF(pos == refinement_map.inst_complete_cond.end()) - << "Cannot find the completion condition for " << inst_name; + << "Cannot find the completion condition for " << inst_name; return pos->second; } // get_current_instruction_rf diff --git a/src/vtarget-out/vlg_mod.cc b/src/vtarget-out/vlg_mod.cc index 33242a4eb..0c85a0870 100644 --- a/src/vtarget-out/vlg_mod.cc +++ b/src/vtarget-out/vlg_mod.cc @@ -268,17 +268,14 @@ void VerilogModifier::RecordAdditionalVlgModuleStmt( add_stmt_map[loc.first].push_back(add_stmt_t(loc.second, stmt)); } - // RTL.a.b.c[3] // vname : RTL__DOT__a__DOT__b__DOT__c_3_ // hiearchy RTL.a.b // last_level_name c[3] -void VerilogModifier::RecordConnectSigName( - const std::string& vname, // wirename - const std::string& hierarchy, // - const std::string& last_level_name, - unsigned width) -{ +void VerilogModifier::RecordConnectSigName(const std::string& vname, // wirename + const std::string& hierarchy, // + const std::string& last_level_name, + unsigned width) { ILA_CHECK(width != 0); auto mod_hier_name = Split(hierarchy, "."); @@ -319,7 +316,7 @@ void VerilogModifier::RecordConnectSigName( } // RecordConnectSigName -#if 0 // the old implementation +#if 0 // the old implementation /// record the name to add a keep there VerilogModifier::vlg_sig_t VerilogModifier::RecordConnectSigName(const std::string& vlg_sig_name, diff --git a/src/vtarget-out/vtarget_gen.cc b/src/vtarget-out/vtarget_gen.cc index b634b6e21..2c6e9a645 100644 --- a/src/vtarget-out/vtarget_gen.cc +++ b/src/vtarget-out/vtarget_gen.cc @@ -44,10 +44,9 @@ VerilogVerificationTargetGenerator::VerilogVerificationTargetGenerator( : _generator(new VlgVerifTgtGen( implementation_include_path, implementation_srcs, implementation_top_module, - rfmap::VerilogRefinementMap( - refinement_variable_mapping,refinement_conditions), - output_path, ila_ptr, backend, vtg_config, - NULL)) {} + rfmap::VerilogRefinementMap(refinement_variable_mapping, + refinement_conditions), + output_path, ila_ptr, backend, vtg_config, NULL)) {} VerilogVerificationTargetGenerator::~VerilogVerificationTargetGenerator() { if (_generator) diff --git a/src/vtarget-out/vtarget_gen_impl.cc b/src/vtarget-out/vtarget_gen_impl.cc index b834023cb..6211e71d4 100644 --- a/src/vtarget-out/vtarget_gen_impl.cc +++ b/src/vtarget-out/vtarget_gen_impl.cc @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include // #include // #include // for invariant synthesis @@ -29,29 +29,25 @@ VlgVerifTgtGen::VlgVerifTgtGen( const std::vector& implementation_include_path, const std::vector& implementation_srcs, const std::string& implementation_top_module, - const rfmap::VerilogRefinementMap & refinement, - const std::string& output_path, - const InstrLvlAbsPtr& ila_ptr, - backend_selector backend, - const vtg_config_t& vtg_config, + const rfmap::VerilogRefinementMap& refinement, + const std::string& output_path, const InstrLvlAbsPtr& ila_ptr, + backend_selector backend, const vtg_config_t& vtg_config, advanced_parameters_t* adv_ptr) : _vlg_impl_include_path(implementation_include_path), _vlg_impl_srcs(implementation_srcs), - _vlg_impl_top_name(implementation_top_module), - _refinement(refinement), - _output_path(output_path), - _ila_ptr(ila_ptr), + _vlg_impl_top_name(implementation_top_module), _refinement(refinement), + _output_path(output_path), _ila_ptr(ila_ptr), // configure is only for ila, generate the start signal vlg_info_ptr( NULL), // not creating it now, because we don't have the info to do so - _backend(backend), _vtg_config(vtg_config), - _advanced_param_ptr(adv_ptr), _bad_state(false) { - + _backend(backend), _vtg_config(vtg_config), _advanced_param_ptr(adv_ptr), + _bad_state(false) { + if (_ila_ptr == nullptr) { ILA_ERROR << "ILA should not be none"; _bad_state = true; } - + // TODO: check more } @@ -64,15 +60,14 @@ const std::vector& VlgVerifTgtGen::GetRunnableScriptName() const { return runnable_script_name; } - void VlgVerifTgtGen::GenerateTargets(void) { if (bad_state_return()) return; runnable_script_name.clear(); - vlg_info_ptr = new VerilogInfo(_vlg_impl_include_path, _vlg_impl_srcs, - "RTL", _vlg_impl_top_name); + vlg_info_ptr = new VerilogInfo(_vlg_impl_include_path, _vlg_impl_srcs, "RTL", + _vlg_impl_top_name); if (vlg_info_ptr == NULL || vlg_info_ptr->in_bad_state()) { ILA_ERROR << "Unable to generate targets. Verilog parser failed."; @@ -88,36 +83,32 @@ void VlgVerifTgtGen::GenerateTargets(void) { _vtg_config.target_select == vtg_config_t::INV) { // check if there are really invariants: bool invariantExists = false; - if(!_refinement.global_invariants.empty()) + if (!_refinement.global_invariants.empty()) invariantExists = true; - + if ((_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::ALL || - _vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::CONFIRMED) && - (_advanced_param_ptr && - _advanced_param_ptr->_inv_obj_ptr != NULL && - !_advanced_param_ptr->_inv_obj_ptr->GetVlgConstraints() - .empty())) - invariantExists = true; + vtg_config_t::_validate_synthesized_inv::ALL || + _vtg_config.ValidateSynthesizedInvariant == + vtg_config_t::_validate_synthesized_inv::CONFIRMED) && + (_advanced_param_ptr && _advanced_param_ptr->_inv_obj_ptr != NULL && + !_advanced_param_ptr->_inv_obj_ptr->GetVlgConstraints().empty())) + invariantExists = true; if ((_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::ALL || - _vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::CANDIDATE) && - (_advanced_param_ptr && - _advanced_param_ptr->_candidate_inv_ptr != NULL && - !_advanced_param_ptr->_candidate_inv_ptr->GetVlgConstraints() - .empty())) - invariantExists = true; + vtg_config_t::_validate_synthesized_inv::ALL || + _vtg_config.ValidateSynthesizedInvariant == + vtg_config_t::_validate_synthesized_inv::CANDIDATE) && + (_advanced_param_ptr && + _advanced_param_ptr->_candidate_inv_ptr != NULL && + !_advanced_param_ptr->_candidate_inv_ptr->GetVlgConstraints().empty())) + invariantExists = true; auto sub_output_path = os_portable_append_dir(_output_path, "invariants"); if (_backend == backend_selector::PONO && invariantExists) { auto target = VlgSglTgtGen_Pono( sub_output_path, NULL, // invariant - _ila_ptr, _refinement, vlg_info_ptr, - "wrapper", _vlg_impl_srcs, + _ila_ptr, _refinement, vlg_info_ptr, "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INVARIANTS, _advanced_param_ptr); target.ConstructWrapper(); @@ -127,8 +118,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { auto target = VlgSglTgtGen_Jasper( sub_output_path, NULL, // invariant - _ila_ptr, _refinement, vlg_info_ptr, - "wrapper", _vlg_impl_srcs, + _ila_ptr, _refinement, vlg_info_ptr, "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INVARIANTS, _advanced_param_ptr); target.ConstructWrapper(); @@ -205,8 +195,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { auto target = VlgSglTgtGen_Pono( sub_output_path, instr_ptr, // instruction - _ila_ptr, _refinement, vlg_info_ptr, - "wrapper", _vlg_impl_srcs, + _ila_ptr, _refinement, vlg_info_ptr, "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INSTRUCTIONS, _advanced_param_ptr); target.ConstructWrapper(); @@ -216,8 +205,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { auto target = VlgSglTgtGen_Jasper( sub_output_path, instr_ptr, // instruction - _ila_ptr, _refinement, vlg_info_ptr, - "wrapper", _vlg_impl_srcs, + _ila_ptr, _refinement, vlg_info_ptr, "wrapper", _vlg_impl_srcs, _vlg_impl_include_path, _vtg_config, _backend, target_type_t::INSTRUCTIONS, _advanced_param_ptr); target.ConstructWrapper(); @@ -287,7 +275,6 @@ bool VlgVerifTgtGen::bad_state_return(void) { return _bad_state; } // bad_state_return - #if 0 std::shared_ptr diff --git a/src/vtarget-out/vtarget_gen_jasper.cc b/src/vtarget-out/vtarget_gen_jasper.cc index ccf5a8d91..847cd6a6a 100644 --- a/src/vtarget-out/vtarget_gen_jasper.cc +++ b/src/vtarget-out/vtarget_gen_jasper.cc @@ -19,32 +19,31 @@ VlgSglTgtGen_Jasper::VlgSglTgtGen_Jasper( output_path, // will be a sub directory of the output_path of its parent const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const rfmap::VerilogRefinementMap & refinement, - VerilogInfo* _vlg_info_ptr, + const InstrLvlAbsPtr& ila_ptr, + const rfmap::VerilogRefinementMap& refinement, VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, const vtg_config_t& vtg_config, backend_selector backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, refinement, - _vlg_info_ptr, wrapper_name, implementation_srcs, + : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, refinement, _vlg_info_ptr, + wrapper_name, implementation_srcs, implementation_include_path, vtg_config, backend, target_tp, adv_ptr) {} /// Add SMT-lib2 assumption void VlgSglTgtGen_Jasper::add_a_direct_smt_assumption(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) { - ILA_CHECK(false) << "SMT assumption should not be generated for JasperGold"; + const std::string& ret, + const std::string& body, + const std::string& dspt) { + ILA_CHECK(false) << "SMT assumption should not be generated for JasperGold"; } /// Add SMT-lib2 assertion void VlgSglTgtGen_Jasper::add_a_direct_smt_assertion(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) { + const std::string& ret, + const std::string& body, + const std::string& dspt) { ILA_CHECK(false) << "SMT assertions should not be generated for JasperGold"; } @@ -59,7 +58,6 @@ void VlgSglTgtGen_Jasper::add_a_direct_assertion(const std::string& asst, assertions.push_back(std::make_pair(asst, dspt)); } - /// export the script to run the verification void VlgSglTgtGen_Jasper::Export_script(const std::string& script_name) { auto fn = os_portable_append_dir(_output_path, script_name); @@ -108,8 +106,7 @@ void VlgSglTgtGen_Jasper::Export_problem(const std::string& extra_name) { for (auto&& asst_dspt_pair : assertions) fout << "assert -name " << asst_dspt_pair.second + std::to_string(No++) << " {" << asst_dspt_pair.first << "}" << std::endl; - -} +} /// For jasper, this means do nothing, for yosys, you need to add (*keep*) void VlgSglTgtGen_Jasper::Export_modify_verilog() { diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index d8abc9b9c..9b593930d 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -17,7 +17,6 @@ namespace ilang { #define VLG_TRUE "`true" #define VLG_FALSE "`false" - // should not be used static std::string yosysGenerateBtor = R"***( hierarchy -check @@ -28,34 +27,31 @@ memory -nomap; flatten sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% )***"; -// %propselect% is for - +// %propselect% is for VlgSglTgtGen_Pono::VlgSglTgtGen_Pono( const std::string& output_path, // will be a sub directory of the output_path of its parent const InstrPtr& instr_ptr, // which could be an empty pointer, and it will // be used to verify invariants - const InstrLvlAbsPtr& ila_ptr, - const rfmap::VerilogRefinementMap & refinement, - VerilogInfo* _vlg_info_ptr, + const InstrLvlAbsPtr& ila_ptr, + const rfmap::VerilogRefinementMap& refinement, VerilogInfo* _vlg_info_ptr, const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, const vtg_config_t& vtg_config, backend_selector vbackend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr) - : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, refinement, - _vlg_info_ptr, wrapper_name, implementation_srcs, + : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, refinement, _vlg_info_ptr, + wrapper_name, implementation_srcs, implementation_include_path, vtg_config, vbackend, target_tp, adv_ptr) {} - /// Add an assumption void VlgSglTgtGen_Pono::add_a_direct_assumption(const std::string& aspt, const std::string& dspt) { auto wire_name = dspt + new_property_id(); - vlg_wrapper.add_wire(wire_name,1); - vlg_wrapper.add_output(wire_name,1); + vlg_wrapper.add_wire(wire_name, 1); + vlg_wrapper.add_output(wire_name, 1); vlg_wrapper.add_assign_stmt(wire_name, aspt); _problems.assumptions[dspt].exprs.push_back(wire_name); } @@ -63,19 +59,18 @@ void VlgSglTgtGen_Pono::add_a_direct_assumption(const std::string& aspt, void VlgSglTgtGen_Pono::add_a_direct_assertion(const std::string& asst, const std::string& dspt) { auto wire_name = dspt + new_property_id(); - vlg_wrapper.add_wire(wire_name,1); - vlg_wrapper.add_output(wire_name,1); + vlg_wrapper.add_wire(wire_name, 1); + vlg_wrapper.add_output(wire_name, 1); vlg_wrapper.add_assign_stmt(wire_name, asst); _problems.assertions[dspt].exprs.push_back(wire_name); } - /// Add an assertion void VlgSglTgtGen_Pono::add_a_direct_sanity_assertion(const std::string& asst, - const std::string& dspt) { + const std::string& dspt) { auto wire_name = dspt + new_property_id(); - vlg_wrapper.add_wire(wire_name,1); - vlg_wrapper.add_output(wire_name,1); + vlg_wrapper.add_wire(wire_name, 1); + vlg_wrapper.add_output(wire_name, 1); vlg_wrapper.add_assign_stmt(wire_name, asst); _problems.sanity_assertions[dspt].exprs.push_back(wire_name); } @@ -90,16 +85,14 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { return; } fout << "#!/bin/bash" << std::endl; - - + std::string yosys = "yosys"; if (!_vtg_config.YosysPath.empty()) yosys = os_portable_append_dir(_vtg_config.YosysPath, yosys); // execute it - fout << yosys << " -s " << ys_script_name << " > __yosys_exec_result.txt\n"; - + fout << yosys << " -s " << ys_script_name << " > __yosys_exec_result.txt\n"; std::string pono = "pono"; std::string options; @@ -119,51 +112,55 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { } std::string extra_smt_properties; - if(!_problems.smt_assertions.empty() || !_problems.smt_assumptions.empty()) { + if (!_problems.smt_assertions.empty() || !_problems.smt_assumptions.empty()) { extra_smt_properties += " --property-file property.smt2 "; } - fout << pono << options << extra_smt_properties << " problem.btor2 " << std::endl; + fout << pono << options << extra_smt_properties << " problem.btor2 " + << std::endl; - if(!_problems.sanity_assertions.empty()) { - fout << yosys << " -s gen_sanity_prop.ys > __yosys_exec_result.sanity.txt\n"; + if (!_problems.sanity_assertions.empty()) { + fout << yosys + << " -s gen_sanity_prop.ys > __yosys_exec_result.sanity.txt\n"; // here we intentionally leave out the property interface file. fout << pono << options << " sanity.btor2 " << std::endl; } } // Export_script - /// Add SMT-lib2 assumption void VlgSglTgtGen_Pono::add_a_direct_smt_assumption(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) { + const std::string& ret, + const std::string& body, + const std::string& dspt) { size_t idx = _problems.smt_assumptions.size(); - _problems.smt_assumptions.push_back( - "(define-fun assumption."+std::to_string(idx)+" " + arg + " " + ret + " " + body+")"); - + _problems.smt_assumptions.push_back("(define-fun assumption." + + std::to_string(idx) + " " + arg + " " + + ret + " " + body + ")"); } /// Add SMT-lib2 assertion void VlgSglTgtGen_Pono::add_a_direct_smt_assertion(const std::string& arg, - const std::string& ret, - const std::string& body, - const std::string& dspt) { + const std::string& ret, + const std::string& body, + const std::string& dspt) { size_t idx = _problems.smt_assertions.size(); - _problems.smt_assertions.push_back( - "(define-fun assertion."+std::to_string(idx)+" " + arg + " " + ret + " " + body+")"); + _problems.smt_assertions.push_back("(define-fun assertion." + + std::to_string(idx) + " " + arg + " " + + ret + " " + body + ")"); } /// export the yosys script void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { - if (_problems.assertions.empty() && _problems.smt_assertions.empty() && _problems.sanity_assertions.empty()) { + if (_problems.assertions.empty() && _problems.smt_assertions.empty() && + _problems.sanity_assertions.empty()) { ILA_ERROR << "Nothing to prove, no assertions inserted!"; return; } ys_script_name = yosys_script_name; - std::string ys_script_name_path = os_portable_append_dir(_output_path, ys_script_name); + std::string ys_script_name_path = + os_portable_append_dir(_output_path, ys_script_name); { // export to ys_script_name std::ofstream ys_script_fout(ys_script_name_path); @@ -177,51 +174,48 @@ void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { ys_script_fout << "prep -top " << top_mod_name << std::endl; std::string property_selection_cmd; - if(!_problems.sanity_assertions.empty()) { + if (!_problems.sanity_assertions.empty()) { property_selection_cmd = "\n" - "select wrapper/sanitycheck\n" - "chformal -remove\n" - "select *\n"; + "select wrapper/sanitycheck\n" + "chformal -remove\n" + "select *\n"; } - ys_script_fout << - ReplaceAll( + ys_script_fout << ReplaceAll( ReplaceAll( - ReplaceAll( - ReplaceAll(yosysGenerateBtor, - "%rstlen%", - std::to_string( - refinement_map.reset_specification.reset_cycle)), - "%cycle%", - std::to_string( - refinement_map.reset_specification.reset_cycle)), - "%module%", top_mod_name), - "%propselect%", property_selection_cmd); + ReplaceAll( + ReplaceAll(yosysGenerateBtor, "%rstlen%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%cycle%", + std::to_string(refinement_map.reset_specification.reset_cycle)), + "%module%", top_mod_name), + "%propselect%", property_selection_cmd); // this is for pono, I don't know why it is unhappy, but we need fix this // in the long run - if(_vtg_config.YosysSetUndrivenZero) + if (_vtg_config.YosysSetUndrivenZero) ys_script_fout << "setundef -undriven -zero\n"; - - ys_script_fout << "write_btor " << write_btor_options << " problem.btor2" << std::endl; + ys_script_fout << "write_btor " << write_btor_options << " problem.btor2" + << std::endl; } // finish writing auto smt_property_fname = os_portable_append_dir(_output_path, "property.smt2"); { std::ofstream smt_fout(smt_property_fname); - for(const auto & prop : _problems.smt_assumptions) + for (const auto& prop : _problems.smt_assumptions) smt_fout << prop << std::endl; - - for(const auto & prop : _problems.smt_assertions) + + for (const auto& prop : _problems.smt_assertions) smt_fout << prop << std::endl; } // sanity checks - if(!_problems.sanity_assertions.empty()) - { // export to ys_script_name - std::string ys_script_name_path = os_portable_append_dir(_output_path, "gen_sanity_prop.ys"); + if (!_problems.sanity_assertions.empty()) { // export to ys_script_name + std::string ys_script_name_path = + os_portable_append_dir(_output_path, "gen_sanity_prop.ys"); std::ofstream ys_script_fout(ys_script_name_path); std::string write_btor_options; @@ -234,36 +228,31 @@ void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { ys_script_fout << "prep -top " << top_mod_name << std::endl; std::string property_selection_cmd = "\n" - "select wrapper/normalassert\n" - "chformal -remove\n" - "select *\n"; + "select wrapper/normalassert\n" + "chformal -remove\n" + "select *\n"; - ys_script_fout << - ReplaceAll( + ys_script_fout << ReplaceAll( ReplaceAll( - ReplaceAll( - ReplaceAll(yosysGenerateBtor, - "%rstlen%", - std::to_string( - refinement_map.reset_specification.reset_cycle)), - "%cycle%", - std::to_string( - refinement_map.reset_specification.reset_cycle)), - "%module%", top_mod_name), - "%propselect%", property_selection_cmd); + ReplaceAll( + ReplaceAll(yosysGenerateBtor, "%rstlen%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%cycle%", + std::to_string(refinement_map.reset_specification.reset_cycle)), + "%module%", top_mod_name), + "%propselect%", property_selection_cmd); // this is for pono, I don't know why it is unhappy, but we need fix this // in the long run - if(_vtg_config.YosysSetUndrivenZero) + if (_vtg_config.YosysSetUndrivenZero) ys_script_fout << "setundef -undriven -zero\n"; - - ys_script_fout << "write_btor " << write_btor_options << " sanity.btor2" << std::endl; + ys_script_fout << "write_btor " << write_btor_options << " sanity.btor2" + << std::endl; } // finish writing } // only for Pono - - // PreExportProcess is about how to add assumption/assertions void VlgSglTgtGen_Pono::PreExportProcess() { @@ -306,15 +295,14 @@ void VlgSglTgtGen_Pono::PreExportProcess() { } // for expr } // for problem // add assert wire (though no use : make sure will not optimized away) - if(_problems.smt_assertions.empty()) + if (_problems.smt_assertions.empty()) ILA_CHECK(!all_assert_wire_content.empty()) << "no property to check!"; - - if(all_assert_wire_content.empty()) - { // in case all_assert_wire_content is empty + + if (all_assert_wire_content + .empty()) { // in case all_assert_wire_content is empty all_assert_wire_content = "1'b1"; // (assert true) } - // this is to check given sanity assertions for (auto&& pbname_prob_pair : _problems.sanity_assertions) { // const auto& prbname = pbname_prob_pair.first; @@ -332,31 +320,31 @@ void VlgSglTgtGen_Pono::PreExportProcess() { else all_sanity_assert_wire_content += " && (" + p + ")"; } // for expr - } + } vlg_wrapper.add_wire("__all_assert_wire__", 1, true); vlg_wrapper.add_output("__all_assert_wire__", 1); vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); - vlg_wrapper.add_stmt( - "normalassert: assert property ( __all_assert_wire__ ); // the only assertion \n"); - + vlg_wrapper.add_stmt("normalassert: assert property ( __all_assert_wire__ ); " + "// the only assertion \n"); + if (!all_assume_wire_content.empty()) { vlg_wrapper.add_wire("__all_assume_wire__", 1, true); vlg_wrapper.add_output("__all_assume_wire__", 1); vlg_wrapper.add_assign_stmt("__all_assume_wire__", all_assume_wire_content); - vlg_wrapper.add_stmt( - "all_assume: assume property ( __all_assume_wire__ ); // the only sanity assertion \n"); + vlg_wrapper.add_stmt("all_assume: assume property ( __all_assume_wire__ ); " + "// the only sanity assertion \n"); } if (!all_sanity_assert_wire_content.empty()) { vlg_wrapper.add_wire("__sanitycheck_wire__", 1, true); vlg_wrapper.add_output("__sanitycheck_wire__", 1); - vlg_wrapper.add_assign_stmt("__sanitycheck_wire__", all_sanity_assert_wire_content); + vlg_wrapper.add_assign_stmt("__sanitycheck_wire__", + all_sanity_assert_wire_content); - vlg_wrapper.add_stmt( - "sanitycheck: assert property ( __sanitycheck_wire__ ); // the only assumption \n"); - + vlg_wrapper.add_stmt("sanitycheck: assert property ( __sanitycheck_wire__ " + "); // the only assumption \n"); } } // PreExportProcess @@ -369,15 +357,13 @@ void VlgSglTgtGen_Pono::Export_modify_verilog() { VerilogModifier vlg_mod(vlg_info_ptr, static_cast( _vtg_config.PortDeclStyle), - _vtg_config.PonoAddKeep, - refinement_map.width_info); + _vtg_config.PonoAddKeep, refinement_map.width_info); - for (auto && wn_extraw : rtl_extra_wire) { + for (auto&& wn_extraw : rtl_extra_wire) { ILA_CHECK(StrStartsWith(wn_extraw.first, "RTL__DOT__")); - vlg_mod.RecordConnectSigName(wn_extraw.second.wire_name, - wn_extraw.second.hierarchy, - wn_extraw.second.internal_name, - wn_extraw.second.width); + vlg_mod.RecordConnectSigName( + wn_extraw.second.wire_name, wn_extraw.second.hierarchy, + wn_extraw.second.internal_name, wn_extraw.second.width); // will not record keep } vlg_mod.FinishRecording(); diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index 18e7c58eb..d4d126601 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -229,7 +229,6 @@ TEST(TestVlgTargetGen, PipeExampleRfmapPost) { vg.GenerateTargets(); } - TEST(TestVlgTargetGen, PipeStallRfmapShortNoValueHolder) { auto ila_model = SimplePipe::BuildStallModel(); @@ -237,15 +236,18 @@ TEST(TestVlgTargetGen, PipeStallRfmapShortNoValueHolder) { auto rfDir = os_portable_append_dir(dirName, "rfmap"); VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_append_dir(dirName, "simple_pipe_stall_short.v")}, // vlog files - "pipeline_v", // top_module_name + {}, // no include + {os_portable_append_dir(dirName, + "simple_pipe_stall_short.v")}, // vlog files + "pipeline_v", // top_module_name os_portable_append_dir(rfDir, "vmap-rfmap-stall-short.json"), // variable mapping - os_portable_append_dir(rfDir, - "cond-rfmap-stall-short.json"), // instruction-mapping - os_portable_append_dir(dirName, "verify_stall_short_nopvholder"), // verification dir - ila_model.get(), // ILA model + os_portable_append_dir( + rfDir, + "cond-rfmap-stall-short.json"), // instruction-mapping + os_portable_append_dir( + dirName, "verify_stall_short_nopvholder"), // verification dir + ila_model.get(), // ILA model VerilogVerificationTargetGenerator::backend_selector::PONO // engine ); @@ -261,15 +263,18 @@ TEST(TestVlgTargetGen, PipeStallRfmapShort) { auto rfDir = os_portable_append_dir(dirName, "rfmap"); VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_append_dir(dirName, "simple_pipe_stall_short.v")}, // vlog files - "pipeline_v", // top_module_name - os_portable_append_dir(rfDir, - "vmap-rfmap-pvholder-stall-short.json"), // variable mapping - os_portable_append_dir(rfDir, - "cond-rfmap-pvholder-stall-short.json"), // instruction-mapping + {}, // no include + {os_portable_append_dir(dirName, + "simple_pipe_stall_short.v")}, // vlog files + "pipeline_v", // top_module_name + os_portable_append_dir( + rfDir, + "vmap-rfmap-pvholder-stall-short.json"), // variable mapping + os_portable_append_dir( + rfDir, + "cond-rfmap-pvholder-stall-short.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_stall_short"), // verification dir - ila_model.get(), // ILA model + ila_model.get(), // ILA model VerilogVerificationTargetGenerator::backend_selector::PONO // engine ); @@ -278,7 +283,6 @@ TEST(TestVlgTargetGen, PipeStallRfmapShort) { vg.GenerateTargets(); } - TEST(TestVlgTargetGen, PipeStallRfmap) { auto ila_model = SimplePipe::BuildStallModel(); @@ -286,15 +290,17 @@ TEST(TestVlgTargetGen, PipeStallRfmap) { auto rfDir = os_portable_append_dir(dirName, "rfmap"); VerilogVerificationTargetGenerator vg( - {}, // no include + {}, // no include {os_portable_append_dir(dirName, "simple_pipe_stall.v")}, // vlog files - "pipeline_v", // top_module_name - os_portable_append_dir(rfDir, - "vmap-rfmap-pvholder-stall.json"), // variable mapping - os_portable_append_dir(rfDir, - "cond-rfmap-pvholder-stall.json"), // instruction-mapping + "pipeline_v", // top_module_name + os_portable_append_dir( + rfDir, + "vmap-rfmap-pvholder-stall.json"), // variable mapping + os_portable_append_dir( + rfDir, + "cond-rfmap-pvholder-stall.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_stall"), // verification dir - ila_model.get(), // ILA model + ila_model.get(), // ILA model VerilogVerificationTargetGenerator::backend_selector::PONO // engine ); @@ -328,7 +334,7 @@ TEST(TestVlgTargetGen, PipeExampleJasperGold) { TEST(TestVlgTargetGen, PipeExampleNotEqu) { auto ila_model = SimplePipe::BuildModel(); - + auto dirName = os_portable_join_dir({ILANG_TEST_SRC_ROOT, "unit-data", "vpipe"}); VerilogVerificationTargetGenerator vg( @@ -421,23 +427,22 @@ TEST(TestVlgTargetGen, MemoryInternalExternalEntry6) { DebugLog::Enable("VTG.ReplWireEq"); DebugLog::Enable("VTG.ReplAssert"); DebugLog::Enable("VTG.ReplAssume"); - + DebugLog::Enable("VTG.AddWireEq"); DebugLog::Enable("VTG.AddAssert"); DebugLog::Enable("VTG.AddAssume"); - VlgVerifTgtGenBase::vtg_config_t vtg_cfg; vtg_cfg.PonoAddKeep = false; auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; VerilogVerificationTargetGenerator vg( - {}, // no include - {dirName + "rf_as_mem_6rf.v"}, // vlog files - "proc", // top_module_name + {}, // no include + {dirName + "rf_as_mem_6rf.v"}, // vlog files + "proc", // top_module_name dirName + "vmap-rfarray6.json", // variable mapping - dirName + "cond-rfarray.json", // cond path - dirName + "rfarray_rf6/", // output path + dirName + "cond-rfarray.json", // cond path + dirName + "rfarray_rf6/", // output path ila_model.get(), VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg); @@ -465,7 +470,6 @@ TEST(TestVlgTargetGen, MemoryRead) { vg.GenerateTargets(); } - TEST(TestVlgTargetGen, MemoryReadAbsReadJasperGold) { VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; @@ -561,7 +565,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir( {dirName, "rfmap", "vmap.json"}), // variable mapping os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path - os_portable_append_dir(dirName, "out2"), // output path + os_portable_append_dir(dirName, "out2"), // output path ila_model.get(), VerilogVerificationTargetGenerator::backend_selector::PONO); @@ -571,5 +575,4 @@ TEST(TestVlgTargetGen, ResetAnnotation) { } } - }; // namespace ilang From 3be66b79f1558bcdf843b284e32ce25bf1c5f93b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 15 Oct 2021 14:39:23 +0800 Subject: [PATCH 41/78] add rtl verify api --- include/ilang/ilang++.h | 23 ++ include/ilang/rtl_verify.h | 251 ++++++++++++++++ include/ilang/vtarget-out/vtarget_gen.h | 267 +----------------- include/ilang/vtarget-out/vtarget_gen_impl.h | 23 +- .../ilang/vtarget-out/vtarget_gen_jasper.h | 2 +- include/ilang/vtarget-out/vtarget_gen_pono.h | 2 +- src/ilang++.cc | 27 ++ src/vtarget-out/gen_util.cc | 3 +- src/vtarget-out/single_target.cc | 4 +- src/vtarget-out/single_target_as.cc | 2 +- src/vtarget-out/single_target_cond.cc | 2 +- .../single_target_inv_syn_support.cc | 10 +- src/vtarget-out/vtarget_gen.cc | 26 +- src/vtarget-out/vtarget_gen_impl.cc | 62 ++-- src/vtarget-out/vtarget_gen_jasper.cc | 18 +- src/vtarget-out/vtarget_gen_pono.cc | 13 +- test/t_api.cc | 28 ++ test/t_inv_syn.cc | 60 ++-- test/t_vtarget_gen.cc | 210 ++------------ test/unit-data/vpipe/reset/out3/.gitignore | 1 + 20 files changed, 488 insertions(+), 546 deletions(-) create mode 100644 include/ilang/rtl_verify.h create mode 100644 test/unit-data/vpipe/reset/out3/.gitignore diff --git a/include/ilang/ilang++.h b/include/ilang/ilang++.h index 09f7d6616..8f172eeb3 100644 --- a/include/ilang/ilang++.h +++ b/include/ilang/ilang++.h @@ -16,6 +16,7 @@ #endif // SMTSWITCH_INTERFACE #include +#include /// \namespace ilang /// Defines the core data structure and APIs for constructing and storing ILA. @@ -745,6 +746,28 @@ class IlaZ3Unroller { }; // class IlaZ3Unroller + +/// \brief The wrapper of Rtl verification target generator +class IlaVerilogRefinemetChecker { + +public: + // ------------------------- CONSTRUCTOR/DESTRUCTOR ----------------------- // + /// Default constructor + IlaVerilogRefinemetChecker( + const Ila& ila, + const std::vector& implementation_include_path, + const std::vector& implementation_srcs, + const std::string& implementation_top_module, + const std::string& refinement_variable_mapping, + const std::string& refinement_conditions, + const std::string& output_path, + ModelCheckerSelection backend, + const RtlVerifyConfig& vtg_config = RtlVerifyConfig() ); + /// Default virtual destructor. + ~IlaVerilogRefinemetChecker() {}; + +}; // class RtlVerifier + #ifdef SMTSWITCH_INTERFACE /// \brief Reset the solver and generate the SMT Term (for smt-switch). diff --git a/include/ilang/rtl_verify.h b/include/ilang/rtl_verify.h new file mode 100644 index 000000000..b1f0c43e9 --- /dev/null +++ b/include/ilang/rtl_verify.h @@ -0,0 +1,251 @@ +/// \file +/// The header for the c++ API. + +#ifndef ILANG_RTL_VERIFY_CONFIG_H__ +#define ILANG_RTL_VERIFY_CONFIG_H__ + +#include +#include +#include +#include + + +/// \namespace ilang +/// Defines the configurations for Verilog refinement checking +namespace ilang { + + + // ----------- Verification Settings -------------- // + /// Type of the backend: + /// Pono, JasperGold + /// YOSYS is for generic btor generation + enum class ModelCheckerSelection { + NONE = 0, + JASPERGOLD = 2, + YOSYS = 128, // 10000000 + // CHC = YOSYS + 8, // 10001000 + // Z3PDR = CHC + 1, // 10001001 + // ELD_CEGAR = CHC + 2, // 10001010 + // GRAIN_SYGUS = CHC + 4, // 10001100 + // ABCPDR = YOSYS + 16, // 10010000 + PONO = YOSYS + 32, // 10100000 + RELCHC = YOSYS + 64 // 11000000 + }; // enum class ModelCheckerSelection + +/// Verilog Target Generation Configuration + typedef struct _vtg_config { + /// Preheader Content : will use in all targets + std::string WrapperPreheader; + /// Set the targets: instructions/invariants/both + enum { INST, INV, BOTH } target_select; + /// If not an empty string, then only check for that instruction + std::string CheckThisInstructionOnly; + /// Ensure the instruction will not be reseted while + /// in the whole execution of checking instruction + /// from reseted --> to forever + bool InstructionNoReset; // true + /// Ensure the design will not be reseted + /// from reseted --> to forever + bool InvariantCheckNoReset; // true + /// Does not insert assertions of variable mapping + /// if an instruction does not update that var + bool OnlyCheckInstUpdatedVars; // true + /// Whether to pass Verilog node name in reference + /// generation + bool VerilogGenPassNodeName; + /// if false : assume (cond |-> reg == value) + /// if true : assume ((START || STARTED) && cond && not_triggered) + /// |-> reg == value + bool EnforcingValueRecorderForOnlyOneCycle; + + /// Configure the behavior of INV target, if false, + /// will not check synthesized invariants by default (unless call + /// generateInvariantVerificationTarget) if true, will check by default + enum class _validate_synthesized_inv { + NOINV, + CANDIDATE, + CONFIRMED, + ALL + } ValidateSynthesizedInvariant; + + // ----------- Options for Pono settings -------------- // + /// Whether to force the instruction check to start from reset state + bool ForceInstCheckReset; + /// For Pono target generator : whether to force NEW/OLD port declaration + enum class PortDeclStyleT { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; + + /// Pono VCD output + std::string PonoVcdOutputName; + /// Binary location of Pono + std::string PonoPath; + /// For Pono backend: do we add (* keep *)? default true, however, it can be + /// buggy, so you can disable it if you want + bool PonoAddKeep; + /// For Pono backend: the default engine (ind by default) + /// other options: like bmc, bmc-sp, ind, interp, mbic3, + /// ic3bits, ic3ia, msat-ic3ia, ic3sa, sygus-pdr + std::string PonoEngine; + /// For Pono backend: what more options to add + std::string PonoOtherOptions; + /// whether to force dot reference check in the generation + /// if you expect to use Pono on the it, yes, you need to + /// use the default setting : NOTIFY_PANIC + /// in some rare cases, you may want to use JasperGold after it + /// in that case, it is okay to just ignore it + enum class PonoDotReferenceNotify_t { + NOTIFY_PANIC = 0, + NOTIFY_WARNING = 1, + NOTIFY_IGNORE = 2 + } PonoDotReferenceNotify; + // The bound of BMC, default 127 + unsigned MaxBound; + /// Only enforce var eq on updated vars, should not be used + bool OnlyAssumeUpdatedVarsEq; // should be false + + // ----------- Options for Yosys SMT-LIB2 Generator -------------- // + /// The path to yosys, if yosys is not in the PATH, default empty + std::string YosysPath; + /// whether to explicitly turn the undriven net to input + /// for smt-backend, the top level undriven net seems always turned into + /// inputs, but the lower level may not + bool YosysUndrivenNetAsInput; + /// Whether to flatten the module hierarchy + bool YosysSmtFlattenHierarchy; + /// Whether to flatten the datatypes + bool YosysSmtFlattenDatatype; + /// when used in property verification, show prove? + bool YosysPropertyCheckShowProof; + /// Whether to word-blast array or use SMT Array + /// By default will word-blast + bool YosysSmtArrayForRegFile; + /// How to encode Verilog state + /// DataSort seems to use PDR engine + enum class YosysStateSortT { + UnintepretedFunc /*not supported*/, + Datatypes, /*by default*/ + BitVec /*optional for property check, not inv-syn*/ + } YosysSmtStateSort; + /// for invariant synthesis do we keep memory abstraction in Verilog + /// you can keep it true, untill the invariant refers to some memory there + bool InvariantSynthesisKeepMemory; + /// for invariant check, do we keep memory abstraction in Verilog + bool InvariantCheckKeepMemory; + /// Whether to assume the old invariants when check for reachability + /// It seems for Z3, setting this to be false is faster (I don't know why) + /// For grain-enhance, this will be (internally) overwritten to be true + bool InvariantSynthesisReachableCheckKeepOldInvariant; + /// Whether to set undriven net in yosys as 0. In general this should not + /// be needed, but for some reason, PONO is unhappy sometimes. + bool YosysSetUndrivenZero; + + // ----------- Options for CHC Solver -------------- // + /// CHC, whether to turn array into individual registers + bool ChcWordBlastArray; + /// CHC, whether to force assumption on the init + bool ChcAssumptionsReset; + /// CHC, whether to force assumption on the next T + bool ChcAssumptionNextState; + /// CHC, whether to force assumption on the end T + bool ChcAssumptionEnd; + + // ----------- Options for Btor Output -------------- // + /// in the format of "xxxx [options] %btorfile% [options]" + /// will replace %btorfile% with the file + std::string BtorGenericCmdline; + /// CHC, whether to turn array into individual registers + bool BtorSingleProperty; + /// CHC, whether to force assumption on the init + bool BtorAddCommentsInOutputs; + + /* TODO: future work: + bool YosysAssumptionOverlyConstrainedCheck; + */ + + // ----------- Options for Z3/Grain/ABC Solver -------------- // + /// The path to Z3, if "z3" is not in the PATH, default empty + std::string Z3Path; + /// The path to Grain, if "grain" is not in the PATH, default empty + std::string GrainPath; + /// Grain Configuration Options + std::vector GrainOptions; + /// FreqHorn style (cocistyple, cnfstyle) + bool GrainHintsUseCnfStyle; + /// The path to ABC, if "abc" is not in the PATH, default empty + std::string AbcPath; + + // ----------- Extended Options for ABC Solver -------------- // + /// ABC option : whether to use gate-level abstraction + bool AbcUseGla; + /// ABC option : gate-level abstraction time limit + unsigned AbcGlaTimeLimit; + /// ABC option : gate-level abstraction frame limit + unsigned AbcGlaFrameLimit; + /// ABC option : whether to use correlation analysis + bool AbcUseCorr; + /// ABC option : whether to pass aiger to ABC + bool AbcUseAiger; + /// ABC option : whether to minimize invariant + bool AbcMinimizeInv; + /// ABC option : the way to handle assumptions + enum class AbcAssumptionStyle_t { + AigMiterExtraOutput = + 0, // Use AIG's extra output to represent, cannot use with GLA + AssumptionRegister = + 1 // Use extra register, may have issues in interpreting the invariant + } AbcAssumptionStyle; + + // ----------- Refinement Sanity Check Options-------------- // + bool SanityCheck_ValueRecorderOverlyConstrained; + + /// The default constructor for default values + _vtg_config() + : target_select(BOTH), CheckThisInstructionOnly(""), + InstructionNoReset(true), InvariantCheckNoReset(false), + OnlyCheckInstUpdatedVars(true), VerilogGenPassNodeName(false), + EnforcingValueRecorderForOnlyOneCycle(true), + ValidateSynthesizedInvariant(_validate_synthesized_inv::ALL), + + // ----------- Options for Pono settings -------------- // + ForceInstCheckReset(false), PortDeclStyle(PortDeclStyleT::AUTO), + PonoVcdOutputName("cex.vcd"), PonoAddKeep(false), PonoEngine("ind"), + PonoOtherOptions(""), + PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), + MaxBound(127), OnlyAssumeUpdatedVarsEq(false), + + // ----------- Options for Pono script -------------- // + // PonoAssumptionOverlyConstrainedCheck(false), + + // ----------- Options for Yosys SMT-LIB2 Generator -------------- // + YosysUndrivenNetAsInput(true), YosysSmtFlattenHierarchy(true), + YosysSmtFlattenDatatype(false), YosysPropertyCheckShowProof(false), + YosysSmtArrayForRegFile(false), + YosysSmtStateSort(YosysStateSortT::Datatypes), + InvariantSynthesisKeepMemory(true), InvariantCheckKeepMemory(true), + InvariantSynthesisReachableCheckKeepOldInvariant(false), + YosysSetUndrivenZero(false), + + // ----------- Options for CHCs -------------- // + ChcWordBlastArray(true), ChcAssumptionsReset(false), + ChcAssumptionNextState(false), ChcAssumptionEnd(false), + + // ----------- Options for Btor Output -------------- // + /// CHC, whether to turn array into individual registers + BtorSingleProperty(true), + /// CHC, whether to force assumption on the init + BtorAddCommentsInOutputs(false), + + // ----------- Options for Z3/Grain/ABC Solver -------------- // + GrainHintsUseCnfStyle(true), + + // ----------- Options for ABC -------------- // + AbcUseGla(false), AbcGlaTimeLimit(500), AbcGlaFrameLimit(200), + AbcUseCorr(false), AbcUseAiger(true), AbcMinimizeInv(false), + AbcAssumptionStyle(AbcAssumptionStyle_t::AigMiterExtraOutput), + + // ----------- Options for Refinement Sanity Checks -------------- // + SanityCheck_ValueRecorderOverlyConstrained(true) {} + } RtlVerifyConfig; + +} // namespace ilang + +#endif // ILANG_RTL_VERIFY_CONFIG_H__ diff --git a/include/ilang/vtarget-out/vtarget_gen.h b/include/ilang/vtarget-out/vtarget_gen.h index e50d3e506..2428fd155 100644 --- a/include/ilang/vtarget-out/vtarget_gen.h +++ b/include/ilang/vtarget-out/vtarget_gen.h @@ -6,6 +6,7 @@ #define ILANG_VTARGET_OUT_VTARGET_GEN_H__ #include +#include #include #include #include @@ -24,255 +25,25 @@ class VlgVerifTgtGenBase { ex_info_t(const std::string& r) : range(r) {} }; - // ----------- Verification Settings -------------- // - /// Type of the backend: - /// Pono, JasperGold, CHC for chc solver, AIGER for abc - // YOSYS is for invariant synthesis use - enum class backend_selector { - NONE = 0, - JASPERGOLD = 2, - YOSYS = 128, // 10000000 - // CHC = YOSYS + 8, // 10001000 - // Z3PDR = CHC + 1, // 10001001 - // ELD_CEGAR = CHC + 2, // 10001010 - // GRAIN_SYGUS = CHC + 4, // 10001100 - // ABCPDR = YOSYS + 16, // 10010000 - PONO = YOSYS + 32, // 10100000 - RELCHC = YOSYS + 64 // 11000000 - }; /// decide if a backend needs Yosys - static bool backend_needs_yosys(backend_selector b) { - return (int(b) & int(backend_selector::YOSYS)) == - int(backend_selector::YOSYS); + static bool backend_needs_yosys(ModelCheckerSelection b) { + return (int(b) & int(ModelCheckerSelection::YOSYS)) == + int(ModelCheckerSelection::YOSYS); } /// Type of invariant synthesis backend /*enum class synthesis_backend_selector { - // Z3 = int(backend_selector::Z3PDR) ^ - int(backend_selector::YOSYS), // 01001 GRAIN = - int(backend_selector::GRAIN_SYGUS) ^ int(backend_selector::YOSYS), // 01100 - ABC = int(backend_selector::ABCPDR) ^ - int(backend_selector::YOSYS), // 10000 ELDERICA = - int(backend_selector::ELD_CEGAR) ^ int(backend_selector::YOSYS), // 01010 - NOSYN = int(backend_selector::YOSYS) // 1000000 } ;*/ + // Z3 = int(ModelCheckerSelection::Z3PDR) ^ + int(ModelCheckerSelection::YOSYS), // 01001 GRAIN = + int(ModelCheckerSelection::GRAIN_SYGUS) ^ int(ModelCheckerSelection::YOSYS), // 01100 + ABC = int(ModelCheckerSelection::ABCPDR) ^ + int(ModelCheckerSelection::YOSYS), // 10000 ELDERICA = + int(ModelCheckerSelection::ELD_CEGAR) ^ int(ModelCheckerSelection::YOSYS), // 01010 + NOSYN = int(ModelCheckerSelection::YOSYS) // 1000000 } ;*/ /// Type of the chc target enum class _chc_target_t { CEX, INVCANDIDATE, GENERAL_PROPERTY }; - /// Verilog Target Generation Configuration - typedef struct _vtg_config { - /// Preheader Content : will use in all targets - std::string WrapperPreheader; - /// Set the targets: instructions/invariants/both - enum { INST, INV, BOTH } target_select; - /// If not an empty string, then only check for that instruction - std::string CheckThisInstructionOnly; - /// Ensure the instruction will not be reseted while - /// in the whole execution of checking instruction - /// from reseted --> to forever - bool InstructionNoReset; // true - /// Ensure the design will not be reseted - /// from reseted --> to forever - bool InvariantCheckNoReset; // true - /// Does not insert assertions of variable mapping - /// if an instruction does not update that var - bool OnlyCheckInstUpdatedVars; // true - /// Whether to pass Verilog node name in reference - /// generation - bool VerilogGenPassNodeName; - /// if false : assume (cond |-> reg == value) - /// if true : assume ((START || STARTED) && cond && not_triggered) - /// |-> reg == value - bool EnforcingValueRecorderForOnlyOneCycle; - - /// Configure the behavior of INV target, if false, - /// will not check synthesized invariants by default (unless call - /// generateInvariantVerificationTarget) if true, will check by default - enum class _validate_synthesized_inv { - NOINV, - CANDIDATE, - CONFIRMED, - ALL - } ValidateSynthesizedInvariant; - - // ----------- Options for Pono settings -------------- // - /// Whether to force the instruction check to start from reset state - bool ForceInstCheckReset; - /// For Pono target generator : whether to force NEW/OLD port declaration - enum class PortDeclStyleT { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; - - /// Pono VCD output - std::string PonoVcdOutputName; - /// Binary location of Pono - std::string PonoPath; - /// For Pono backend: do we add (* keep *)? default true, however, it can be - /// buggy, so you can disable it if you want - bool PonoAddKeep; - /// For Pono backend: the default engine (ind by default) - /// other options: like bmc, bmc-sp, ind, interp, mbic3, - /// ic3bits, ic3ia, msat-ic3ia, ic3sa, sygus-pdr - std::string PonoEngine; - /// For Pono backend: what more options to add - std::string PonoOtherOptions; - /// whether to force dot reference check in the generation - /// if you expect to use Pono on the it, yes, you need to - /// use the default setting : NOTIFY_PANIC - /// in some rare cases, you may want to use JasperGold after it - /// in that case, it is okay to just ignore it - enum class PonoDotReferenceNotify_t { - NOTIFY_PANIC = 0, - NOTIFY_WARNING = 1, - NOTIFY_IGNORE = 2 - } PonoDotReferenceNotify; - // The bound of BMC, default 127 - unsigned MaxBound; - /// Only enforce var eq on updated vars, should not be used - bool OnlyAssumeUpdatedVarsEq; // should be false - - // ----------- Options for Yosys SMT-LIB2 Generator -------------- // - /// The path to yosys, if yosys is not in the PATH, default empty - std::string YosysPath; - /// whether to explicitly turn the undriven net to input - /// for smt-backend, the top level undriven net seems always turned into - /// inputs, but the lower level may not - bool YosysUndrivenNetAsInput; - /// Whether to flatten the module hierarchy - bool YosysSmtFlattenHierarchy; - /// Whether to flatten the datatypes - bool YosysSmtFlattenDatatype; - /// when used in property verification, show prove? - bool YosysPropertyCheckShowProof; - /// Whether to word-blast array or use SMT Array - /// By default will word-blast - bool YosysSmtArrayForRegFile; - /// How to encode Verilog state - /// DataSort seems to use PDR engine - enum class YosysStateSortT { - UnintepretedFunc /*not supported*/, - Datatypes, /*by default*/ - BitVec /*optional for property check, not inv-syn*/ - } YosysSmtStateSort; - /// for invariant synthesis do we keep memory abstraction in Verilog - /// you can keep it true, untill the invariant refers to some memory there - bool InvariantSynthesisKeepMemory; - /// for invariant check, do we keep memory abstraction in Verilog - bool InvariantCheckKeepMemory; - /// Whether to assume the old invariants when check for reachability - /// It seems for Z3, setting this to be false is faster (I don't know why) - /// For grain-enhance, this will be (internally) overwritten to be true - bool InvariantSynthesisReachableCheckKeepOldInvariant; - /// Whether to set undriven net in yosys as 0. In general this should not - /// be needed, but for some reason, PONO is unhappy sometimes. - bool YosysSetUndrivenZero; - - // ----------- Options for CHC Solver -------------- // - /// CHC, whether to turn array into individual registers - bool ChcWordBlastArray; - /// CHC, whether to force assumption on the init - bool ChcAssumptionsReset; - /// CHC, whether to force assumption on the next T - bool ChcAssumptionNextState; - /// CHC, whether to force assumption on the end T - bool ChcAssumptionEnd; - - // ----------- Options for Btor Output -------------- // - /// in the format of "xxxx [options] %btorfile% [options]" - /// will replace %btorfile% with the file - std::string BtorGenericCmdline; - /// CHC, whether to turn array into individual registers - bool BtorSingleProperty; - /// CHC, whether to force assumption on the init - bool BtorAddCommentsInOutputs; - - /* TODO: future work: - bool YosysAssumptionOverlyConstrainedCheck; - */ - - // ----------- Options for Z3/Grain/ABC Solver -------------- // - /// The path to Z3, if "z3" is not in the PATH, default empty - std::string Z3Path; - /// The path to Grain, if "grain" is not in the PATH, default empty - std::string GrainPath; - /// Grain Configuration Options - std::vector GrainOptions; - /// FreqHorn style (cocistyple, cnfstyle) - bool GrainHintsUseCnfStyle; - /// The path to ABC, if "abc" is not in the PATH, default empty - std::string AbcPath; - - // ----------- Extended Options for ABC Solver -------------- // - /// ABC option : whether to use gate-level abstraction - bool AbcUseGla; - /// ABC option : gate-level abstraction time limit - unsigned AbcGlaTimeLimit; - /// ABC option : gate-level abstraction frame limit - unsigned AbcGlaFrameLimit; - /// ABC option : whether to use correlation analysis - bool AbcUseCorr; - /// ABC option : whether to pass aiger to ABC - bool AbcUseAiger; - /// ABC option : whether to minimize invariant - bool AbcMinimizeInv; - /// ABC option : the way to handle assumptions - enum class AbcAssumptionStyle_t { - AigMiterExtraOutput = - 0, // Use AIG's extra output to represent, cannot use with GLA - AssumptionRegister = - 1 // Use extra register, may have issues in interpreting the invariant - } AbcAssumptionStyle; - - // ----------- Extended Options for Grain -------------- // - - // ----------- Refinement Sanity Check Options-------------- // - bool SanityCheck_ValueRecorderOverlyConstrained; - - /// The default constructor for default values - _vtg_config() - : target_select(BOTH), CheckThisInstructionOnly(""), - InstructionNoReset(true), InvariantCheckNoReset(false), - OnlyCheckInstUpdatedVars(true), VerilogGenPassNodeName(false), - EnforcingValueRecorderForOnlyOneCycle(true), - ValidateSynthesizedInvariant(_validate_synthesized_inv::ALL), - - // ----------- Options for Pono settings -------------- // - ForceInstCheckReset(false), PortDeclStyle(PortDeclStyleT::AUTO), - PonoVcdOutputName("cex.vcd"), PonoAddKeep(false), PonoEngine("ind"), - PonoOtherOptions(""), - PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), - MaxBound(127), OnlyAssumeUpdatedVarsEq(false), - - // ----------- Options for Pono script -------------- // - // PonoAssumptionOverlyConstrainedCheck(false), - - // ----------- Options for Yosys SMT-LIB2 Generator -------------- // - YosysUndrivenNetAsInput(true), YosysSmtFlattenHierarchy(true), - YosysSmtFlattenDatatype(false), YosysPropertyCheckShowProof(false), - YosysSmtArrayForRegFile(false), - YosysSmtStateSort(YosysStateSortT::Datatypes), - InvariantSynthesisKeepMemory(true), InvariantCheckKeepMemory(true), - InvariantSynthesisReachableCheckKeepOldInvariant(false), - YosysSetUndrivenZero(false), - - // ----------- Options for CHCs -------------- // - ChcWordBlastArray(true), ChcAssumptionsReset(false), - ChcAssumptionNextState(false), ChcAssumptionEnd(false), - - // ----------- Options for Btor Output -------------- // - /// CHC, whether to turn array into individual registers - BtorSingleProperty(true), - /// CHC, whether to force assumption on the init - BtorAddCommentsInOutputs(false), - - // ----------- Options for Z3/Grain/ABC Solver -------------- // - GrainHintsUseCnfStyle(true), - - // ----------- Options for ABC -------------- // - AbcUseGla(false), AbcGlaTimeLimit(500), AbcGlaFrameLimit(200), - AbcUseCorr(false), AbcUseAiger(true), AbcMinimizeInv(false), - AbcAssumptionStyle(AbcAssumptionStyle_t::AigMiterExtraOutput), - - // ----------- Options for Refinement Sanity Checks -------------- // - SanityCheck_ValueRecorderOverlyConstrained(true) {} - } vtg_config_t; + /// Advanced parameters used for invariant synthesizer /// should not be used by generat @@ -299,7 +70,7 @@ class VlgVerifTgtGenBase { // destructor : do nothing (make it virtual !!!) virtual ~VlgVerifTgtGenBase() {} /// check if a backend selector is valid - static bool isValidVerifBackend(backend_selector vbackend); + static bool isValidVerifBackend(ModelCheckerSelection vbackend); private: // avoid instantiation @@ -307,14 +78,6 @@ class VlgVerifTgtGenBase { }; // class VlgVerifTgtGenBase class VerilogVerificationTargetGenerator { -public: - /// Type of the backend - using backend_selector = VlgVerifTgtGenBase::backend_selector; - /// Type of the synthesis backend - // using synthesis_backend_selector = - // VlgVerifTgtGenBase::synthesis_backend_selector; - /// Type of configuration - using vtg_config_t = VlgVerifTgtGenBase::vtg_config_t; public: // --------------------- CONSTRUCTOR ---------------------------- // @@ -338,8 +101,8 @@ class VerilogVerificationTargetGenerator { const std::string& implementation_top_module, const std::string& refinement_variable_mapping, const std::string& refinement_conditions, const std::string& output_path, - const InstrLvlAbsPtr& ila_ptr, backend_selector backend, - const vtg_config_t& vtg_config = vtg_config_t(), + const InstrLvlAbsPtr& ila_ptr, ModelCheckerSelection backend, + const RtlVerifyConfig& vtg_config = RtlVerifyConfig(), const VerilogGenerator::VlgGenConfig& config = VerilogGenerator::VlgGenConfig()); // --------------------- DECONSTRUCTOR ---------------------------- // diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index d367e470e..520a270b5 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -56,13 +56,6 @@ class VlgSglTgtGen { typedef enum { INVARIANTS, INSTRUCTIONS, INV_SYN_DESIGN_ONLY } target_type_t; /// Per func apply counter typedef std::map func_app_cnt_t; - /// Type of the verification backend - using backend_selector = VlgVerifTgtGenBase::backend_selector; - /// Type of the synthesis backend - // using synthesis_backend_selector = - // VlgVerifTgtGenBase::synthesis_backend_selector; - /// Type of configuration - using vtg_config_t = VlgVerifTgtGenBase::vtg_config_t; /// Type of record of extra info of a signal using ex_info_t = VlgVerifTgtGenBase::ex_info_t; /// Type of advanced parameter @@ -91,7 +84,7 @@ class VlgSglTgtGen { const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector backend, + const RtlVerifyConfig& vtg_config, ModelCheckerSelection backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr); /// Destructor: do nothing , most importantly it is virtual @@ -338,9 +331,9 @@ class VlgSglTgtGen { /// include paths std::vector vlg_include_files_path; /// Store the configuration - vtg_config_t _vtg_config; + RtlVerifyConfig _vtg_config; /// Store the selection of backend - backend_selector _backend; + ModelCheckerSelection _backend; protected: // ----------------------- MEMBERS for storing assumptions/assertions @@ -474,10 +467,6 @@ class VlgSglTgtGen { /// outside class VlgVerifTgtGen : public VlgVerifTgtGenBase { // --------------------- TYPE DEFINITIONS ---------------------------- // - /// tell us which backend to use - using backend_selector = VlgVerifTgtGenBase::backend_selector; - /// Type of configuration - using vtg_config_t = VlgVerifTgtGenBase::vtg_config_t; /// Type of a target using target_type_t = VlgSglTgtGen::target_type_t; /// Type of advanced parameter @@ -501,7 +490,7 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { const std::string& implementation_top_module, const rfmap::VerilogRefinementMap& refinement, const std::string& output_path, const InstrLvlAbsPtr& ila_ptr, - backend_selector backend, const vtg_config_t& vtg_config, + ModelCheckerSelection backend, const RtlVerifyConfig& vtg_config, advanced_parameters_t* adv_ptr = NULL); /// no copy constructor, please @@ -531,11 +520,11 @@ class VlgVerifTgtGen : public VlgVerifTgtGenBase { /// A pointer to create verilog analyzer VerilogInfo* vlg_info_ptr; /// to store the backend - backend_selector _backend; + ModelCheckerSelection _backend; /// to store the verilog configuration VerilogGenerator::VlgGenConfig _cfg; /// to store the configuration - vtg_config_t _vtg_config; + RtlVerifyConfig _vtg_config; /// to store the advanced parameter configurations advanced_parameters_t* _advanced_param_ptr; /// to store the generate script name diff --git a/include/ilang/vtarget-out/vtarget_gen_jasper.h b/include/ilang/vtarget-out/vtarget_gen_jasper.h index 115be6103..bdcb1e48e 100644 --- a/include/ilang/vtarget-out/vtarget_gen_jasper.h +++ b/include/ilang/vtarget-out/vtarget_gen_jasper.h @@ -42,7 +42,7 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& include_dirs, - const vtg_config_t& vtg_config, backend_selector backend, + const RtlVerifyConfig& vtg_config, ModelCheckerSelection backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr); protected: diff --git a/include/ilang/vtarget-out/vtarget_gen_pono.h b/include/ilang/vtarget-out/vtarget_gen_pono.h index 29fe48f75..7f321e707 100644 --- a/include/ilang/vtarget-out/vtarget_gen_pono.h +++ b/include/ilang/vtarget-out/vtarget_gen_pono.h @@ -86,7 +86,7 @@ class VlgSglTgtGen_Pono : public VlgSglTgtGen { const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& include_dirs, - const vtg_config_t& vtg_config, backend_selector backend, + const RtlVerifyConfig& vtg_config, ModelCheckerSelection backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr); protected: diff --git a/src/ilang++.cc b/src/ilang++.cc index 6091c964e..9f7250069 100644 --- a/src/ilang++.cc +++ b/src/ilang++.cc @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef SMTSWITCH_INTERFACE #include @@ -868,4 +869,30 @@ smt::Term ResetAndGetSmtTerm(smt::SmtSolver& solver, const ExprRef& expr, } #endif // SMTSWITCH_INTERFACE +IlaVerilogRefinemetChecker::IlaVerilogRefinemetChecker( + const Ila& ila, + const std::vector& implementation_include_path, + const std::vector& implementation_srcs, + const std::string& implementation_top_module, + const std::string& refinement_variable_mapping, + const std::string& refinement_conditions, + const std::string& output_path, + ModelCheckerSelection backend, + const RtlVerifyConfig& vtg_config ) { + + VerilogVerificationTargetGenerator checker( + implementation_include_path, + implementation_srcs, + implementation_top_module, + refinement_variable_mapping, + refinement_conditions, + output_path, + ila.get(), + backend, + vtg_config + ); + + checker.GenerateTargets(); +} + } // namespace ilang diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 83f35daf5..c9cb8650f 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -301,7 +302,7 @@ VlgSglTgtGen::CreateVarReplacement(const rfmap::RfVar& var, } rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr& in) { - bool replace_dot = _backend != VlgSglTgtGen::backend_selector::JASPERGOLD; + bool replace_dot = _backend != ModelCheckerSelection::JASPERGOLD; std::unordered_map vars; refinement_map.GetVars(in, vars); diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index 50e0fc69a..128bab7cb 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -37,7 +37,7 @@ VlgSglTgtGen::VlgSglTgtGen( const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector backend, + const RtlVerifyConfig& vtg_config, ModelCheckerSelection backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr) : _output_path(output_path), _instr_ptr(instr_ptr), _host(ila_ptr), _vlg_mod_inst_name("RTL"), _ila_mod_inst_name("ILA"), @@ -435,7 +435,7 @@ void VlgSglTgtGen::Export_ila_vlg(const std::string& ila_vlg_name) { if (VlgVerifTgtGenBase::backend_needs_yosys(_backend)) { fn = os_portable_append_dir(_output_path, top_file_name); fout.open(fn, std::ios_base::app); - } else if (_backend == backend_selector::JASPERGOLD) { + } else if (_backend == ModelCheckerSelection::JASPERGOLD) { fn = os_portable_append_dir(_output_path, ila_vlg_name); fout.open(fn); } diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index 6a5b03b86..ea8f8f637 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -183,7 +183,7 @@ void VlgSglTgtGen::add_wire_assign_assumption(const std::string& varname, // populate the RtlExtraWire data structure void VlgSglTgtGen:: ConstructWrapper_translate_property_and_collect_all_rtl_connection_var() { - bool is_jg = _backend == VlgSglTgtGen::backend_selector::JASPERGOLD; + bool is_jg = _backend == ModelCheckerSelection::JASPERGOLD; for (auto& dspt_vn_rfexpr_eq : assign_or_assumptions) { const auto& vn = std::get<1>(dspt_vn_rfexpr_eq); diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index 50bb5c55e..3d5480557 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -51,7 +51,7 @@ void VlgSglTgtGen::ConstructWrapper_reset_setup() { } else if (target_type == target_type_t::INVARIANTS || target_type == target_type_t::INV_SYN_DESIGN_ONLY) { if (_vtg_config.InvariantCheckNoReset) { - if (_backend == backend_selector::JASPERGOLD) { + if (_backend == ModelCheckerSelection::JASPERGOLD) { // no need to any thing } else if (VlgVerifTgtGenBase::backend_needs_yosys(_backend)) { add_a_direct_assumption("rst == 0", "noreset"); diff --git a/src/vtarget-out/single_target_inv_syn_support.cc b/src/vtarget-out/single_target_inv_syn_support.cc index 4330c92d5..ce3c366ee 100644 --- a/src/vtarget-out/single_target_inv_syn_support.cc +++ b/src/vtarget-out/single_target_inv_syn_support.cc @@ -135,14 +135,14 @@ void VlgSglTgtGen:: ConstructWrapper_add_inv_assumption_or_assertion_target_invariant() { ILA_CHECK(target_type == target_type_t::INVARIANTS); if (_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::NOINV && + RtlVerifyConfig::_validate_synthesized_inv::NOINV && !has_rf_invariant) { ILA_CHECK(false) << "No invariant to handle for INVARIANT target, this is a bug!"; } if (_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::ALL) { + RtlVerifyConfig::_validate_synthesized_inv::ALL) { ILA_CHECK(has_confirmed_synthesized_invariant || has_gussed_synthesized_invariant || has_rf_invariant) << "No invariant to handle for INVARIANT target, this is a bug!"; @@ -153,7 +153,7 @@ void VlgSglTgtGen:: add_rf_inv_as_assertion(); } else if (_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::CANDIDATE) { + RtlVerifyConfig::_validate_synthesized_inv::CANDIDATE) { ILA_CHECK(has_gussed_synthesized_invariant) << "No invariant to handle for INVARIANT target, need candidate " "invariant!"; @@ -165,7 +165,7 @@ void VlgSglTgtGen:: add_rf_inv_as_assumption(); } else if (_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::CONFIRMED) { + RtlVerifyConfig::_validate_synthesized_inv::CONFIRMED) { ILA_INFO_IF(has_confirmed_synthesized_invariant) << "Will ignore candidate invariants when checking confirmed " "invariants"; @@ -177,7 +177,7 @@ void VlgSglTgtGen:: // assume rf add_rf_inv_as_assumption(); } else if (_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::NOINV) { + RtlVerifyConfig::_validate_synthesized_inv::NOINV) { // assert rf add_rf_inv_as_assertion(); } diff --git a/src/vtarget-out/vtarget_gen.cc b/src/vtarget-out/vtarget_gen.cc index 2c6e9a645..e81a58af3 100644 --- a/src/vtarget-out/vtarget_gen.cc +++ b/src/vtarget-out/vtarget_gen.cc @@ -9,23 +9,23 @@ namespace ilang { -bool VlgVerifTgtGenBase::isValidVerifBackend(backend_selector vbackend) { - if (vbackend == backend_selector::PONO) +bool VlgVerifTgtGenBase::isValidVerifBackend(ModelCheckerSelection vbackend) { + if (vbackend == ModelCheckerSelection::PONO) return true; - if (vbackend == backend_selector::JASPERGOLD) + if (vbackend == ModelCheckerSelection::JASPERGOLD) return true; /* - if (vbackend == backend_selector::RELCHC) + if (vbackend == ModelCheckerSelection::RELCHC) return true; - if ((vbackend & backend_selector::YOSYS) == backend_selector::YOSYS) { - if (vbackend == backend_selector::ABCPDR) + if ((vbackend & ModelCheckerSelection::YOSYS) == ModelCheckerSelection::YOSYS) { + if (vbackend == ModelCheckerSelection::ABCPDR) return true; - if (vbackend == backend_selector::BTOR_GENERIC) + if (vbackend == ModelCheckerSelection::BTOR_GENERIC) return true; - if ((vbackend & backend_selector::CHC) == backend_selector::CHC) { - if (vbackend == backend_selector::ELD_CEGAR || - vbackend == backend_selector::GRAIN_SYGUS || - vbackend == backend_selector::Z3PDR) + if ((vbackend & ModelCheckerSelection::CHC) == ModelCheckerSelection::CHC) { + if (vbackend == ModelCheckerSelection::ELD_CEGAR || + vbackend == ModelCheckerSelection::GRAIN_SYGUS || + vbackend == ModelCheckerSelection::Z3PDR) return true; } }*/ @@ -38,8 +38,8 @@ VerilogVerificationTargetGenerator::VerilogVerificationTargetGenerator( const std::string& implementation_top_module, const std::string& refinement_variable_mapping, const std::string& refinement_conditions, const std::string& output_path, - const InstrLvlAbsPtr& ila_ptr, backend_selector backend, - const vtg_config_t& vtg_config, + const InstrLvlAbsPtr& ila_ptr, ModelCheckerSelection backend, + const RtlVerifyConfig& vtg_config, const VerilogGenerator::VlgGenConfig& notused) : _generator(new VlgVerifTgtGen( implementation_include_path, implementation_srcs, diff --git a/src/vtarget-out/vtarget_gen_impl.cc b/src/vtarget-out/vtarget_gen_impl.cc index 6211e71d4..fac3c62bb 100644 --- a/src/vtarget-out/vtarget_gen_impl.cc +++ b/src/vtarget-out/vtarget_gen_impl.cc @@ -31,7 +31,7 @@ VlgVerifTgtGen::VlgVerifTgtGen( const std::string& implementation_top_module, const rfmap::VerilogRefinementMap& refinement, const std::string& output_path, const InstrLvlAbsPtr& ila_ptr, - backend_selector backend, const vtg_config_t& vtg_config, + ModelCheckerSelection backend, const RtlVerifyConfig& vtg_config, advanced_parameters_t* adv_ptr) : _vlg_impl_include_path(implementation_include_path), _vlg_impl_srcs(implementation_srcs), @@ -79,32 +79,32 @@ void VlgVerifTgtGen::GenerateTargets(void) { return; } - if (_vtg_config.target_select == vtg_config_t::BOTH || - _vtg_config.target_select == vtg_config_t::INV) { + if (_vtg_config.target_select == RtlVerifyConfig::BOTH || + _vtg_config.target_select == RtlVerifyConfig::INV) { // check if there are really invariants: bool invariantExists = false; if (!_refinement.global_invariants.empty()) invariantExists = true; if ((_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::ALL || + RtlVerifyConfig::_validate_synthesized_inv::ALL || _vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::CONFIRMED) && + RtlVerifyConfig::_validate_synthesized_inv::CONFIRMED) && (_advanced_param_ptr && _advanced_param_ptr->_inv_obj_ptr != NULL && !_advanced_param_ptr->_inv_obj_ptr->GetVlgConstraints().empty())) invariantExists = true; if ((_vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::ALL || + RtlVerifyConfig::_validate_synthesized_inv::ALL || _vtg_config.ValidateSynthesizedInvariant == - vtg_config_t::_validate_synthesized_inv::CANDIDATE) && + RtlVerifyConfig::_validate_synthesized_inv::CANDIDATE) && (_advanced_param_ptr && _advanced_param_ptr->_candidate_inv_ptr != NULL && !_advanced_param_ptr->_candidate_inv_ptr->GetVlgConstraints().empty())) invariantExists = true; auto sub_output_path = os_portable_append_dir(_output_path, "invariants"); - if (_backend == backend_selector::PONO && invariantExists) { + if (_backend == ModelCheckerSelection::PONO && invariantExists) { auto target = VlgSglTgtGen_Pono( sub_output_path, NULL, // invariant @@ -114,7 +114,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { target.ConstructWrapper(); target.ExportAll("wrapper.v", "ila.v", "run.sh", "gen_btor.ys"); target.do_not_instantiate(); // no use, just for coverage - } else if (_backend == backend_selector::JASPERGOLD && invariantExists) { + } else if (_backend == ModelCheckerSelection::JASPERGOLD && invariantExists) { auto target = VlgSglTgtGen_Jasper( sub_output_path, NULL, // invariant @@ -126,7 +126,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { target.do_not_instantiate(); // no use, just for coverage } #if 0 - else if (_backend == backend_selector::RELCHC && invariantExists) { + else if (_backend == ModelCheckerSelection::RELCHC && invariantExists) { // will actually fail : not supported for using relchc for invariant // targets auto target = VlgSglTgtGen_Relchc( @@ -140,8 +140,8 @@ void VlgVerifTgtGen::GenerateTargets(void) { target.ExportAll("wrapper.v", "ila.v", "run.sh", "__design_smt.smt2", "absmem.v"); target.do_not_instantiate(); - } else if ((_backend & backend_selector::YOSYS) == - backend_selector::YOSYS && + } else if ((_backend & ModelCheckerSelection::YOSYS) == + ModelCheckerSelection::YOSYS && invariantExists) { auto target = VlgSglTgtGen_Yosys( sub_output_path, @@ -153,11 +153,11 @@ void VlgVerifTgtGen::GenerateTargets(void) { _chc_target_t::GENERAL_PROPERTY); target.ConstructWrapper(); std::string design_file; - if (_backend == backend_selector::ABCPDR) + if (_backend == ModelCheckerSelection::ABCPDR) design_file = "wrapper.aig"; - else if ((_backend & backend_selector::CHC) == backend_selector::CHC) + else if ((_backend & ModelCheckerSelection::CHC) == ModelCheckerSelection::CHC) design_file = "wrapper.smt2"; - else if (_backend == backend_selector::BTOR_GENERIC) + else if (_backend == ModelCheckerSelection::BTOR_GENERIC) design_file = "wrapper.btor2"; else design_file = "wrapper.unknfmt"; @@ -174,8 +174,8 @@ void VlgVerifTgtGen::GenerateTargets(void) { // == INV) // now let's deal w. instructions in rf_cond - if (_vtg_config.target_select == vtg_config_t::BOTH || - _vtg_config.target_select == vtg_config_t::INST) { + if (_vtg_config.target_select == RtlVerifyConfig::BOTH || + _vtg_config.target_select == RtlVerifyConfig::INST) { for (auto&& instr : _refinement.inst_complete_cond) { std::string iname = instr.first; if (_vtg_config.CheckThisInstructionOnly != "" && @@ -191,7 +191,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { auto sub_output_path = os_portable_append_dir(_output_path, iname); - if (_backend == backend_selector::PONO) { + if (_backend == ModelCheckerSelection::PONO) { auto target = VlgSglTgtGen_Pono( sub_output_path, instr_ptr, // instruction @@ -201,7 +201,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { target.ConstructWrapper(); target.ExportAll("wrapper.v", "ila.v", "run.sh", "gen_btor.ys"); target.do_not_instantiate(); - } else if (_backend == backend_selector::JASPERGOLD) { + } else if (_backend == ModelCheckerSelection::JASPERGOLD) { auto target = VlgSglTgtGen_Jasper( sub_output_path, instr_ptr, // instruction @@ -213,7 +213,7 @@ void VlgVerifTgtGen::GenerateTargets(void) { target.do_not_instantiate(); } #if 0 - else if (_backend == backend_selector::RELCHC) { + else if (_backend == ModelCheckerSelection::RELCHC) { // will actually fail : not supported for using relchc for invariant // targets auto target = VlgSglTgtGen_Relchc( @@ -227,8 +227,8 @@ void VlgVerifTgtGen::GenerateTargets(void) { target.ExportAll("wrapper.v", "ila.v", "run.sh", "__design_smt.smt2", "absmem.v"); target.do_not_instantiate(); - } else if ((_backend & backend_selector::YOSYS) == - backend_selector::YOSYS) { + } else if ((_backend & ModelCheckerSelection::YOSYS) == + ModelCheckerSelection::YOSYS) { // in this case we will have two targets to generate // one is the target with only the design and // and the second one should use the smt file it generates @@ -244,11 +244,11 @@ void VlgVerifTgtGen::GenerateTargets(void) { _chc_target_t::GENERAL_PROPERTY); target.ConstructWrapper(); std::string design_file; - if (_backend == backend_selector::ABCPDR) + if (_backend == ModelCheckerSelection::ABCPDR) design_file = "wrapper.aig"; - else if ((_backend & backend_selector::CHC) == backend_selector::CHC) + else if ((_backend & ModelCheckerSelection::CHC) == ModelCheckerSelection::CHC) design_file = "wrapper.smt2"; - else if (_backend == backend_selector::BTOR_GENERIC) + else if (_backend == ModelCheckerSelection::BTOR_GENERIC) design_file = "wrapper.btor2"; else design_file = "wrapper.unknfmt"; @@ -279,7 +279,7 @@ bool VlgVerifTgtGen::bad_state_return(void) { std::shared_ptr VlgVerifTgtGen::GenerateInvSynTargets(synthesis_backend_selector s_backend) { - ILA_CHECK(_backend == backend_selector::YOSYS) + ILA_CHECK(_backend == ModelCheckerSelection::YOSYS) << "All inv-syn relies on yosys!"; if (vlg_info_ptr) @@ -295,7 +295,7 @@ VlgVerifTgtGen::GenerateInvSynTargets(synthesis_backend_selector s_backend) { // parameter override auto tmp_vtg_config(_vtg_config); tmp_vtg_config.CosaDotReferenceNotify = - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_PANIC; + RtlVerifyConfig::CosaDotReferenceNotify_t::NOTIFY_PANIC; auto target = VlgSglTgtGen_Chc( os_portable_append_dir(_output_path, "inv-syn/"), @@ -318,7 +318,7 @@ VlgVerifTgtGen::GenerateInvSynTargets(synthesis_backend_selector s_backend) { std::shared_ptr VlgVerifTgtGen::GenerateInvSynEnhanceTargets(const InvariantInCnf& cnf) { - ILA_ERROR_IF(_backend != backend_selector::YOSYS) + ILA_ERROR_IF(_backend != ModelCheckerSelection::YOSYS) << "All inv-syn relies on yosys!"; if (vlg_info_ptr) @@ -336,7 +336,7 @@ VlgVerifTgtGen::GenerateInvSynEnhanceTargets(const InvariantInCnf& cnf) { tmp_vtg_config.InvariantSynthesisReachableCheckKeepOldInvariant = true; tmp_vtg_config.YosysSmtFlattenDatatype = true; tmp_vtg_config.CosaDotReferenceNotify = - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_PANIC; + RtlVerifyConfig::CosaDotReferenceNotify_t::NOTIFY_PANIC; // TODO: you may need to change a bit of _advanced_param_ptr's inv // and maybe the assume inv part @@ -363,7 +363,7 @@ VlgVerifTgtGen::GenerateInvSynEnhanceTargets(const InvariantInCnf& cnf) { void VlgVerifTgtGen::GenerateInvSynTargetsAbc(bool useGla, bool useCorr, bool useAiger) { - ILA_ERROR_IF(_backend != backend_selector::YOSYS) + ILA_ERROR_IF(_backend != ModelCheckerSelection::YOSYS) << "All inv-syn relies on yosys!"; if (vlg_info_ptr) @@ -378,7 +378,7 @@ void VlgVerifTgtGen::GenerateInvSynTargetsAbc(bool useGla, bool useCorr, // parameter override auto tmp_vtg_config(_vtg_config); tmp_vtg_config.CosaDotReferenceNotify = - vtg_config_t::CosaDotReferenceNotify_t::NOTIFY_PANIC; + RtlVerifyConfig::CosaDotReferenceNotify_t::NOTIFY_PANIC; auto target = VlgSglTgtGen_Abc( os_portable_append_dir(_output_path, "inv-syn-abc/"), diff --git a/src/vtarget-out/vtarget_gen_jasper.cc b/src/vtarget-out/vtarget_gen_jasper.cc index 847cd6a6a..ab351013d 100644 --- a/src/vtarget-out/vtarget_gen_jasper.cc +++ b/src/vtarget-out/vtarget_gen_jasper.cc @@ -24,7 +24,7 @@ VlgSglTgtGen_Jasper::VlgSglTgtGen_Jasper( const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector backend, + const RtlVerifyConfig& vtg_config, ModelCheckerSelection backend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr) : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, refinement, _vlg_info_ptr, wrapper_name, implementation_srcs, @@ -94,7 +94,23 @@ void VlgSglTgtGen_Jasper::Export_problem(const std::string& extra_name) { fout << "\n\n"; fout << "elaborate -top " << top_mod_name << std::endl; + + // in fact clock configuration should not stay here + // because this controls the top-level reset/clock + // whereas we want internal reset/clock signals to be + // changed + ILA_CHECK( + refinement_map.clock_specification.custom_clock_factor.empty() && + refinement_map.clock_specification.custom_clock_sequence.empty() + ) << "TODO: custom clock sequence not implemented yet"; + fout << "clock clk" << std::endl; + + ILA_CHECK( + refinement_map.reset_specification.custom_reset_sequence.empty() && + refinement_map.reset_specification.initial_state.empty() + ) << "TODO: custom reset sequence not implemented yet"; + fout << "reset rst" << std::endl; unsigned No = 0; diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index 9b593930d..d73135180 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -39,7 +39,7 @@ VlgSglTgtGen_Pono::VlgSglTgtGen_Pono( const std::string& wrapper_name, const std::vector& implementation_srcs, const std::vector& implementation_include_path, - const vtg_config_t& vtg_config, backend_selector vbackend, + const RtlVerifyConfig& vtg_config, ModelCheckerSelection vbackend, const target_type_t& target_tp, advanced_parameters_t* adv_ptr) : VlgSglTgtGen(output_path, instr_ptr, ila_ptr, refinement, _vlg_info_ptr, wrapper_name, implementation_srcs, @@ -232,6 +232,17 @@ void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { "chformal -remove\n" "select *\n"; + + ILA_CHECK( + refinement_map.clock_specification.custom_clock_factor.empty() && + refinement_map.clock_specification.custom_clock_sequence.empty() + ) << "TODO: custom clock sequence not implemented yet"; + + ILA_CHECK( + refinement_map.reset_specification.custom_reset_sequence.empty() && + refinement_map.reset_specification.initial_state.empty() + ) << "TODO: custom reset sequence not implemented yet"; + ys_script_fout << ReplaceAll( ReplaceAll( ReplaceAll( diff --git a/test/t_api.cc b/test/t_api.cc index e2da6facf..23f04d549 100644 --- a/test/t_api.cc +++ b/test/t_api.cc @@ -599,4 +599,32 @@ TEST(TestApi, Portable) { DisableDebug("Portable"); } +TEST(TestApi, RtlVerify) { + // 1. build the ila + auto proc = Ila("proc"); + auto v = proc.NewBvState("v",1); + proc.SetValid(BoolConst(true)); + { // + auto inst = proc.NewInstr("inst"); + inst.SetDecode(BoolConst(true)); + inst.SetUpdate(v, BvConst(1,1)); + } + + // 2. verify + auto dirName = os_portable_join_dir( + {ILANG_TEST_SRC_ROOT, "unit-data", "vpipe", "reset"}); + auto vlg_name = os_portable_join_dir( + {dirName, "verilog", "resetter.v"}); + auto vmap_name = os_portable_join_dir( + {dirName, "rfmap", "vmap-e1.json"}); + auto cond_name = os_portable_join_dir( + {dirName, "rfmap", "cond.json"}); + auto out_name = os_portable_append_dir(dirName, "out3"); + + IlaVerilogRefinemetChecker checker( + proc, {}, {vlg_name}, "resetter", vmap_name, cond_name, out_name, + ModelCheckerSelection::PONO); + +} + } // namespace ilang diff --git a/test/t_inv_syn.cc b/test/t_inv_syn.cc index c54f5b2ee..c6e19cb2b 100644 --- a/test/t_inv_syn.cc +++ b/test/t_inv_syn.cc @@ -50,7 +50,7 @@ class TestVlgVerifInvSyn : public ::testing::Test { TEST_F(TestVlgVerifInvSyn, SimpleCntCegar) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -77,7 +77,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegar) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::Z3, cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -149,7 +149,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegar) { TEST_F(TestVlgVerifInvSyn, SimpleCntCegarWithAssumptions) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = true; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -176,7 +176,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegarWithAssumptions) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::Z3, cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -194,7 +194,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegarWithAssumptions) { TEST_F(TestVlgVerifInvSyn, LoadInvFromBeginning) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -223,7 +223,7 @@ TEST_F(TestVlgVerifInvSyn, LoadInvFromBeginning) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::Z3, cfg); @@ -244,7 +244,7 @@ TEST_F(TestVlgVerifInvSyn, LoadInvFromBeginning) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::Z3, cfg); @@ -265,7 +265,7 @@ TEST_F(TestVlgVerifInvSyn, LoadInvFromBeginning) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::Z3, cfg); @@ -294,7 +294,7 @@ TEST_F(TestVlgVerifInvSyn, LoadInvFromBeginning) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::Z3, cfg); @@ -318,7 +318,7 @@ TEST_F(TestVlgVerifInvSyn, LoadInvFromBeginning) { TEST_F(TestVlgVerifInvSyn, SimpleCntCegarPassed) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -346,7 +346,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegarPassed) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::Z3, cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -360,7 +360,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntCegarPassed) { TEST_F(TestVlgVerifInvSyn, CegarCntAbc) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -390,7 +390,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbc) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::ABC, cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -412,7 +412,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbc) { TEST_F(TestVlgVerifInvSyn, CegarCntAbcBlif) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -444,7 +444,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcBlif) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::ABC, cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -465,7 +465,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcBlif) { TEST_F(TestVlgVerifInvSyn, CegarCntAbcWithAssumption) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = true; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -495,7 +495,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcWithAssumption) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::ABC, cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -511,7 +511,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcWithAssumption) { TEST_F(TestVlgVerifInvSyn, CegarCntAbcInvStart) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -545,7 +545,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcInvStart) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::ABC, cfg); @@ -581,7 +581,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcInvStart) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::ABC, cfg); @@ -606,7 +606,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntAbcInvStart) { TEST_F(TestVlgVerifInvSyn, CegarCntGrain) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = true; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -654,7 +654,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntGrain) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::GRAIN, cfg); @@ -678,7 +678,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntGrain) { TEST_F(TestVlgVerifInvSyn, CegarCntGrainBackVars) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.InvariantSynthesisReachableCheckKeepOldInvariant = true; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -727,7 +727,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntGrainBackVars) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond-noinv.json"})), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::GRAIN, cfg); @@ -753,7 +753,7 @@ TEST_F(TestVlgVerifInvSyn, CegarCntGrainBackVars) { TEST_F(TestVlgVerifInvSyn, CegarPipelineAbcAigEnhance) { auto ila_model = SimplePipe::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; // cfg.InvariantSynthesisReachableCheckKeepOldInvariant = false; cfg.PonoAddKeep = false; cfg.VerificationSettingAvoidIssueStage = true; @@ -786,7 +786,7 @@ TEST_F(TestVlgVerifInvSyn, CegarPipelineAbcAigEnhance) { os_portable_join_dir({dirName, "rfmap", "vmap.json"}), // variable mapping os_portable_join_dir({dirName, "rfmap", "cond-noinv.json"}), outDir, ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::COSA, + ModelCheckerSelection::COSA, VerilogVerificationTargetGenerator::synthesis_backend_selector::ABC, cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -836,7 +836,7 @@ TEST_F(TestVlgVerifInvSyn, CegarPipelineAbcAigEnhance) { TEST_F(TestVlgVerifInvSyn, SimpleCntRelChc) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.PonoAddKeep = false; cfg.YosysPath = "N/A"; cfg.YosysSmtFlattenHierarchy = false; @@ -848,7 +848,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntRelChc) { "opposite", // top_module_name dirName + "rfmap/vmap.json", // variable mapping dirName + "rfmap/cond-relchc.json", dirName + "out/", ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::RELCHC, cfg); + ModelCheckerSelection::RELCHC, cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -858,7 +858,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntRelChc) { TEST_F(TestVlgVerifInvSyn, SimpleCntRelChcNoStart) { auto ila_model = CntTest::BuildModel(); - VerilogVerificationTargetGenerator::vtg_config_t cfg; + RtlVerifyConfig cfg; cfg.PonoAddKeep = false; cfg.YosysPath = "N/A"; cfg.YosysSmtFlattenHierarchy = false; @@ -872,7 +872,7 @@ TEST_F(TestVlgVerifInvSyn, SimpleCntRelChcNoStart) { dirName + "rfmap/vmap.json", // variable mapping dirName + "rfmap/cond-relchc.json", dirName + "out-no-start/", ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::RELCHC, cfg); + ModelCheckerSelection::RELCHC, cfg); EXPECT_FALSE(vg.in_bad_state()); diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index d4d126601..0d918cc76 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -20,7 +20,7 @@ TEST(TestVlgTargetGen, PipeExample) { auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); auto rfDir = os_portable_append_dir(dirName, "rfmap"); - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); + auto vtg_config = RtlVerifyConfig(); VerilogVerificationTargetGenerator vg( {}, // no include @@ -30,180 +30,13 @@ TEST(TestVlgTargetGen, PipeExample) { os_portable_append_dir(rfDir, "cond.json"), // instruction-mapping os_portable_append_dir(dirName, "verify"), // verification dir ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::PONO, // engine + ModelCheckerSelection::PONO, // engine vtg_config); EXPECT_FALSE(vg.in_bad_state()); vg.GenerateTargets(); } -#if 0 -TEST(TestVlgTargetGen, PipeExampleZ3) { - auto ila_model = SimplePipe::BuildModel(); - - auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); - auto rfDir = os_portable_append_dir(dirName, "rfmap"); - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.YosysPath = "N/A"; - vtg_config.Z3Path = "N/A"; - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files - "pipeline_v", // top_module_name - os_portable_append_dir(rfDir, "vmap.json"), // variable mapping - os_portable_append_dir(rfDir, "cond.json"), // instruction-mapping - os_portable_append_dir(dirName, "verify-z3"), // verification dir - ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::Z3PDR, // engine - vtg_config); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} - -TEST(TestVlgTargetGen, PipeExampleGrain) { - auto ila_model = SimplePipe::BuildModel(); - - auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); - auto rfDir = os_portable_append_dir(dirName, "rfmap"); - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.YosysPath = "N/A"; - vtg_config.GrainPath = "N/A"; - vtg_config.YosysSmtFlattenDatatype = true; - vtg_config.GrainHintsUseCnfStyle = true; - vtg_config.GrainOptions = { - "--skip-cnf --skip-const-check --skip-stat-collect --ante-size 1 " - "--conseq-size 1 --cnf cnt-no-group.cnf --use-arith-bvnot " - "--no-const-enum-vars-on m1.v,m1.imp"}; - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files - "pipeline_v", // top_module_name - os_portable_append_dir(rfDir, "vmap.json"), // variable mapping - os_portable_append_dir(rfDir, "cond.json"), // instruction-mapping - os_portable_append_dir(dirName, "verify-grain"), // verification dir - ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector:: - GRAIN_SYGUS, // engine - vtg_config); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} - -TEST(TestVlgTargetGen, PipeExampleGrainDeath) { - auto ila_model = SimplePipe::BuildModel(); - - auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); - auto rfDir = os_portable_append_dir(dirName, "rfmap"); - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.YosysSmtFlattenDatatype = false; - vtg_config.YosysPath = "N/A"; - vtg_config.GrainPath = "N/A"; - vtg_config.Z3Path = "N/A"; - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files - "pipeline_v", // top_module_name - os_portable_append_dir(rfDir, "vmap.json"), // variable mapping - os_portable_append_dir(rfDir, "cond.json"), // instruction-mapping - os_portable_append_dir(dirName, "verify-grain"), // verification dir - ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector:: - GRAIN_SYGUS, // engine - vtg_config); - - EXPECT_FALSE(vg.in_bad_state()); - - EXPECT_DEATH(vg.GenerateTargets(), ".*"); -} - -TEST(TestVlgTargetGen, PipeExampleEldaricaDeath) { - auto ila_model = SimplePipe::BuildModel(); - - auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); - auto rfDir = os_portable_append_dir(dirName, "rfmap"); - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.YosysPath = "N/A"; - vtg_config.GrainPath = "N/A"; - vtg_config.Z3Path = "N/A"; - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files - "pipeline_v", // top_module_name - os_portable_append_dir(rfDir, "vmap.json"), // variable mapping - os_portable_append_dir(rfDir, "cond.json"), // instruction-mapping - os_portable_append_dir(dirName, "verify-grain"), // verification dir - ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::ELD_CEGAR, // engine - vtg_config); - - EXPECT_FALSE(vg.in_bad_state()); - - EXPECT_DEATH(vg.GenerateTargets(), ".*"); -} - -TEST(TestVlgTargetGen, PipeExampleBtor) { - auto ila_model = SimplePipe::BuildModel(); - - auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); - auto rfDir = os_portable_append_dir(dirName, "rfmap"); - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.YosysPath = "N/A"; - vtg_config.GrainPath = "N/A"; - vtg_config.Z3Path = "N/A"; - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files - "pipeline_v", // top_module_name - os_portable_append_dir(rfDir, "vmap.json"), // variable mapping - os_portable_append_dir(rfDir, "cond.json"), // instruction-mapping - os_portable_append_dir(dirName, "verify-btor"), // verification dir - ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector:: - BTOR_GENERIC, // engine - vtg_config); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} - -TEST(TestVlgTargetGen, PipeExampleAbc) { - auto ila_model = SimplePipe::BuildModel(); - - auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); - auto rfDir = os_portable_append_dir(dirName, "rfmap"); - auto vtg_config = VerilogVerificationTargetGenerator::vtg_config_t(); - vtg_config.YosysPath = "N/A"; - vtg_config.GrainPath = "N/A"; - vtg_config.Z3Path = "N/A"; - vtg_config.AbcPath = "N/A"; - - VerilogVerificationTargetGenerator vg( - {}, // no include - {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files - "pipeline_v", // top_module_name - os_portable_append_dir(rfDir, "vmap.json"), // variable mapping - os_portable_append_dir(rfDir, "cond.json"), // instruction-mapping - os_portable_append_dir(dirName, "verify-abc"), // verification dir - ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::ABCPDR, // engine - vtg_config); - - EXPECT_FALSE(vg.in_bad_state()); - - vg.GenerateTargets(); -} - -#endif TEST(TestVlgTargetGen, PipeExampleRfmapPost) { auto ila_model = SimplePipe::BuildModel(); @@ -221,7 +54,7 @@ TEST(TestVlgTargetGen, PipeExampleRfmapPost) { "cond-rfmap-pvholder.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_pvholder"), // verification dir ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::PONO // engine + ModelCheckerSelection::PONO // engine ); EXPECT_FALSE(vg.in_bad_state()); @@ -248,7 +81,7 @@ TEST(TestVlgTargetGen, PipeStallRfmapShortNoValueHolder) { os_portable_append_dir( dirName, "verify_stall_short_nopvholder"), // verification dir ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::PONO // engine + ModelCheckerSelection::PONO // engine ); EXPECT_FALSE(vg.in_bad_state()); @@ -275,7 +108,7 @@ TEST(TestVlgTargetGen, PipeStallRfmapShort) { "cond-rfmap-pvholder-stall-short.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_stall_short"), // verification dir ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::PONO // engine + ModelCheckerSelection::PONO // engine ); EXPECT_FALSE(vg.in_bad_state()); @@ -301,7 +134,7 @@ TEST(TestVlgTargetGen, PipeStallRfmap) { "cond-rfmap-pvholder-stall.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_stall"), // verification dir ila_model.get(), // ILA model - VerilogVerificationTargetGenerator::backend_selector::PONO // engine + ModelCheckerSelection::PONO // engine ); EXPECT_FALSE(vg.in_bad_state()); @@ -325,7 +158,7 @@ TEST(TestVlgTargetGen, PipeExampleJasperGold) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond.json"})), os_portable_append_dir(dirName, "verify_jg/"), ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::JASPERGOLD); + ModelCheckerSelection::JASPERGOLD); EXPECT_FALSE(vg.in_bad_state()); @@ -345,7 +178,7 @@ TEST(TestVlgTargetGen, PipeExampleNotEqu) { P({"rfmap", "vmap.json"})), // variable mapping os_portable_append_dir(dirName, P({"rfmap", "cond.json"})), os_portable_append_dir(dirName, "disprove/"), ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); + ModelCheckerSelection::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -367,7 +200,7 @@ TEST(TestVlgTargetGen, Memory) { os_portable_append_dir(dirName, P({"cond.json"})), dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); + ModelCheckerSelection::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -378,8 +211,7 @@ TEST(TestVlgTargetGen, MemoryInternal) { // test the expansion of memory auto ila_model = MemorySwap::BuildSimpleSwapModel(); - VerilogVerificationTargetGenerator::vtg_config_t - vtg_cfg; // default configuration + RtlVerifyConfig vtg_cfg; // default configuration VerilogGeneratorBase::VlgGenConfig vlg_cfg; vlg_cfg.extMem = false; auto dirName = @@ -392,7 +224,7 @@ TEST(TestVlgTargetGen, MemoryInternal) { // test the expansion of memory os_portable_append_dir(dirName, "cond-expand.json"), dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg, + ModelCheckerSelection::PONO, vtg_cfg, vlg_cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -414,7 +246,7 @@ TEST(TestVlgTargetGen, MemoryInternalExternal) { os_portable_append_dir(dirName, "cond-rfarray.json"), dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); + ModelCheckerSelection::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -432,7 +264,7 @@ TEST(TestVlgTargetGen, MemoryInternalExternalEntry6) { DebugLog::Enable("VTG.AddAssert"); DebugLog::Enable("VTG.AddAssume"); - VlgVerifTgtGenBase::vtg_config_t vtg_cfg; + RtlVerifyConfig vtg_cfg; vtg_cfg.PonoAddKeep = false; auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; @@ -444,7 +276,7 @@ TEST(TestVlgTargetGen, MemoryInternalExternalEntry6) { dirName + "cond-rfarray.json", // cond path dirName + "rfarray_rf6/", // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO, vtg_cfg); + ModelCheckerSelection::PONO, vtg_cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -463,7 +295,7 @@ TEST(TestVlgTargetGen, MemoryRead) { dirName + "cond-rd.json", // cond path dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); + ModelCheckerSelection::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -471,7 +303,7 @@ TEST(TestVlgTargetGen, MemoryRead) { } TEST(TestVlgTargetGen, MemoryReadAbsReadJasperGold) { - VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; + RtlVerifyConfig vtg_cfg; auto ila_model = MemorySwap::BuildRdModel(); @@ -484,7 +316,7 @@ TEST(TestVlgTargetGen, MemoryReadAbsReadJasperGold) { dirName + "cond-rd.json", // cond path dirName + "rdabs_jg/", // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::JASPERGOLD, + ModelCheckerSelection::JASPERGOLD, vtg_cfg); EXPECT_FALSE(vg.in_bad_state()); @@ -504,7 +336,7 @@ TEST(TestVlgTargetGen, UndetValue) { dirName + "cond-val.json", // cond path dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); + ModelCheckerSelection::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -523,7 +355,7 @@ TEST(TestVlgTargetGen, UndetFunc) { dirName + "cond-func.json", // cond path dirName, // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); + ModelCheckerSelection::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -546,7 +378,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path os_portable_append_dir(dirName, "out"), // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); + ModelCheckerSelection::PONO); EXPECT_FALSE(vg.in_bad_state()); @@ -567,7 +399,7 @@ TEST(TestVlgTargetGen, ResetAnnotation) { os_portable_join_dir({dirName, "rfmap", "cond.json"}), // cond path os_portable_append_dir(dirName, "out2"), // output path ila_model.get(), - VerilogVerificationTargetGenerator::backend_selector::PONO); + ModelCheckerSelection::PONO); EXPECT_FALSE(vg.in_bad_state()); diff --git a/test/unit-data/vpipe/reset/out3/.gitignore b/test/unit-data/vpipe/reset/out3/.gitignore new file mode 100644 index 000000000..72e8ffc0d --- /dev/null +++ b/test/unit-data/vpipe/reset/out3/.gitignore @@ -0,0 +1 @@ +* From dad992211734caa34a2d0fa8cbf4a530017ac73c Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 15 Oct 2021 15:33:56 +0800 Subject: [PATCH 42/78] update vexpparser ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 951e3c34e..dd94bf95b 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 951e3c34ee07ebe1a0a77a8e1ae88b73a598dfbb +Subproject commit dd94bf95b72ee0a0506afde4a36a52ae437dd349 From 9b9cb4fcc080d62b6c15c7364b7b250e6eb90e4c Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 15 Oct 2021 15:38:30 +0800 Subject: [PATCH 43/78] adjust path --- include/ilang/rfmap-in/verilog_rfmap.h | 2 +- src/rfmap-in/verilog_rfmap.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index cfb025ae5..433f498d9 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include namespace ilang { namespace rfmap { diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index d343fa7ef..fdc889314 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -8,7 +8,7 @@ #include -#include "interpreter.h" +#include "vexpparser/interpreter.h" #include "nlohmann/json.hpp" namespace ilang { From 74fca2f95929449a605ae3214e6715aafa56c4fa Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 15 Oct 2021 15:51:19 +0800 Subject: [PATCH 44/78] address lgtm --- include/ilang/rfmap-in/rfvar_type.h | 2 ++ src/rfmap-in/rfexpr_to_smt.cc | 1 + 2 files changed, 3 insertions(+) diff --git a/include/ilang/rfmap-in/rfvar_type.h b/include/ilang/rfmap-in/rfvar_type.h index cd5d9e66a..20e069550 100644 --- a/include/ilang/rfmap-in/rfvar_type.h +++ b/include/ilang/rfmap-in/rfvar_type.h @@ -62,6 +62,8 @@ class RfVarTypeOrig { RfVarTypeOrig(const RfVarTypeOrig& r) : var_ref_type(r.var_ref_type), type(r.type) {} + RfVarTypeOrig& operator=(const RfVarTypeOrig&) = default; + }; // class RfVarType } // namespace rfmap diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc index ff3b9e840..5a04ce4d2 100644 --- a/src/rfmap-in/rfexpr_to_smt.cc +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -106,6 +106,7 @@ static SmtType common_type(RfMapVarType tp1, RfMapVarType tp2) { return SmtType(tp2, false); } ILA_CHECK(false) << "unable to determine common type"; + return SmtType(); // should not be reachable } static std::string extend_width(const std::string& in, unsigned inw, From 322ebd36371409c0acc44b4e5c2d7ea55801d545 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 15 Oct 2021 17:31:04 +0800 Subject: [PATCH 45/78] libfl-dev --- appveyor.yml | 2 +- azure-pipelines.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index d189fb8bf..ace79576d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ configuration: install: - sudo apt update --yes -- sudo apt install --yes z3 libz3-dev bison flex gcc g++ +- sudo apt install --yes z3 libz3-dev bison libfl-dev flex gcc g++ build_script: - cd $APPVEYOR_BUILD_FOLDER diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 97c86439b..e073d459b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -85,6 +85,7 @@ jobs: sudo apt-get install flex sudo apt-get install z3 sudo apt-get install libz3-dev + sudo apt-get install libfl-dev displayName: 'package' - script: | mkdir -p build From e477ee9186207b525cab4a4cf504006599e913af Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 15 Oct 2021 17:37:00 +0800 Subject: [PATCH 46/78] ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index dd94bf95b..0f07b1c61 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit dd94bf95b72ee0a0506afde4a36a52ae437dd349 +Subproject commit 0f07b1c6187eccc3dc89d8296f1b045995162475 From 236d250c6c63e50f6ed840665d552a93320f68a2 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 17 Oct 2021 11:26:55 +0800 Subject: [PATCH 47/78] vexpparser on windows --- azure-pipelines.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 02a6a7bad..af087dfec 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -142,6 +142,15 @@ jobs: cmake --build . --target install displayName: 'vlog-parser' + - script: | + cd extern + cd vexpparser + md build + cd build + cmake .. + cmake --build . --target install + displayName: 'vexpparser' + - script: | md build cd build From 29206934f4d50a22b3c1b7ee73bd8a4f65a51e96 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 17 Oct 2021 12:40:59 +0800 Subject: [PATCH 48/78] fix cmake --- cmake/config.cmake.in | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/config.cmake.in b/cmake/config.cmake.in index 5a30fc266..12b2e5a56 100644 --- a/cmake/config.cmake.in +++ b/cmake/config.cmake.in @@ -6,6 +6,7 @@ find_dependency(glog REQUIRED) find_dependency(nlohmann_json REQUIRED) find_dependency(verilogparser REQUIRED) find_dependency(vcdparser REQUIRED) +find_dependency(vexpparser REQUIRED) find_dependency(smtparser REQUIRED) find_dependency(fmt REQUIRED) find_dependency(Z3 REQUIRED) From 8dc3c8a0ae76e489e8f1501a0113cf270521cafd Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 17 Oct 2021 12:42:41 +0800 Subject: [PATCH 49/78] add azure ppl include for vexpp in msvc --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index af087dfec..940d9801e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -147,7 +147,7 @@ jobs: cd vexpparser md build cd build - cmake .. + cmake .. -DCMAKE_CXX_FLAGS=/I\ %ProgramData%\\chocolatey\\lib\\winflexbison3\\tools cmake --build . --target install displayName: 'vexpparser' From 6a1561840945dcd7d22740928c8f66dd5aa85b1a Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 17 Oct 2021 15:44:33 +0800 Subject: [PATCH 50/78] update vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 0f07b1c61..cc7c2524b 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 0f07b1c6187eccc3dc89d8296f1b045995162475 +Subproject commit cc7c2524bdf6edd91deaddbd2fa9e8abcbf08427 From 172690f18139a172943ff8fe82ee8902b4613211 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 17 Oct 2021 19:00:21 +0800 Subject: [PATCH 51/78] new test --- test/unit-data/vpipe/verify_pvholder_reset/.placeholder | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/unit-data/vpipe/verify_pvholder_reset/.placeholder diff --git a/test/unit-data/vpipe/verify_pvholder_reset/.placeholder b/test/unit-data/vpipe/verify_pvholder_reset/.placeholder new file mode 100644 index 000000000..e69de29bb From 3bf933dee6c2f7166ebfcaa75b43238e4eed3f48 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 17 Oct 2021 19:06:42 +0800 Subject: [PATCH 52/78] add test --- test/unit-data/vpipe/disprove-reset/.placeholder | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/unit-data/vpipe/disprove-reset/.placeholder diff --git a/test/unit-data/vpipe/disprove-reset/.placeholder b/test/unit-data/vpipe/disprove-reset/.placeholder new file mode 100644 index 000000000..e69de29bb From e7736b5ad12bcd9193bdfbc98633b5d30132251b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 20 Oct 2021 12:18:34 +0800 Subject: [PATCH 53/78] add more test --- include/ilang/rtl_verify.h | 23 +- include/ilang/vtarget-out/vtarget_gen_impl.h | 13 +- .../ilang/vtarget-out/vtarget_gen_jasper.h | 6 + include/ilang/vtarget-out/vtarget_gen_pono.h | 16 +- src/rfmap-in/rfmap_typecheck.cc | 4 +- src/rfmap-in/verilog_rfmap.cc | 62 +++- src/vtarget-out/single_target.cc | 2 +- src/vtarget-out/single_target_as.cc | 50 ++- src/vtarget-out/single_target_cond.cc | 12 +- src/vtarget-out/single_target_connect.cc | 1 - src/vtarget-out/single_target_misc.cc | 30 +- src/vtarget-out/vtarget_gen_jasper.cc | 11 + src/vtarget-out/vtarget_gen_pono.cc | 334 ++++++++++++++---- test/t_vtarget_gen.cc | 98 ++++- test/unit-data/vpipe/.gitignore | 2 + test/unit-data/vpipe/autoRunAll.py | 83 +++++ .../vpipe/rfmap/vmap-rfmap-pvholder.json | 5 + test/unit-data/vpipe/simple_pipe.v | 9 +- test/unit-data/vpipe/simple_pipe_wrong.v | 9 +- 19 files changed, 624 insertions(+), 146 deletions(-) create mode 100755 test/unit-data/vpipe/autoRunAll.py diff --git a/include/ilang/rtl_verify.h b/include/ilang/rtl_verify.h index b1f0c43e9..daed69cad 100644 --- a/include/ilang/rtl_verify.h +++ b/include/ilang/rtl_verify.h @@ -58,6 +58,7 @@ namespace ilang { /// |-> reg == value bool EnforcingValueRecorderForOnlyOneCycle; + /// Configure the behavior of INV target, if false, /// will not check synthesized invariants by default (unless call /// generateInvariantVerificationTarget) if true, will check by default @@ -71,6 +72,9 @@ namespace ilang { // ----------- Options for Pono settings -------------- // /// Whether to force the instruction check to start from reset state bool ForceInstCheckReset; + /// If true, will generate a separate check that cover the + /// the commit condition + bool CheckInstrCommitSatisfiable; /// For Pono target generator : whether to force NEW/OLD port declaration enum class PortDeclStyleT { AUTO = 0, NEW = 1, OLD = 2 } PortDeclStyle; @@ -97,6 +101,8 @@ namespace ilang { NOTIFY_WARNING = 1, NOTIFY_IGNORE = 2 } PonoDotReferenceNotify; + /// whether to generator a script to be used with JG as well + bool PonoGenJgScript; // The bound of BMC, default 127 unsigned MaxBound; /// Only enforce var eq on updated vars, should not be used @@ -113,8 +119,6 @@ namespace ilang { bool YosysSmtFlattenHierarchy; /// Whether to flatten the datatypes bool YosysSmtFlattenDatatype; - /// when used in property verification, show prove? - bool YosysPropertyCheckShowProof; /// Whether to word-blast array or use SMT Array /// By default will word-blast bool YosysSmtArrayForRegFile; @@ -195,7 +199,10 @@ namespace ilang { } AbcAssumptionStyle; // ----------- Refinement Sanity Check Options-------------- // + /// if true: will check if the value recorder is triggered multiple times bool SanityCheck_ValueRecorderOverlyConstrained; + /// if true: will check if the value recorder is not triggered before commit + bool SanityCheck_ValueRecorderTriggeredBeforeCommit; /// The default constructor for default values _vtg_config() @@ -206,10 +213,13 @@ namespace ilang { ValidateSynthesizedInvariant(_validate_synthesized_inv::ALL), // ----------- Options for Pono settings -------------- // - ForceInstCheckReset(false), PortDeclStyle(PortDeclStyleT::AUTO), + ForceInstCheckReset(false), + CheckInstrCommitSatisfiable(false), + PortDeclStyle(PortDeclStyleT::AUTO), PonoVcdOutputName("cex.vcd"), PonoAddKeep(false), PonoEngine("ind"), PonoOtherOptions(""), PonoDotReferenceNotify(PonoDotReferenceNotify_t::NOTIFY_PANIC), + PonoGenJgScript(false), MaxBound(127), OnlyAssumeUpdatedVarsEq(false), // ----------- Options for Pono script -------------- // @@ -217,8 +227,8 @@ namespace ilang { // ----------- Options for Yosys SMT-LIB2 Generator -------------- // YosysUndrivenNetAsInput(true), YosysSmtFlattenHierarchy(true), - YosysSmtFlattenDatatype(false), YosysPropertyCheckShowProof(false), - YosysSmtArrayForRegFile(false), + YosysSmtFlattenDatatype(false), + YosysSmtArrayForRegFile(true), YosysSmtStateSort(YosysStateSortT::Datatypes), InvariantSynthesisKeepMemory(true), InvariantCheckKeepMemory(true), InvariantSynthesisReachableCheckKeepOldInvariant(false), @@ -243,7 +253,8 @@ namespace ilang { AbcAssumptionStyle(AbcAssumptionStyle_t::AigMiterExtraOutput), // ----------- Options for Refinement Sanity Checks -------------- // - SanityCheck_ValueRecorderOverlyConstrained(true) {} + SanityCheck_ValueRecorderOverlyConstrained(true), + SanityCheck_ValueRecorderTriggeredBeforeCommit(true) {} } RtlVerifyConfig; } // namespace ilang diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 520a270b5..3ca15767b 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -342,10 +342,14 @@ class VlgSglTgtGen { /// consumed by /// ConstructWrapper_translate_property_and_collect_all_rtl_connection_var std::map> all_assumptions; - /// assumptions : written by add_an_assertion, + /// assertions : written by add_an_assertion, /// consumed by /// ConstructWrapper_translate_property_and_collect_all_rtl_connection_var std::map> all_assertions; + /// assumptions : written by add_a_cover, + /// consumed by + /// ConstructWrapper_translate_property_and_collect_all_rtl_connection_var + std::map> all_covers; /// consumed by /// ConstructWrapper_translate_property_and_collect_all_rtl_connection_var std::map> all_sanity_assertions; @@ -394,6 +398,9 @@ class VlgSglTgtGen { /// Add a sanity assertion virtual void add_a_direct_sanity_assertion(const std::string& aspt, const std::string& dspt) = 0; +/// Add a sanity assertion + virtual void add_a_direct_cover_check(const std::string& cvr, + const std::string& dspt) = 0; /// Add SMT-lib2 assumption virtual void add_a_direct_smt_assumption(const std::string& arg, @@ -414,6 +421,10 @@ class VlgSglTgtGen { virtual void add_an_assertion(const rfmap::RfExpr& asst, const std::string& dspt); + /// Add a cover -- simply put in record + virtual void add_a_cover(const rfmap::RfExpr& asst, + const std::string& dspt); + /// Add an assertion for sanity checking -- simply put in record void add_a_santiy_assertion(const rfmap::RfExpr& aspt, const std::string& dspt); diff --git a/include/ilang/vtarget-out/vtarget_gen_jasper.h b/include/ilang/vtarget-out/vtarget_gen_jasper.h index bdcb1e48e..0952cdc4a 100644 --- a/include/ilang/vtarget-out/vtarget_gen_jasper.h +++ b/include/ilang/vtarget-out/vtarget_gen_jasper.h @@ -51,6 +51,8 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { std::vector> assumptions; /// vector of pairs of std::vector> assertions; + /// vector of pairs of + std::vector> covers; /// vector of clock signals that need to be taken care of /// Name of the problem file @@ -74,6 +76,10 @@ class VlgSglTgtGen_Jasper : public VlgSglTgtGen { /// Add a direct assertion virtual void add_a_direct_assertion(const std::string& asst, const std::string& dspt) override; + + /// Add a direct cover check + virtual void add_a_direct_cover_check(const std::string& cvr, + const std::string& dspt) override; /// Add a direct assertion virtual void add_a_direct_sanity_assertion(const std::string& asst, const std::string& dspt) override { diff --git a/include/ilang/vtarget-out/vtarget_gen_pono.h b/include/ilang/vtarget-out/vtarget_gen_pono.h index 7f321e707..65221c4cd 100644 --- a/include/ilang/vtarget-out/vtarget_gen_pono.h +++ b/include/ilang/vtarget-out/vtarget_gen_pono.h @@ -42,6 +42,8 @@ class Pono_problem { problemset_t assertions; /// problems are splitted into items problemset_t sanity_assertions; + /// problems are splitted into items + problemset_t cover_checks; /// SMT-LIB2 assumptions prop_t smt_assumptions; @@ -94,6 +96,8 @@ class VlgSglTgtGen_Pono : public VlgSglTgtGen { Pono_problem _problems; /// Pono problem file name std::string ys_script_name; + /// all cover assert property names + std::vector all_cover_assert_property_names; protected: /// Add a direct assumption @@ -102,9 +106,12 @@ class VlgSglTgtGen_Pono : public VlgSglTgtGen { /// Add a direct assertion virtual void add_a_direct_assertion(const std::string& asst, const std::string& dspt) override; - /// Add a direct assertion + /// Add a direct sanity assertion virtual void add_a_direct_sanity_assertion(const std::string& asst, const std::string& dspt) override; + /// Add a direct cover check + virtual void add_a_direct_cover_check(const std::string& asst, + const std::string& dspt) override; /// Add SMT-lib2 assumption virtual void add_a_direct_smt_assumption(const std::string& arg, @@ -119,6 +126,13 @@ class VlgSglTgtGen_Pono : public VlgSglTgtGen { /// Pre export work : nothing for pono void virtual PreExportProcess() override; + + // A helper function to generate Yosys script + void GenYosysScript( + const std::string& ys_script_name_path, + const std::string& property_selection_cmd, + const std::string& generated_btor_name ); + /// export the script to run the verification virtual void Export_script(const std::string& script_name) override; /// export extra things (problem) diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 1f57ed289..c0a9a9e42 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -263,7 +263,8 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr( TraverseRfExpr(a.second, func); for (auto& r : ptracker.second.rules) { TraverseRfExpr(r.enter_rule, func); - TraverseRfExpr(r.exit_rule, func); + if(r.exit_rule) + TraverseRfExpr(r.exit_rule, func); for (auto& act : r.enter_action) TraverseRfExpr(act.RHS, func); for (auto& act : r.exit_action) @@ -573,6 +574,7 @@ void RfExprAstUtility::RfMapNoNullNode(const RfExpr& in) { void RfExprAstUtility::TraverseRfExpr(RfExpr& inout, std::function func) { + ILA_NOT_NULL(inout); // DFS -- Note: we need to call func on the parent's child // and make sure it runs the first std::vector> parent_stack; diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index fdc889314..6b1f439ef 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -447,21 +447,49 @@ std::string JsonRfmapParsePhaseTracker(PhaseTracker& tracker, auto* enter = GetJsonSection(stage, {"enter"}); auto* exit = GetJsonSection(stage, {"exit"}); auto* stage_name = GetJsonSection(stage, {"name"}); - ENSURE(enter && exit, - "`rules` object must contain `enter` and `exit` events"); - ENSURE(enter->is_object(), - "`enter` should contain `event` and (optional) `action`"); - ENSURE(exit->is_object(), - "`exit` should contain `event` and (optional) `action`"); - auto* enter_event = GetJsonSection(*enter, {"event"}); - auto* exit_event = GetJsonSection(*exit, {"event"}); - auto* enter_action = GetJsonSection(*enter, {"action"}); - auto* exit_action = GetJsonSection(*exit, {"action"}); + ENSURE(enter || exit, + "`rules` object must contain `enter` or `exit` events"); + if(enter) { + ENSURE(enter->is_object() || enter->is_string(), + "`enter` should contain `event` and (optional) `action`"); + } + if(exit) { + ENSURE(exit->is_object() || exit->is_string(), + "`exit` should contain `event` and (optional) `action`"); + } + + nlohmann::json* enter_event = NULL; + nlohmann::json* enter_action = NULL; + nlohmann::json* exit_event = NULL; + nlohmann::json* exit_action = NULL; + + if (enter) { + if(enter->is_object()) { + enter_event = GetJsonSection(*enter, {"event"}); + enter_action = GetJsonSection(*enter, {"action"}); + } else { // is string + enter_event = enter; + } + } + if (exit) { + if(exit->is_object()) { + exit_event = GetJsonSection(*exit, {"event"}); + exit_action = GetJsonSection(*exit, {"action"}); + } else + exit_event = exit; + } + + ERRIF( enter_event == NULL , "the current stage has no `entering` event, please check!" ); + ERRIF( (enter_event == NULL && enter_action != NULL), "if you specify `enter->action`, you must provide `enter->event`." ); + ERRIF( (exit_event == NULL && exit_action != NULL), "if you specify `exit->action`, you must provide `exit->event`." ); + ENSURE(enter_event, "`enter` should contain `event` and (optional) `action`"); - ENSURE(exit_event, "`exit` should contain `event` and (optional) `action`"); ENSURE(enter_event->is_string(), "`enter` -> `event` should be a string"); - ENSURE(exit_event->is_string(), "`exit` -> `event` should be a string"); + if(exit) { + ENSURE(exit_event, "`exit` should contain `event` and (optional) `action`"); + ENSURE(exit_event->is_string(), "`exit` -> `event` should be a string"); + } tracker.rules.push_back(PhaseTracker::Rule()); auto& ws = tracker.rules.back(); @@ -471,9 +499,12 @@ std::string JsonRfmapParsePhaseTracker(PhaseTracker& tracker, } else { ws.stage_name = tracker_name + "_stage" + std::to_string(sidx++); } + ws.enter_rule = ParseRfMapExprJson(*enter_event); - ws.exit_rule = ParseRfMapExprJson(*exit_event); - + if(exit_event) { + ws.exit_rule = ParseRfMapExprJson(*exit_event); + } + if (enter_action) { ENSURE(enter_action->is_string(), "`action` should be a string"); auto action_str = enter_action->get(); @@ -912,7 +943,8 @@ VerilogRefinementMap::VerilogRefinementMap( ENSURE(template_field->is_string(), "`template` field should be string"); auto template_name = template_field->get(); - if (SectionNameRelaxedMatch(template_name, "phase tracker")) { + if (SectionNameRelaxedMatch(template_name, "phase tracker") || + SectionNameRelaxedMatch(template_name, "stage tracker") ) { phase_tracker.emplace(name, PhaseTracker()); std::string errmsg = JsonRfmapParsePhaseTracker( phase_tracker.at(name), monitor, name); diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index 128bab7cb..3c5b0ffe8 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -59,7 +59,7 @@ VlgSglTgtGen::VlgSglTgtGen( // function true, // w. start signal vtg_config.VerilogGenPassNodeName, // pass node name - false, // no rand init + true, // has rand init false, // no expand memory false // no collecte ITE unknown )), diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index ea8f8f637..643ec8e73 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -94,11 +94,20 @@ void VlgSglTgtGen::add_an_assertion(const rfmap::RfExpr& asst, all_assertions[dspt].push_back(asst); } +void VlgSglTgtGen::add_a_cover(const rfmap::RfExpr& asst, + const std::string& dspt) { + rfmap::RfExprAstUtility::RfMapNoNullNode(asst); + all_covers[dspt].push_back(asst); +} + void VlgSglTgtGen::add_a_santiy_assertion(const rfmap::RfExpr& asst, const std::string& dspt) { - if (dspt == "post_value_holder" && + if (dspt == "post_value_holder_overly_constrained" && !_vtg_config.SanityCheck_ValueRecorderOverlyConstrained) return; + if (dspt == "post_value_holder_triggered" && + !_vtg_config.SanityCheck_ValueRecorderTriggeredBeforeCommit) + return; rfmap::RfExprAstUtility::RfMapNoNullNode(asst); all_sanity_assertions[dspt].push_back(asst); @@ -214,6 +223,13 @@ void VlgSglTgtGen:: } } + for (auto& dspt_cvrs : all_covers) { + for (auto& cvrs : dspt_cvrs.second) { + ILA_DLOG("VTG.ReplAssert") << cvrs->to_verilog(); + cvrs = ReplExpr(cvrs); + } + } + if (is_jg) { for (auto& dspt_aspt : all_assumptions) { for (auto& aspt : dspt_aspt.second) @@ -227,6 +243,11 @@ void VlgSglTgtGen:: for (auto& asst : dspt_asst.second) add_a_direct_sanity_assertion(asst->to_verilog(), dspt_asst.first); } + for (auto& dspt_cvrs : all_covers) { + for (auto& cvr : dspt_cvrs.second) + add_a_direct_cover_check(cvr->to_verilog(), dspt_cvrs.first); + } + for (auto& dspt_vn_rfexpr_eq : assign_or_assumptions) { const auto& vn = std::get<1>(dspt_vn_rfexpr_eq); @@ -235,7 +256,7 @@ void VlgSglTgtGen:: vlg_wrapper.add_assign_stmt(vn, eq->child(1)->to_verilog()); } return; - } + } // end of is_jg (will not continue if using jg) for (const auto& repl : refinement_map.GetVarReplacement()) { ILA_CHECK(StrStartsWith(repl.second.get_orig_name(), "RTL.") == @@ -267,6 +288,7 @@ void VlgSglTgtGen:: for (auto& dspt_aspt : all_assumptions) { for (auto& aspt : dspt_aspt.second) { find_and_replace_array_const(aspt, array_const_set, rtl_extra_wire); + // this will find array[const] and replace as a word reference } } @@ -293,9 +315,12 @@ void VlgSglTgtGen:: ILA_DLOG("VTG.AddWireEq") << eq->to_verilog(); std::map array_var; - if (rfmap::RfExprAstUtility::HasArrayVar(eq, array_var)) + if (rfmap::RfExprAstUtility::HasArrayVar(eq, array_var)) { + ILA_ERROR_IF(!_vtg_config.YosysSmtArrayForRegFile) + << "Requiring array sort in Yosys when generating" + << " properties, please enable YosysSmtArrayForRegFile"; add_smt_assumption(eq, dspt); - else + } else vlg_wrapper.add_assign_stmt(wn, eq->child(1)->to_verilog()); } @@ -304,9 +329,12 @@ void VlgSglTgtGen:: ILA_DLOG("VTG.AddAssume") << aspt->to_verilog(); std::map array_var; - if (rfmap::RfExprAstUtility::HasArrayVar(aspt, array_var)) + if (rfmap::RfExprAstUtility::HasArrayVar(aspt, array_var)) { + ILA_ERROR_IF(!_vtg_config.YosysSmtArrayForRegFile) + << "Requiring array sort in Yosys when generating" + << " properties, please enable YosysSmtArrayForRegFile"; add_smt_assumption(aspt, dspt_aspt.first); - else + } else add_a_direct_assumption(aspt->to_verilog(), dspt_aspt.first); } } @@ -333,6 +361,16 @@ void VlgSglTgtGen:: add_a_direct_sanity_assertion(asst->to_verilog(), dspt_asst.first); } } + for (const auto& dspt_cvrs : all_covers) { + for (const auto& cvr : dspt_cvrs.second) { + std::map array_var; + ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(cvr, array_var)) + << "Implementation bug: cover checks should not contain " + "arrays"; + + add_a_direct_cover_check(cvr->to_verilog(), dspt_cvrs.first); + } + } } // ConstructWrapper_translate_property_and_collect_all_rtl_connection_var diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index 3d5480557..3d2448586 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -92,8 +92,11 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { rfmap_add_replacement("decode", "__START__"); vlg_wrapper.add_stmt("always @(posedge clk) begin"); // how start is triggered - - vlg_wrapper.add_stmt("if (rst) __START__ <= 1;"); + if(_vtg_config.ForceInstCheckReset) { + vlg_wrapper.add_stmt("if (__ISSUE__ && !__START__ && !__STARTED__) __START__ <= 1;"); + } else { + vlg_wrapper.add_stmt("if (rst) __START__ <= 1;"); + } vlg_wrapper.add_stmt("else if (__START__ || __STARTED__) __START__ <= 0;"); vlg_wrapper.add_stmt("end"); @@ -195,6 +198,11 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { rfmap_and({iend_cond, rfmap_var("__STARTED__"), rfmap_var("__RESETED__"), end_no_recur, max_bound_constr}), "IEND"); + + if(_vtg_config.CheckInstrCommitSatisfiable) { + add_a_cover(rfmap_var("commit"), "inst_will_commit"); + } + // handle start decode if (!instr.start_condition.empty()) { diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index eede7568f..41953a2d3 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -68,7 +68,6 @@ std::string VlgSglTgtGen::ConstructWrapper_get_ila_module_inst() { // TODO: check whether all ports have been dealt with // TODO: check whether there are any extra ports we create std::set port_connected; // store the name of ila port - std::set port_of_ila; // store the name of ila port also // .. record function diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 7656f7c53..6af55c8a1 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -257,6 +257,7 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { stage_name + " <= 1'b1;"); vlg_wrapper.add_wire(enter_cond_wire_name, 1, true); rfmap_add_internal_wire(enter_cond_wire_name, 1); + ILA_NOT_NULL(stage.enter_rule); add_wire_assign_assumption(enter_cond_wire_name, stage.enter_rule, "phase_tracker"); @@ -282,8 +283,11 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { vlg_wrapper.add_wire(exit_cond_wire_name, 1, true); rfmap_add_internal_wire(exit_cond_wire_name, 1); - add_wire_assign_assumption(exit_cond_wire_name, stage.exit_rule, - "phase_tracker"); + if (stage.exit_rule == nullptr) + vlg_wrapper.add_assign_stmt(exit_cond_wire_name, "1'b0"); + else + add_wire_assign_assumption(exit_cond_wire_name, stage.exit_rule, + "phase_tracker"); idx = 0; for (const auto& action : stage.exit_action) { @@ -343,8 +347,10 @@ void VlgSglTgtGen::ConstructWrapper_add_post_value_holder() { // pv_sn_cond = && ( __START__ || __STARTED__ ) add_wire_assign_assumption( pv_name + "_sn_cond", - rfmap_and(post_val_holder.second.condition, - rfmap_or(rfmap_var("__START__"), rfmap_var("__STARTED__"))), + rfmap_and({post_val_holder.second.condition, + rfmap_or(rfmap_var("__START__"), rfmap_var("__STARTED__")), + rfmap_not(rfmap_var("__ENDED__")) + }), "pvholder_cond_assign"); // pv_sn_value = @@ -358,12 +364,18 @@ void VlgSglTgtGen::ConstructWrapper_add_post_value_holder() { rfmap_var(pv_name + "_sn_cond")), rfmap_eq(rfmap_var(pv_name + "_sn_value"), rfmap_var(pv_name + "_sn_vhold"))), - "post_value_holder"); - - // you need to add checker + "post_value_holder_overly_constrained"); - // check no - } + // check : commit -> _cond_met + add_a_santiy_assertion( + rfmap_imply(rfmap_var("commit"), + rfmap_or( + rfmap_var(pv_name + "_sn_condmet"), + rfmap_var(pv_name + "_sn_cond") + )), + "post_value_holder_triggered"); + + } // for each value recorder } // ConstructWrapper_add_post_value_holder void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { diff --git a/src/vtarget-out/vtarget_gen_jasper.cc b/src/vtarget-out/vtarget_gen_jasper.cc index ab351013d..f6d1fc88a 100644 --- a/src/vtarget-out/vtarget_gen_jasper.cc +++ b/src/vtarget-out/vtarget_gen_jasper.cc @@ -57,6 +57,12 @@ void VlgSglTgtGen_Jasper::add_a_direct_assertion(const std::string& asst, const std::string& dspt) { assertions.push_back(std::make_pair(asst, dspt)); } +/// Add an cover check +void VlgSglTgtGen_Jasper::add_a_direct_cover_check(const std::string& cvr, + const std::string& dspt) { + covers.push_back(std::make_pair(cvr, dspt)); +} + /// export the script to run the verification void VlgSglTgtGen_Jasper::Export_script(const std::string& script_name) { @@ -122,6 +128,11 @@ void VlgSglTgtGen_Jasper::Export_problem(const std::string& extra_name) { for (auto&& asst_dspt_pair : assertions) fout << "assert -name " << asst_dspt_pair.second + std::to_string(No++) << " {" << asst_dspt_pair.first << "}" << std::endl; + + No = 0; + for (auto&& cover_dspt_pair : covers) + fout << "cover -name " << cover_dspt_pair.second + std::to_string(No++) + << " {" << cover_dspt_pair.first << "}" << std::endl; } /// For jasper, this means do nothing, for yosys, you need to add (*keep*) diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index d73135180..2af81efc1 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -23,12 +23,67 @@ hierarchy -check proc chformal -assume -early; %propselect% -memory -nomap; +memory %-nomap%; flatten +setundef -undriven -expose; sim -clock clk -reset rst -rstlen %rstlen% -n %cycle% -w %module% )***"; // %propselect% is for +static const std::string show_result_bash_script = R"***( +function show_result () { + RfError="" + SanityError="" + CoverError="" + + if test $RfResult = 0; then RfMsg=" (* buggy)"; + elif test $RfResult = 1; then RfMsg=" (passed)"; + elif test $RfResult = 2; then RfMsg=" (* checker error)"; + elif test $RfResult = 3; then RfMsg=" (skipped)"; + elif test $RfResult = 255; then RfMsg=" (unknown)"; + else echo "UNKNOWN PONO RESULT: " $RfResult; RfMsg=" (* terminated)"; RfResult=2 + fi + + if test $SanityResult = 0; then SanityMsg=" (* sanity violation)"; + elif test $SanityResult = 1; then SanityMsg=" (sanity is proved to hold)"; + elif test $SanityResult = 2; then SanityMsg=" (* checker error)"; + elif test $SanityResult = 3; then SanityMsg=" (skipped)"; + elif test $SanityResult = 255; then SanityMsg=" (no sanity violation within bound)"; + else echo "UNKNOWN PONO RESULT: " $SanityResult; SanityMsg=" (* terminated)"; SanityResult=2 + fi + + if test $CoverResult = 0; then CoverMsg=" (covered)"; + elif test $CoverResult = 1; then CoverMsg=" (* not reachable)"; + elif test $CoverResult = 2; then CoverMsg=" (* checker error)"; + elif test $CoverResult = 3; then CoverMsg=" (skipped)"; + elif test $CoverResult = 255; then CoverMsg=" (* not yet reachable)"; + else echo "UNKNOWN PONO RESULT: " $CoverResult; CoverMsg=" (* terminated)"; CoverResult=2; + fi + + echo '============ SUMMARY ============' + echo 'Refinement Check:' $RfResult $RfMsg + echo 'Santiy Check:' $SanityResult $SanityMsg + echo 'Cover Check:' $CoverResult $CoverMsg + echo '============ END OF SUMMARY ============' + echo "" + + if [ $RfResult = 2 ] || [ $SanityResult = 2 ] || [ $CoverResult = 2 ]; then + return 2 + fi + + if test $RfResult = 0; then return 0; + elif test $SanityResult = 0; then return 0; + elif test $CoverResult = 1; then return 0; + elif test $CoverResult = 255; then return 255; + else return $RfResult; + fi +} + +show_result +exit $? + +)***"; + VlgSglTgtGen_Pono::VlgSglTgtGen_Pono( const std::string& output_path, // will be a sub directory of the output_path of its parent @@ -75,6 +130,16 @@ void VlgSglTgtGen_Pono::add_a_direct_sanity_assertion(const std::string& asst, _problems.sanity_assertions[dspt].exprs.push_back(wire_name); } +/// Add a cover assertion +void VlgSglTgtGen_Pono::add_a_direct_cover_check(const std::string& asst, + const std::string& dspt) { + auto wire_name = dspt + new_property_id(); + vlg_wrapper.add_wire(wire_name, 1); + vlg_wrapper.add_output(wire_name, 1); + vlg_wrapper.add_assign_stmt(wire_name, asst); + _problems.cover_checks[dspt].exprs.push_back(wire_name); +} + /// export the script to run the verification void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { @@ -85,6 +150,10 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { return; } fout << "#!/bin/bash" << std::endl; + fout << "echo \"* Remove prior results...\"" << std::endl; + fout << "rm -f *.btor2 *.vcd __yosys*.txt" << std::endl; + + fout << "echo \"* Parsing input...\"" << std::endl; std::string yosys = "yosys"; @@ -116,17 +185,48 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { extra_smt_properties += " --property-file property.smt2 "; } + fout << "echo \"* Run Pono to check refinement...\"" << std::endl; fout << pono << options << extra_smt_properties << " problem.btor2 " << std::endl; + fout << "RfResult=$?" << std::endl; + if (!_problems.sanity_assertions.empty()) { + fout << "echo \"* Parsing sanity check input...\"" << std::endl; fout << yosys << " -s gen_sanity_prop.ys > __yosys_exec_result.sanity.txt\n"; // here we intentionally leave out the property interface file. + + fout << "echo \"* Run Pono to check assumption sanity...\"" << std::endl; fout << pono << options << " sanity.btor2 " << std::endl; + fout << "SanityResult=$?" << std::endl; + } else { + fout << "SanityResult=3" << std::endl; + } + + if(all_cover_assert_property_names.empty()) { + fout << "CoverResult=3" << std::endl; + } else + fout << "CoverResult=0" << std::endl; + + for (unsigned idx = 0; idx < all_cover_assert_property_names.size(); ++idx) { + auto cover_fname = "cover" + std::to_string(idx)+".btor2"; + std::string cover_options = " -e bmc " + _vtg_config.PonoOtherOptions; + + fout << "echo \"* Parsing cover check input #" < __yosys_exec_result.cover" << idx<<".txt\n"; + + fout << "echo \"Run Pono to check cover property (expecting sat)...\"" << std::endl; + fout << pono << cover_options << " " << cover_fname << std::endl; + fout << "if test $? != 0; then CoverResult=$?; fi" << std::endl; } + + fout << show_result_bash_script << std::endl; + } // Export_script + /// Add SMT-lib2 assumption void VlgSglTgtGen_Pono::add_a_direct_smt_assumption(const std::string& arg, const std::string& ret, @@ -149,56 +249,89 @@ void VlgSglTgtGen_Pono::add_a_direct_smt_assertion(const std::string& arg, ret + " " + body + ")"); } + +void VlgSglTgtGen_Pono::GenYosysScript( + const std::string& ys_script_name_path, + const std::string& property_selection_cmd, + const std::string& generated_btor_name ) +{ + // export to ys_script_name + std::ofstream ys_script_fout(ys_script_name_path); + + std::string write_btor_options; + write_btor_options += _vtg_config.BtorAddCommentsInOutputs ? " -v" : ""; + write_btor_options += _vtg_config.BtorSingleProperty ? " -s" : ""; + + ys_script_fout << "read_verilog -sv " + << os_portable_append_dir(_output_path, top_file_name) + << std::endl; + ys_script_fout << "prep -top " << top_mod_name << std::endl; + + ILA_CHECK( + refinement_map.clock_specification.custom_clock_factor.empty() && + refinement_map.clock_specification.custom_clock_sequence.empty() + ) << "TODO: custom clock sequence not implemented yet"; + + ILA_CHECK( + refinement_map.reset_specification.custom_reset_sequence.empty() && + refinement_map.reset_specification.initial_state.empty() + ) << "TODO: custom reset sequence not implemented yet"; + + ys_script_fout << ReplaceAll( + ReplaceAll( + ReplaceAll( + ReplaceAll( + ReplaceAll(yosysGenerateBtor, "%rstlen%", + std::to_string( + refinement_map.reset_specification.reset_cycle)), + "%cycle%", + std::to_string(refinement_map.reset_specification.reset_cycle)), + "%module%", top_mod_name), + "%propselect%", property_selection_cmd), + "%-nomap%", _vtg_config.YosysSmtArrayForRegFile ? "-nomap" : "" ); + + // this is for pono, I don't know why it is unhappy, but we need fix this + // in the long run + if (_vtg_config.YosysSetUndrivenZero) + ys_script_fout << "setundef -undriven -zero\n"; + + ys_script_fout << "write_btor " << write_btor_options + << " " << generated_btor_name + << std::endl; +} // VlgSglTgtGen_Pono::GenYosysScript + /// export the yosys script void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { + if (_problems.assertions.empty() && _problems.smt_assertions.empty() && - _problems.sanity_assertions.empty()) { + _problems.sanity_assertions.empty() && _problems.cover_checks.empty() + ) { ILA_ERROR << "Nothing to prove, no assertions inserted!"; return; } ys_script_name = yosys_script_name; - std::string ys_script_name_path = - os_portable_append_dir(_output_path, ys_script_name); - { // export to ys_script_name - std::ofstream ys_script_fout(ys_script_name_path); - - std::string write_btor_options; - write_btor_options += _vtg_config.BtorAddCommentsInOutputs ? " -v" : ""; - write_btor_options += _vtg_config.BtorSingleProperty ? " -s" : ""; - - ys_script_fout << "read_verilog -sv " - << os_portable_append_dir(_output_path, top_file_name) - << std::endl; - ys_script_fout << "prep -top " << top_mod_name << std::endl; - + { // export the main script + std::string ys_script_name_path = + os_portable_append_dir(_output_path, ys_script_name); std::string property_selection_cmd; if (!_problems.sanity_assertions.empty()) { - property_selection_cmd = "\n" + property_selection_cmd +="\n" "select wrapper/sanitycheck\n" "chformal -remove\n" "select *\n"; } + if (!_problems.cover_checks.empty()) { + ILA_CHECK(!all_cover_assert_property_names.empty()); + for(const auto & p : all_cover_assert_property_names) + property_selection_cmd +="\n" + "select wrapper/"+ p +(" \n" + "chformal -remove\n" + "select *\n"); + } - ys_script_fout << ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll(yosysGenerateBtor, "%rstlen%", - std::to_string( - refinement_map.reset_specification.reset_cycle)), - "%cycle%", - std::to_string(refinement_map.reset_specification.reset_cycle)), - "%module%", top_mod_name), - "%propselect%", property_selection_cmd); - - // this is for pono, I don't know why it is unhappy, but we need fix this - // in the long run - if (_vtg_config.YosysSetUndrivenZero) - ys_script_fout << "setundef -undriven -zero\n"; - - ys_script_fout << "write_btor " << write_btor_options << " problem.btor2" - << std::endl; + GenYosysScript(ys_script_name_path, property_selection_cmd, "problem.btor2"); } // finish writing auto smt_property_fname = @@ -212,57 +345,89 @@ void VlgSglTgtGen_Pono::Export_problem(const std::string& yosys_script_name) { smt_fout << prop << std::endl; } - // sanity checks - if (!_problems.sanity_assertions.empty()) { // export to ys_script_name + if (!_problems.sanity_assertions.empty()) { std::string ys_script_name_path = os_portable_append_dir(_output_path, "gen_sanity_prop.ys"); - std::ofstream ys_script_fout(ys_script_name_path); - - std::string write_btor_options; - write_btor_options += _vtg_config.BtorAddCommentsInOutputs ? " -v" : ""; - write_btor_options += _vtg_config.BtorSingleProperty ? " -s" : ""; - - ys_script_fout << "read_verilog -sv " - << os_portable_append_dir(_output_path, top_file_name) - << std::endl; - ys_script_fout << "prep -top " << top_mod_name << std::endl; - std::string property_selection_cmd = "\n" "select wrapper/normalassert\n" "chformal -remove\n" "select *\n"; + + if (!_problems.cover_checks.empty()) { + ILA_CHECK(!all_cover_assert_property_names.empty()); + for(const auto & p : all_cover_assert_property_names) + property_selection_cmd +="\n" + "select wrapper/"+ p +(" \n" + "chformal -remove\n" + "select *\n"); + } + GenYosysScript(ys_script_name_path, property_selection_cmd, "sanity.btor2"); + } // finish writing sanity check Yosys script - ILA_CHECK( - refinement_map.clock_specification.custom_clock_factor.empty() && - refinement_map.clock_specification.custom_clock_sequence.empty() - ) << "TODO: custom clock sequence not implemented yet"; - - ILA_CHECK( - refinement_map.reset_specification.custom_reset_sequence.empty() && - refinement_map.reset_specification.initial_state.empty() - ) << "TODO: custom reset sequence not implemented yet"; + if (!_problems.cover_checks.empty()) { + ILA_CHECK(!all_cover_assert_property_names.empty()); - ys_script_fout << ReplaceAll( - ReplaceAll( - ReplaceAll( - ReplaceAll(yosysGenerateBtor, "%rstlen%", - std::to_string( - refinement_map.reset_specification.reset_cycle)), - "%cycle%", - std::to_string(refinement_map.reset_specification.reset_cycle)), - "%module%", top_mod_name), - "%propselect%", property_selection_cmd); - - // this is for pono, I don't know why it is unhappy, but we need fix this - // in the long run - if (_vtg_config.YosysSetUndrivenZero) - ys_script_fout << "setundef -undriven -zero\n"; - - ys_script_fout << "write_btor " << write_btor_options << " sanity.btor2" - << std::endl; - } // finish writing -} // only for Pono + std::string property_selection_cmd_tmpl = "\n" + "select wrapper/normalassert\n" + "chformal -remove\n" + "select *\n"; + + if(!_problems.sanity_assertions.empty()) { + property_selection_cmd_tmpl += "\n" + "select wrapper/sanitycheck\n" + "chformal -remove\n" + "select *\n"; + } + + for (unsigned idx = 0; idx < all_cover_assert_property_names.size() ; ++idx) { + std::string ys_script_name_path = + os_portable_append_dir(_output_path, "gen_cover_prop" + std::to_string(idx) + ".ys"); + + std::string property_selection_cmd = property_selection_cmd_tmpl; + for(unsigned jdx = 0; jdx < all_cover_assert_property_names.size(); ++jdx) { + if (jdx == idx) + continue; + // remove all other covers + property_selection_cmd += "\n" + "select wrapper/" + all_cover_assert_property_names.at(jdx) + "\n" + "chformal -remove\n" + "select *\n"; + } // end for each other cover property remove it + + GenYosysScript(ys_script_name_path, property_selection_cmd, "cover"+ std::to_string(idx) +".btor2"); + } // end for each cover property + } // finish writing cover check Yosys script + + + if(_vtg_config.PonoGenJgScript) { + auto jg_script_fname = os_portable_append_dir(_output_path, "jg.tcl"); + std::ofstream fout(jg_script_fname); + ILA_ERROR_IF(!fout.is_open()) << "Cannot write to " << jg_script_fname; + fout << "analyze -sva " << top_file_name << std::endl; + fout << "elaborate -top " << top_mod_name << std::endl; + fout << "clock clk" << std::endl; + fout << "reset rst" << std::endl; + // remove cover assert + for (const auto & pname : all_cover_assert_property_names) { + fout << "assert -disable " << pname << std::endl; + } + // re-insert as jg covers + unsigned cover_property_id = 0; + for (auto && pbname_prob_pair : _problems.cover_checks) { + // const auto& prbname = pbname_prob_pair.first; + const auto& prob = pbname_prob_pair.second; + + for (auto&& p : prob.exprs) { + // there should be only one expression (for cex target) + // ILA_CHECK(all_assert_wire_content.empty()); + fout << "cover -name " << "cover_"<<(cover_property_id++) << " {" + << p << "}"; + } // for expr + } // end for each cover + } // end for jg script + +} // end of Export_problem -- export Yosys script // PreExportProcess is about how to add assumption/assertions void VlgSglTgtGen_Pono::PreExportProcess() { @@ -333,6 +498,21 @@ void VlgSglTgtGen_Pono::PreExportProcess() { } // for expr } + unsigned cover_property_id = 0; + for (auto && pbname_prob_pair : _problems.cover_checks) { + // const auto& prbname = pbname_prob_pair.first; + const auto& prob = pbname_prob_pair.second; + + for (auto&& p : prob.exprs) { + // there should be only one expression (for cex target) + // ILA_CHECK(all_assert_wire_content.empty()); + auto property_name = "negcoverassert" + std::to_string(cover_property_id ++); + vlg_wrapper.add_stmt(property_name + ": assert property (!" + + p +"); /*expecting: false*/"); + all_cover_assert_property_names.push_back(property_name); + } // for expr + } + vlg_wrapper.add_wire("__all_assert_wire__", 1, true); vlg_wrapper.add_output("__all_assert_wire__", 1); vlg_wrapper.add_assign_stmt("__all_assert_wire__", all_assert_wire_content); diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index 0d918cc76..584dbdf39 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -41,6 +41,10 @@ TEST(TestVlgTargetGen, PipeExample) { TEST(TestVlgTargetGen, PipeExampleRfmapPost) { auto ila_model = SimplePipe::BuildModel(); + RtlVerifyConfig cfg; + cfg.CheckInstrCommitSatisfiable = true; + cfg.PonoGenJgScript = true; + auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); auto rfDir = os_portable_append_dir(dirName, "rfmap"); @@ -54,7 +58,39 @@ TEST(TestVlgTargetGen, PipeExampleRfmapPost) { "cond-rfmap-pvholder.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_pvholder"), // verification dir ila_model.get(), // ILA model - ModelCheckerSelection::PONO // engine + ModelCheckerSelection::PONO, // engine + cfg + ); + + EXPECT_FALSE(vg.in_bad_state()); + + vg.GenerateTargets(); +} + + +TEST(TestVlgTargetGen, PipeExampleRfmapPostResetStart) { + auto ila_model = SimplePipe::BuildModel(); + RtlVerifyConfig cfg; + cfg.PonoGenJgScript = true; + cfg.ForceInstCheckReset = true; + cfg.CheckInstrCommitSatisfiable = true; + cfg.PonoOtherOptions = " -v 1 "; + + auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); + auto rfDir = os_portable_append_dir(dirName, "rfmap"); + + VerilogVerificationTargetGenerator vg( + {}, // no include + {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files + "pipeline_v", // top_module_name + os_portable_append_dir(rfDir, + "vmap-rfmap-pvholder.json"), // variable mapping + os_portable_append_dir(rfDir, + "cond-rfmap-pvholder.json"), // instruction-mapping + os_portable_append_dir(dirName, "verify_pvholder_reset"), // verification dir + ila_model.get(), // ILA model + ModelCheckerSelection::PONO, // engine + cfg ); EXPECT_FALSE(vg.in_bad_state()); @@ -63,6 +99,10 @@ TEST(TestVlgTargetGen, PipeExampleRfmapPost) { } TEST(TestVlgTargetGen, PipeStallRfmapShortNoValueHolder) { + RtlVerifyConfig cfg; + cfg.PonoEngine = "bmc"; + cfg.PonoOtherOptions = " -k 5 -v 1 "; + auto ila_model = SimplePipe::BuildStallModel(); auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); @@ -81,7 +121,8 @@ TEST(TestVlgTargetGen, PipeStallRfmapShortNoValueHolder) { os_portable_append_dir( dirName, "verify_stall_short_nopvholder"), // verification dir ila_model.get(), // ILA model - ModelCheckerSelection::PONO // engine + ModelCheckerSelection::PONO, // engine + cfg ); EXPECT_FALSE(vg.in_bad_state()); @@ -89,7 +130,13 @@ TEST(TestVlgTargetGen, PipeStallRfmapShortNoValueHolder) { vg.GenerateTargets(); } +// stall short has no instruction buffer +// it is 1 stage shorter than stall TEST(TestVlgTargetGen, PipeStallRfmapShort) { + RtlVerifyConfig cfg; + cfg.PonoEngine = "bmc"; + cfg.PonoOtherOptions = " -k 5 -v 1 "; + auto ila_model = SimplePipe::BuildStallModel(); auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); @@ -108,7 +155,8 @@ TEST(TestVlgTargetGen, PipeStallRfmapShort) { "cond-rfmap-pvholder-stall-short.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_stall_short"), // verification dir ila_model.get(), // ILA model - ModelCheckerSelection::PONO // engine + ModelCheckerSelection::PONO, // engine + cfg ); EXPECT_FALSE(vg.in_bad_state()); @@ -117,6 +165,10 @@ TEST(TestVlgTargetGen, PipeStallRfmapShort) { } TEST(TestVlgTargetGen, PipeStallRfmap) { + RtlVerifyConfig cfg; + cfg.PonoEngine = "bmc"; + cfg.PonoOtherOptions = " -k 5 -v 1 "; + auto ila_model = SimplePipe::BuildStallModel(); auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); @@ -134,7 +186,8 @@ TEST(TestVlgTargetGen, PipeStallRfmap) { "cond-rfmap-pvholder-stall.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_stall"), // verification dir ila_model.get(), // ILA model - ModelCheckerSelection::PONO // engine + ModelCheckerSelection::PONO, // engine + cfg ); EXPECT_FALSE(vg.in_bad_state()); @@ -185,6 +238,31 @@ TEST(TestVlgTargetGen, PipeExampleNotEqu) { vg.GenerateTargets(); } + +TEST(TestVlgTargetGen, PipeExampleNotEquFromReset) { + auto ila_model = SimplePipe::BuildModel(); + RtlVerifyConfig cfg; + cfg.ForceInstCheckReset = true; + cfg.PonoGenJgScript = true; + + auto dirName = + os_portable_join_dir({ILANG_TEST_SRC_ROOT, "unit-data", "vpipe"}); + VerilogVerificationTargetGenerator vg( + {}, // no include + {os_portable_append_dir(dirName, "simple_pipe_wrong.v")}, // + "pipeline_v", // top_module_name + os_portable_append_dir(dirName, + P({"rfmap", "vmap.json"})), // variable mapping + os_portable_append_dir(dirName, P({"rfmap", "cond.json"})), + os_portable_append_dir(dirName, "disprove-reset/"), ila_model.get(), + ModelCheckerSelection::PONO, + cfg); + + EXPECT_FALSE(vg.in_bad_state()); + + vg.GenerateTargets(); +} + // #warning "Continue your test from here" TEST(TestVlgTargetGen, Memory) { @@ -256,13 +334,13 @@ TEST(TestVlgTargetGen, MemoryInternalExternal) { TEST(TestVlgTargetGen, MemoryInternalExternalEntry6) { auto ila_model = MemorySwap::BuildRfAsMemModelRegEntry6(); - DebugLog::Enable("VTG.ReplWireEq"); - DebugLog::Enable("VTG.ReplAssert"); - DebugLog::Enable("VTG.ReplAssume"); + // DebugLog::Enable("VTG.ReplWireEq"); + // DebugLog::Enable("VTG.ReplAssert"); + // DebugLog::Enable("VTG.ReplAssume"); - DebugLog::Enable("VTG.AddWireEq"); - DebugLog::Enable("VTG.AddAssert"); - DebugLog::Enable("VTG.AddAssume"); + // DebugLog::Enable("VTG.AddWireEq"); + // DebugLog::Enable("VTG.AddAssert"); + // DebugLog::Enable("VTG.AddAssume"); RtlVerifyConfig vtg_cfg; vtg_cfg.PonoAddKeep = false; diff --git a/test/unit-data/vpipe/.gitignore b/test/unit-data/vpipe/.gitignore index 6e701d8f2..94d1d5813 100644 --- a/test/unit-data/vpipe/.gitignore +++ b/test/unit-data/vpipe/.gitignore @@ -3,7 +3,9 @@ verify/* verify_jg/* verify_pvholder/* +verify_pvholder_reset/* disprove/* +disprove-reset/* vmem/invariants vmem/SWAP vmem/SWAPExpand diff --git a/test/unit-data/vpipe/autoRunAll.py b/test/unit-data/vpipe/autoRunAll.py new file mode 100755 index 000000000..71415a82d --- /dev/null +++ b/test/unit-data/vpipe/autoRunAll.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +import os + +rootDir = '.' +allTaskInfo = {} # 'path -> result' + +ignored_subdir = set() + +cmd = "bash run.sh" + + +# --------------------- HELPER --------------------- ## +def ExecOnPath(p): + if not os.path.exists(p): + print 'Path:',p,'does not exist' + return + if not os.path.exists(os.path.join(p,'run.sh')): + # ignored + ignored_subdir.add(p) + return + if not os.path.exists(os.path.join(p,'gen_btor.ys')): + # ignored + allTaskInfo[p] = "skip" + return + + curDir = os.getcwd() + os.chdir(p) + print 'cd',p + finalCmd = cmd + print 'exec:',finalCmd + + os.system("rm -f *.btor *.btor2") + ret = os.system(finalCmd) + if ret == 256: + ret = 1 + elif ret == 65280: + ret = 255 + elif ret == 512: + ret = 2 + + os.chdir(curDir) + allTaskInfo[p] = ret + +# --------------------- MAIN --------------------- ## + +for dirName, subdirList, fileList in os.walk(rootDir): + for subDirName in subdirList: + ExecOnPath(os.path.join(dirName, subDirName)) + +print +print '----------- PASSED ------------' +for t,r in allTaskInfo.items(): + if r == 1: + print t + +print +print '----------- UNKNOWN ------------' +for t,r in allTaskInfo.items(): + if r == 255: + print t + +print +print '----------- FAILED ------------' +for t,r in allTaskInfo.items(): + if r == 0: + print t + +print +print '----------- SKIPPED ------------' +for t,r in allTaskInfo.items(): + if r == "skip": + print t + +print +print '----------- No Valid run.sh ------------' +print ignored_subdir + +print +print '----------- STATUS-ERR ------------' +for t,r in allTaskInfo.items(): + if r not in [0,1,255,"skip"]: + print r,':',t + diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json index ffa0d77d2..08f42150e 100644 --- a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json @@ -77,6 +77,11 @@ "name" : "wb", "enter" : {"event" : "#ppl_stage_ex#"}, "exit" : {"event" : "1"} + }, + + { + "name" : "teststage1", + "enter" : "#ppl_stage_ex#" } ] diff --git a/test/unit-data/vpipe/simple_pipe.v b/test/unit-data/vpipe/simple_pipe.v index 82c47d975..e4a8b2003 100644 --- a/test/unit-data/vpipe/simple_pipe.v +++ b/test/unit-data/vpipe/simple_pipe.v @@ -198,14 +198,7 @@ end // WB always @(posedge clk ) begin - if (rst) begin - // reset - registers[0] <= 8'd0; - registers[1] <= 8'd0; - registers[2] <= 8'd0; - registers[3] <= 8'd0; - end - else if (ex_wb_reg_wen) begin + if (ex_wb_reg_wen) begin case (ex_wb_rd) 2'd0: registers[0] <= ex_wb_val; 2'd1: registers[1] <= ex_wb_val; diff --git a/test/unit-data/vpipe/simple_pipe_wrong.v b/test/unit-data/vpipe/simple_pipe_wrong.v index 3c4e58986..0e83edd96 100644 --- a/test/unit-data/vpipe/simple_pipe_wrong.v +++ b/test/unit-data/vpipe/simple_pipe_wrong.v @@ -196,14 +196,7 @@ end // WB always @(posedge clk ) begin - if (rst) begin - // reset - registers[0] <= 8'd0; - registers[1] <= 8'd0; - registers[2] <= 8'd0; - registers[3] <= 8'd0; - end - else if (ex_wb_reg_wen) begin + if (ex_wb_reg_wen) begin case (ex_wb_rd) 2'd0: registers[0] <= ex_wb_val; 2'd1: registers[1] <= ex_wb_val; From 61c7588932adfc07a7ae6d43c3b5456114cdcce5 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sat, 23 Oct 2021 22:52:30 +0800 Subject: [PATCH 54/78] update vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index cc7c2524b..2a478edeb 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit cc7c2524bdf6edd91deaddbd2fa9e8abcbf08427 +Subproject commit 2a478edeb2841c793ea347b5cb6a98c9e7c4382d From dd8f61eb12eb88f7d6832d58629a23b06b06b743 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 24 Oct 2021 00:28:53 +0800 Subject: [PATCH 55/78] before remove mod --- include/ilang/rfmap-in/verilog_rfmap.h | 2 + src/rfmap-in/rfmap_typecheck.cc | 50 ++++++++++++++++--- src/rfmap-in/verilog_rfmap.cc | 23 +++++++-- src/vtarget-out/directive.cc | 11 +++- src/vtarget-out/single_target_cond.cc | 1 + src/vtarget-out/single_target_connect.cc | 9 ++++ src/vtarget-out/single_target_misc.cc | 5 ++ .../vpipe/rfmap/vmap-rfmap-pvholder.json | 13 +++-- 8 files changed, 98 insertions(+), 16 deletions(-) diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 433f498d9..12993ac59 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -75,6 +75,8 @@ struct RtlInterfaceMapping { std::set nreset_pins; // "CUSTOMRESET" : {"name" : "input-pin", ...} std::map> custom_reset_domain_defs; + // "INPUT/INPUTs/INPUT-ports", + std::map input_port_connection; }; // struct RtlInterfaceMapping typedef std::vector OneBitSignalSequence; diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index c0a9a9e42..a64f01cc1 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -115,14 +115,17 @@ void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr& inout) { int delay = inout->get_parameter().at(0); aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), delay)); + std::cout << "SingleDelay:" <get_child().at(0) <get_parameter().size() == 2 // RANGE/INF a ##[n,m] / ##[n,0] 0 represents $ int delay = inout->get_parameter().at(0); int delay_upper = inout->get_parameter().at(1); aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), delay, delay_upper)); + std::cout << "2Delay:" <get_child().at(0) <get_child().size() == 1) { inout = new_node; } else { @@ -131,6 +134,7 @@ void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr& inout) { inout->get_child().at(1)); inout = tmp_node; } + std::cout << "-->:" << inout <get_child_cnt() == 1 && ( + in->get_op() == voperator::B_AND || // & a + in->get_op() == voperator::B_NAND || // ~& a + in->get_op() == voperator::B_OR || // | a + in->get_op() == voperator::B_NOR || // ~| a + in->get_op() == voperator::B_XOR || // ^ a + in->get_op() == voperator::B_EQU // "^~"|"~^" + ) ) { + return RfMapVarType(1); + } + if (in->get_op() == verilog_expr::voperator::STAR || in->get_op() == verilog_expr::voperator::PLUS || in->get_op() == verilog_expr::voperator::MINUS || @@ -593,12 +614,14 @@ void RfExprAstUtility::TraverseRfExpr(RfExpr& inout, continue; } else { // enter c[idx] - if (lastlv.first->get_child_cnt() == 0) { - func(lastlv.first->child(idx)); - ++idx; - } else { - parent_stack.push_back(std::make_pair(lastlv.first->child(idx), 0U)); - } + ILA_CHECK(lastlv.first->get_child_cnt() != 0); + // if (lastlv.first->get_child_cnt() == 0) { + // ILA_CHECK(false) << "Should not be reachable!"; + // func(lastlv.first->child(idx)); + // ++idx; + // } else { + parent_stack.push_back(std::make_pair(lastlv.first->child(idx), 0U)); + //} } } // end of while func(inout); @@ -657,6 +680,21 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { assert(inout->get_op() != verilog_expr::voperator::MK_CONST && inout->get_op() != verilog_expr::voperator::MK_VAR); + if ( inout->get_child_cnt() == 1 && + ( + inout->get_op() == voperator::B_AND || + inout->get_op() == voperator::B_NAND || + inout->get_op() == voperator::B_OR || + inout->get_op() == voperator::B_NOR || + inout->get_op() == voperator::B_XOR || + inout->get_op() == voperator::B_EQU // "^~"|"~^" + ) ) { + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(1); + inout->set_annotation(new_annotation); + return; + } + if (inout->get_op() == verilog_expr::voperator::STAR || inout->get_op() == verilog_expr::voperator::PLUS || inout->get_op() == verilog_expr::voperator::MINUS || diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 6b1f439ef..c698e9a44 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -379,27 +379,27 @@ std::string JsonRfMapParseVarDefs( nlohmann::json& def_field) { ENSURE(def_field.is_array(), - "`defs` field should be list of [name, width, type]"); + "`defs` field should be list of [[name, width, type], ...]"); for (auto& one_def : def_field) { ENSURE(one_def.is_array(), - "`defs` field should be list of [name, width, type]"); + "`defs` field should be list of [[name, width, type], ...]"); auto pos = one_def.begin(); ENSURE(pos != one_def.end() && pos->is_string(), - "`defs` field should be list of [name, width, type]"); + "`defs` field should be list of [[name, width, type], ...]"); auto var_name = pos->get(); ENSURE(!IN(var_name, var_defs), "var " + var_name + " has been defined"); ++pos; ENSURE(pos != one_def.end() && pos->is_number_unsigned(), - "`defs` field should be list of [name, width, type]"); + "`defs` field should be list of [[name, width, type], ...]"); var_defs[var_name].width = pos->get(); ERRIF(var_defs[var_name].width == 0, "Definition of " + var_name + " has 0 width"); ++pos; ENSURE(pos != one_def.end() && pos->is_string(), - "`defs` field should be list of [name, width, type]"); + "`defs` field should be list of [[name, width, type], ...]"); auto tp = pos->get(); ENSURE(SectionNameRelaxedMatch(tp, "reg") || SectionNameRelaxedMatch(tp, "wire"), @@ -698,6 +698,8 @@ VerilogRefinementMap::VerilogRefinementMap( nlohmann::json* nreset_list = GetJsonSection(*rtl_if_map, {"NRESET"}, true); nlohmann::json* reset_domains = GetJsonSection(*rtl_if_map, {"CUSTOMRESET"}, true); + nlohmann::json* input_ports = GetJsonSection(*rtl_if_map, + {"INPUT", "INPORT", "INPUTS", "INPORTS", "INPUT-PORT", "INPUT-PORTS"}, false); if (clock_domains) { ENSURE(clock_domains->is_array() || clock_domains->is_string() || clock_domains->is_object(), @@ -776,6 +778,17 @@ VerilogRefinementMap::VerilogRefinementMap( } } // if is_object } // if reset custom domain + if(input_ports) { + ENSURE(input_ports->is_object(), "Expecting `input-port` to be a map of string->string"); + for (const auto& n_l_pair : input_ports->items()) { + ENSURE(n_l_pair.value().is_string(), "Expecting `input-port` to be a map of string->string"); + auto rfe = ParseRfMapExprJson( n_l_pair.value() ); + auto port_name = n_l_pair.key(); + ENSURE(rtl_interface_connection.input_port_connection.find(port_name) == rtl_interface_connection.input_port_connection.end(), + ("Error: port name " + port_name + " has been assigned already") ); + rtl_interface_connection.input_port_connection.emplace(port_name, rfe); + } + } } // interface map { // reset section parsing diff --git a/src/vtarget-out/directive.cc b/src/vtarget-out/directive.cc index 734aa8b0f..ea5009f4f 100644 --- a/src/vtarget-out/directive.cc +++ b/src/vtarget-out/directive.cc @@ -187,9 +187,16 @@ void IntefaceDirectiveRecorder::RegisterInterface(const SignalInfoBase& vlg_sig, << "Expecting `" << short_name << "` to be input of width 1"; mod_inst_rec.insert( {short_name, inf_connector_t({inf_dir_t::CLOCK, "clk"})}); - } else + } else if (refstr == "**CUSTOM_INPUT**") { + ILA_CHECK(is_input) << "Cannot assign to output port : " << short_name; + ILA_ERROR_IF(IN(short_name, mod_inst_rec)) << short_name << " has already been connected"; + internal_wires.push_back({"__VLG_II_" + short_name, width}); + mod_inst_rec.insert( + {short_name, + inf_connector_t({inf_dir_t::INPUT, "__VLG_II_" + short_name})}); + } else { ILA_ASSERT(false) << "Implementation error. Should not be reachable."; - // decide how to connect and signals to create + } // decide how to connect and signals to create return; } // IntefaceDirectiveRecorder::RegisterInterface diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index 3d2448586..83573e713 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -103,6 +103,7 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { vlg_wrapper.add_reg("__STARTED__", 1); rfmap_add_internal_reg("__STARTED__", 1); + rfmap_add_replacement("afterdecode", "__STARTED__"); vlg_wrapper.add_stmt("always @(posedge clk) begin"); vlg_wrapper.add_stmt("if (rst) __STARTED__ <= 0;"); vlg_wrapper.add_stmt( diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index 41953a2d3..30b1bd9f4 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -305,6 +305,7 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_input_output() { refinement_map.rtl_interface_connection.clock_domain_defs.at("default"); const auto& reset_pins = refinement_map.rtl_interface_connection.reset_pins; const auto& nreset_pins = refinement_map.rtl_interface_connection.nreset_pins; + const auto& custom_input = refinement_map.rtl_interface_connection.input_port_connection; for (auto&& name_siginfo_pair : vlg_inputs) { std::string refstr = "**KEEP**"; if (IN(name_siginfo_pair.first, clock_pins)) @@ -313,6 +314,14 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_input_output() { refstr = "**RESET**"; else if (IN(name_siginfo_pair.first, nreset_pins)) refstr = "**NRESET**"; + else if (IN(name_siginfo_pair.first, custom_input)) { + auto short_name = name_siginfo_pair.first; + add_wire_assign_assumption( "__VLG_II_" + short_name, custom_input.at(name_siginfo_pair.first), + "vlg_input_wire"); + rfmap_add_internal_wire("__VLG_II_" + short_name, + name_siginfo_pair.second.get_width() ); + refstr = "**CUSTOM_INPUT**"; + } _idr.RegisterInterface(name_siginfo_pair.second, refstr); } diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 6af55c8a1..0676c7b0b 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -157,6 +157,11 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { } // ConstructWrapper_add_uf_constraints void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { + for (const auto& delay_unit : refinement_map.aux_delays) { + std::cout << delay_unit.first << " : expr = " + << (delay_unit.second.signal) << std::endl; + } + for (const auto& delay_unit : refinement_map.aux_delays) { const auto& name = delay_unit.first; const auto& du = delay_unit.second; diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json index 08f42150e..87218194e 100644 --- a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json @@ -12,7 +12,10 @@ "rtl-interface-connection" : { "CLOCK" : "clk", - "RESET" : "rst" + "RESET" : "rst", + "INPUT" : { + "dummy_read_rf" : "#dummy_read_rf#" + } }, "monitor" :{ @@ -43,7 +46,7 @@ " if (__START__) ref_test <= 0;", " else if (__STARTED__ && !__ENDED__ && stage_tracker == 1) ref_test <= RTL.registers[0] + 1;", "end"], - "defs" :[ ["ref_test", 2, "reg"] ], + "defs" :[ ["ref_test", 2, "reg"], ["dummy_read_rf", 2, "wire"] ], "refs" :[ "RTL.registers[0]" ] }, @@ -66,11 +69,15 @@ // pipeline tracker "ppl_stage" : { "template" : "phase tracker", + "event-alias" : { + "dsignal" : "ppl_stage_ex ## [1:$] ppl_stage_wb ##1 (1'b1)" + }, + "aux-var" : [["cnt", 2, "reg"]], "rules" : [ { // "name" : "ex", "enter" : {"event" : "#decode#"}, - "exit" : {"event" : "1"} + "exit" : {"event" : "1", "action": " cnt <= RTL.reg_0_w_stage "} }, { // From cb2ae2ec95d0ede7ef784b6279d03d96f12e674d Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 24 Oct 2021 08:06:27 +0800 Subject: [PATCH 56/78] vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 2a478edeb..7732eb0f2 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 2a478edeb2841c793ea347b5cb6a98c9e7c4382d +Subproject commit 7732eb0f2233e060abfd56ef03a69571615bfc0d From 6f90197316dde754e7d00b10763248e418f8cf55 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 24 Oct 2021 08:11:41 +0800 Subject: [PATCH 57/78] vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 7732eb0f2..0aeb63535 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 7732eb0f2233e060abfd56ef03a69571615bfc0d +Subproject commit 0aeb63535e0a8d9a60d696881cafc99cdc195c30 From 133ed8b84e23b4c8bfa5c8ad3bd8e628f5191f3b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 24 Oct 2021 22:46:05 +0800 Subject: [PATCH 58/78] fix cmake install --- include/ilang/rfmap-in/rfmap_typecheck.h | 12 +- src/CMakeLists.txt | 5 + src/rfmap-in/rfexpr_to_smt.cc | 6 +- src/rfmap-in/rfmap_typecheck.cc | 286 +++++++++--------- src/vtarget-out/directive.cc | 1 + src/vtarget-out/single_target_as.cc | 87 +++--- src/vtarget-out/single_target_cond.cc | 2 + src/vtarget-out/single_target_connect.cc | 5 +- .../single_target_inv_syn_support.cc | 4 + src/vtarget-out/single_target_misc.cc | 26 +- .../vpipe/rfmap/vmap-rfmap-pvholder.json | 9 +- test/unit-data/vpipe/simple_pipe.v | 13 +- test/unit-data/vpipe/simple_pipe_wrong.v | 10 +- 13 files changed, 253 insertions(+), 213 deletions(-) diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index ae119d500..6d6a369be 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -108,8 +108,8 @@ class RfExprAstUtility { static RfVarTypeOrig GetType(const RfExpr& in); /// will modify where the pointer is pointing to /// because we will be creating new rfexpr - static void TraverseRfExpr(RfExpr& inout, - std::function func); + static RfExpr TraverseRfExpr(const RfExpr& inout, + std::function func); /// check to make sure no null ptr static void RfMapNoNullNode(const RfExpr& in); }; @@ -181,7 +181,7 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap, // this should include phase-tracker (m,v,alias) // ... ? - void TraverseAllRfExpr(std::function func); + void TraverseAllRfExpr(std::function func); // this function is used in // (1) value holder/delay : width determination @@ -209,7 +209,7 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap, /// deal with condition map void TraverseCondMap(SingleVarMap& inout, - std::function func); + std::function func); private: // help with naming @@ -217,8 +217,8 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap, std::string new_id(); // helper for AST traversal - void collect_inline_value_recorder_func(RfExpr& inout); - void collect_inline_delay_func(RfExpr& inout); + RfExpr collect_inline_value_recorder_func(const RfExpr& inout); + RfExpr collect_inline_delay_func(const RfExpr& inout); // this function uses the above two and the void CollectInlineDelayValueHolder(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a03ca3786..6043b117f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -283,6 +283,11 @@ else() DESTINATION ${ILANG_INCLUDE_INSTALL_DIR}/ilang ) + install( + FILES ${ILANG_INCLUDE_BUILD_DIR}/ilang/rtl_verify.h + DESTINATION ${ILANG_INCLUDE_INSTALL_DIR}/ilang + ) + install( FILES ${ILANG_INCLUDE_BUILD_DIR}/ilang/config.h DESTINATION ${ILANG_INCLUDE_INSTALL_DIR}/ilang diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc index 5a04ce4d2..6863d3d6b 100644 --- a/src/rfmap-in/rfexpr_to_smt.cc +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -125,6 +125,10 @@ static std::string type_convert(SmtType out_tp, SmtType in_tp, } if (in_tp.is_bool() && out_tp.is_bv()) { + auto retstr = "(ite " + in + " #b1 #b0)"; + ILA_CHECK(out_tp.unified_width() > 0); + if(out_tp.unified_width() == 1) + return retstr; return extend_width("(ite " + in + " #b1 #b0)", 1, out_tp.unified_width()); } @@ -419,7 +423,7 @@ std::string RfExpr2Smt::to_smt2(const RfExpr& in, SmtType expected_type) { if (op_ == verilog_expr::voperator::REPEAT) { ILA_ASSERT(in->get_child_cnt() == 2); unsigned ntimes; - if (!_compute_const(in->child(0), ntimes)) + if (!_compute_const(in->get_child().at(0), ntimes)) throw verilog_expr::VexpException( verilog_expr::ExceptionCause::UnknownNumberSmtTranslation); ILA_ASSERT(ntimes > 0); diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index a64f01cc1..d20dd819a 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -69,73 +69,79 @@ RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar(const RfExpr& in) { return in; } // else is op - auto ret_copy = std::make_shared(*in); - for (size_t idx = 0; idx < ret_copy->get_child_cnt(); ++idx) { - ret_copy->child(idx) = ReplacingRtlIlaVar(ret_copy->get_child().at(idx)); - } // for each child - return ret_copy; + std::vector retchild; + for (size_t idx = 0; idx < in->get_child_cnt(); ++idx) { + retchild.push_back(ReplacingRtlIlaVar(in->get_child().at(idx))); + } + auto ret = in->MakeCopyWithNewChild(retchild); + ret->set_annotation(in->get_annotation()); + return ret; } // AnnotateSignalsAndCollectRtlVars -void TypedVerilogRefinementMap::collect_inline_value_recorder_func( - RfExpr& inout) { - if (inout->get_op() == verilog_expr::voperator::AT) { - auto recorder_name = new_id() + "recorder"; - auto new_node = verilog_expr::VExprAst::MakeVar(recorder_name); - - verilog_expr::VExprAst::VExprAstPtrVec child(inout->get_child()); - ValueRecorder tmp_value_recorder; - tmp_value_recorder.width = 0; - tmp_value_recorder.value = child.at(0); - // TODO: deal with value@CLK.n - if (child.at(1)->is_constant()) { - // deal with value@0 - auto new_cond = verilog_expr::VExprAst::MakeBinaryAst( - verilog_expr::voperator::L_EQ, - verilog_expr::VExprAst::MakeVar("__CYCLE_CNT__"), child.at(1)); - tmp_value_recorder.condition = new_cond; - } else - tmp_value_recorder.condition = child.at(1); - value_recorder.emplace(recorder_name, tmp_value_recorder); - inout = new_node; // rewrite the node - } +RfExpr TypedVerilogRefinementMap::collect_inline_value_recorder_func( + const RfExpr& in) { + if (in->get_op() != verilog_expr::voperator::AT) + return in; + + auto recorder_name = new_id() + "recorder"; + auto new_node = verilog_expr::VExprAst::MakeVar(recorder_name); + + verilog_expr::VExprAst::VExprAstPtrVec child(in->get_child()); + ValueRecorder tmp_value_recorder; + tmp_value_recorder.width = 0; + tmp_value_recorder.value = child.at(0); + // TODO: deal with value@CLK.n + if (child.at(1)->is_constant()) { + // deal with value@0 + auto new_cond = verilog_expr::VExprAst::MakeBinaryAst( + verilog_expr::voperator::L_EQ, + verilog_expr::VExprAst::MakeVar("__CYCLE_CNT__"), child.at(1)); + tmp_value_recorder.condition = new_cond; + } else + tmp_value_recorder.condition = child.at(1); + value_recorder.emplace(recorder_name, tmp_value_recorder); + return new_node; // rewrite the node } // collect_inline_value_recorder_func -void TypedVerilogRefinementMap::collect_inline_delay_func(RfExpr& inout) { - if (inout->get_op() == voperator::DELAY) { - assert(inout->get_parameter().size() == inout->get_str_parameter().size()); - assert(inout->get_child().size() == 1 || inout->get_child().size() == 2); - assert(inout->get_parameter().size() == 1 || - inout->get_parameter().size() == 2); - - auto delay_name = new_id() + "delay"; - auto new_node = VExprAst::MakeVar(delay_name); - - if (inout->get_parameter().size() == 1) { - // Single a ##n - int delay = inout->get_parameter().at(0); - aux_delays.emplace(delay_name, - SignalDelay(inout->get_child().at(0), delay)); - std::cout << "SingleDelay:" <get_child().at(0) <get_parameter().size() == 2 - // RANGE/INF a ##[n,m] / ##[n,0] 0 represents $ - int delay = inout->get_parameter().at(0); - int delay_upper = inout->get_parameter().at(1); - aux_delays.emplace(delay_name, SignalDelay(inout->get_child().at(0), - delay, delay_upper)); - std::cout << "2Delay:" <get_child().at(0) <get_op() != voperator::DELAY) + return in; + // else + assert(in->get_parameter().size() == in->get_str_parameter().size()); + assert(in->get_child().size() == 1 || in->get_child().size() == 2); + assert(in->get_parameter().size() == 1 || + in->get_parameter().size() == 2); + + auto delay_name = new_id() + "delay"; + auto new_node = VExprAst::MakeVar(delay_name); + + if (in->get_parameter().size() == 1) { + // Single a ##n + int delay = in->get_parameter().at(0); + aux_delays.emplace(delay_name, + SignalDelay(in->get_child().at(0), delay)); + // std::cout << "SingleDelay:" <get_child().at(0) <get_parameter().size() == 2 + // RANGE/INF a ##[n,m] / ##[n,0] 0 represents $ + int delay = in->get_parameter().at(0); + int delay_upper = in->get_parameter().at(1); + aux_delays.emplace(delay_name, SignalDelay(in->get_child().at(0), + delay, delay_upper)); + // std::cout << "2Delay:" <get_child().at(0) <get_child().size() == 1) { - inout = new_node; - } else { - assert(inout->get_child().size() == 2); - auto tmp_node = VExprAst::MakeBinaryAst(voperator::L_AND, new_node, - inout->get_child().at(1)); - inout = tmp_node; - } - std::cout << "-->:" << inout <get_child().size() == 1) { + ret = new_node; + } else { + assert(in->get_child().size() == 2); + auto tmp_node = VExprAst::MakeBinaryAst(voperator::L_AND, new_node, + in->get_child().at(1)); + ret = tmp_node; } + // std::cout << "-->:" << ret < void { - this->collect_inline_delay_func(inout); + TraverseAllRfExpr([this](const RfExpr& in) -> RfExpr { + return this->collect_inline_delay_func(in); }); - TraverseAllRfExpr([this](RfExpr& inout) -> void { - this->collect_inline_value_recorder_func(inout); + TraverseAllRfExpr([this](const RfExpr& in) -> RfExpr { + return this->collect_inline_value_recorder_func(in); }); } @@ -207,25 +213,25 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { } // CollectInternallyDefinedVars void TypedVerilogRefinementMap::TraverseCondMap( - SingleVarMap& inout, std::function func) { + SingleVarMap& inout, std::function func) { if (inout.single_map) - TraverseRfExpr(inout.single_map, func); + inout.single_map = TraverseRfExpr(inout.single_map, func); else for (auto& c : inout.cond_map) { - TraverseRfExpr(c.first, func); - TraverseRfExpr(c.second, func); + c.first = TraverseRfExpr(c.first, func); + c.second = TraverseRfExpr(c.second, func); } } // TraverseCondMap void TypedVerilogRefinementMap::TraverseAllRfExpr( - std::function func) { + std::function func) { for (auto& sv : ila_state_var_map) { if (sv.second.type == IlaVarMapping::StateVarMapType::SINGLE) - TraverseRfExpr(sv.second.single_map.single_map, func); + sv.second.single_map.single_map = TraverseRfExpr(sv.second.single_map.single_map, func); else if (sv.second.type == IlaVarMapping::StateVarMapType::CONDITIONAL) { for (auto& c : sv.second.single_map.cond_map) { - TraverseRfExpr(c.first, func); - TraverseRfExpr(c.second, func); + c.first = TraverseRfExpr(c.first, func); + c.second = TraverseRfExpr(c.second, func); } } else { // extern map for (auto& m : sv.second.externmem_map) { @@ -241,60 +247,60 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr( for (auto& sv : ila_input_var_map) { if (sv.second.type == IlaVarMapping::StateVarMapType::SINGLE) - TraverseRfExpr(sv.second.single_map.single_map, func); + sv.second.single_map.single_map = TraverseRfExpr(sv.second.single_map.single_map, func); else /* if(sv.second.type == IlaVarMapping::StateVarMapType::CONDITIONAL) */ { for (auto& c : sv.second.single_map.cond_map) { - TraverseRfExpr(c.first, func); - TraverseRfExpr(c.second, func); + c.first = TraverseRfExpr(c.first, func); + c.second = TraverseRfExpr(c.second, func); } } } // input var for (auto& ufa : uf_application) { for (auto& fapp : ufa.second.func_applications) { - TraverseRfExpr(fapp.result_map, func); + fapp.result_map = TraverseRfExpr(fapp.result_map, func); for (auto& a : fapp.arg_map) - TraverseRfExpr(a, func); + a = TraverseRfExpr(a, func); } } // uf application for (auto& a : assumptions) - TraverseRfExpr(a, func); + a = TraverseRfExpr(a, func); for (auto& a : additional_mapping) - TraverseRfExpr(a, func); + a = TraverseRfExpr(a, func); for (auto& ptracker : phase_tracker) { for (auto& a : ptracker.second.event_alias) - TraverseRfExpr(a.second, func); + a.second = TraverseRfExpr(a.second, func); for (auto& r : ptracker.second.rules) { - TraverseRfExpr(r.enter_rule, func); + r.enter_rule = TraverseRfExpr(r.enter_rule, func); if(r.exit_rule) - TraverseRfExpr(r.exit_rule, func); + r.exit_rule = TraverseRfExpr(r.exit_rule, func); for (auto& act : r.enter_action) - TraverseRfExpr(act.RHS, func); + act.RHS = TraverseRfExpr(act.RHS, func); for (auto& act : r.exit_action) - TraverseRfExpr(act.RHS, func); + act.RHS = TraverseRfExpr(act.RHS, func); } } // phase tracker for (auto& pv : value_recorder) { - TraverseRfExpr(pv.second.condition, func); - TraverseRfExpr(pv.second.value, func); + pv.second.condition = TraverseRfExpr(pv.second.condition, func); + pv.second.value = TraverseRfExpr(pv.second.value, func); } // ALERT: do not handle customized recorder for (auto& instcond : inst_complete_cond) { if (instcond.second.type == InstructionCompleteCondition::ConditionType::SIGNAL) - TraverseRfExpr(instcond.second.ready_signal, func); + instcond.second.ready_signal = TraverseRfExpr(instcond.second.ready_signal, func); for (auto& cond : instcond.second.start_condition) - TraverseRfExpr(cond, func); + cond = TraverseRfExpr(cond, func); } for (auto& a : global_invariants) - TraverseRfExpr(a, func); + a = TraverseRfExpr(a, func); for (auto& p_rf: rtl_interface_connection.input_port_connection) { - TraverseRfExpr(p_rf.second, func); + p_rf.second = TraverseRfExpr(p_rf.second, func); } } // TraverseAllRfExpr @@ -430,7 +436,7 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { unsigned nchild = in->get_child_cnt(); unsigned maxw = 0; for (size_t idx = 0; idx < nchild; idx++) { - RfMapVarType t = TypeInferTravserRfExpr(in->child(idx)); + RfMapVarType t = TypeInferTravserRfExpr(in->get_child().at(idx)); if (t.is_bv()) maxw = std::max(maxw, t.unified_width()); } @@ -441,7 +447,7 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { in->get_op() == verilog_expr::voperator::LSR || in->get_op() == verilog_expr::voperator::AT) { // the left type assert(in->get_child_cnt() == 2); - return TypeInferTravserRfExpr(in->child(0)); + return TypeInferTravserRfExpr(in->get_child().at(0)); } else if (in->get_op() == verilog_expr::voperator::DELAY) { // arg 1: width of first // arg 2: width is 1 !!! @@ -450,7 +456,7 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { return RfMapVarType(1); // set return type to be the same as the first one - return TypeInferTravserRfExpr(in->child(0)); + return TypeInferTravserRfExpr(in->get_child().at(0)); } else if (in->get_op() == verilog_expr::voperator::GTE || in->get_op() == verilog_expr::voperator::LTE || in->get_op() == verilog_expr::voperator::GT || @@ -464,7 +470,7 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { in->get_op() == verilog_expr::voperator::L_OR) { return RfMapVarType(1); } else if (in->get_op() == verilog_expr::voperator::INDEX) { - RfMapVarType child_type = TypeInferTravserRfExpr(in->child(0)); + RfMapVarType child_type = TypeInferTravserRfExpr(in->get_child().at(0)); if (child_type.is_array()) return RfMapVarType(child_type.unified_width()); // data width // TODO: check index within ? @@ -475,7 +481,7 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { in->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { assert(in->get_child().size() == 3); unsigned diff; - bool succ = _compute_const(in->child(2), diff /*ref*/); + bool succ = _compute_const(in->get_child().at(2), diff /*ref*/); // TODO: check index within ? if (succ) return RfMapVarType(diff); @@ -484,8 +490,8 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { assert(in->get_child_cnt() == 3); unsigned l, r; - bool succ = _compute_const(in->child(1), l /*ref*/); - succ = succ && _compute_const(in->child(2), r /*ref*/); + bool succ = _compute_const(in->get_child().at(1), l /*ref*/); + succ = succ && _compute_const(in->get_child().at(2), r /*ref*/); if (!succ) return RfMapVarType(); // TODO: check width! @@ -493,10 +499,10 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { } else if (in->get_op() == verilog_expr::voperator::STORE_OP) { // TODO: check width! // actually not implemented - return TypeInferTravserRfExpr(in->child(0)); + return TypeInferTravserRfExpr(in->get_child().at(0)); } else if (in->get_op() == verilog_expr::voperator::TERNARY) { - auto left = TypeInferTravserRfExpr(in->child(1)); - auto right = TypeInferTravserRfExpr(in->child(2)); + auto left = TypeInferTravserRfExpr(in->get_child().at(1)); + auto right = TypeInferTravserRfExpr(in->get_child().at(2)); if (left.is_array() || right.is_array()) return left; // TODO: check compatibility return RfMapVarType( @@ -507,7 +513,7 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { unsigned nchild = in->get_child_cnt(); unsigned sumw = 0; for (size_t idx = 0; idx < nchild; idx++) { - RfMapVarType t = TypeInferTravserRfExpr(in->child(idx)); + RfMapVarType t = TypeInferTravserRfExpr(in->get_child().at(idx)); if (t.is_bv()) sumw += t.unified_width(); else @@ -517,9 +523,9 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { } else if (in->get_op() == verilog_expr::voperator::REPEAT) { assert(in->get_child_cnt() == 2); unsigned ntimes; - if (!_compute_const(in->child(0), ntimes)) + if (!_compute_const(in->get_child().at(0), ntimes)) return RfMapVarType(); - auto tp = TypeInferTravserRfExpr(in->child(1)); + auto tp = TypeInferTravserRfExpr(in->get_child().at(1)); return RfMapVarType(tp.unified_width() * ntimes); } ILA_ASSERT(false) << "BUG: Operator " << int(in->get_op()) @@ -581,7 +587,7 @@ bool RfExprAstUtility::HasArrayVar(const RfExpr& in, } bool has_array = false; for (size_t idx = 0; idx < in->get_child_cnt(); idx++) { - has_array = has_array || HasArrayVar(in->child(idx), array_var); + has_array = has_array || HasArrayVar(in->get_child().at(idx), array_var); } return has_array; } @@ -590,41 +596,39 @@ void RfExprAstUtility::RfMapNoNullNode(const RfExpr& in) { ILA_NOT_NULL(in); size_t cnt = in->get_child_cnt(); for (size_t idx = 0; idx < cnt; ++idx) - RfMapNoNullNode(in->child(idx)); + RfMapNoNullNode(in->get_child().at(idx)); } -void RfExprAstUtility::TraverseRfExpr(RfExpr& inout, - std::function func) { - ILA_NOT_NULL(inout); - // DFS -- Note: we need to call func on the parent's child - // and make sure it runs the first +RfExpr RfExprAstUtility::TraverseRfExpr(const RfExpr& in, + std::function func) { + ILA_NOT_NULL(in); + std::vector> child_stack; + child_stack.push_back({}); + child_stack.push_back({}); std::vector> parent_stack; - parent_stack.push_back(std::make_pair(inout, 0U)); + parent_stack.push_back(std::make_pair(in, 0U)); while (!parent_stack.empty()) { auto& lastlv = parent_stack.back(); auto cnt = lastlv.first->get_child_cnt(); auto& idx = lastlv.second; if (idx >= cnt) { + auto new_c = lastlv.first->MakeCopyWithNewChild(child_stack.back()); + auto new_node = func(new_c); + new_node->set_annotation(lastlv.first->get_annotation()); + child_stack.pop_back(); + child_stack.back().push_back(new_node); parent_stack.pop_back(); - if (!parent_stack.empty()) { - // refer to parent - func(parent_stack.back().first->child(parent_stack.back().second)); + if(!parent_stack.empty()) ++parent_stack.back().second; - } continue; - } else { - // enter c[idx] - ILA_CHECK(lastlv.first->get_child_cnt() != 0); - // if (lastlv.first->get_child_cnt() == 0) { - // ILA_CHECK(false) << "Should not be reachable!"; - // func(lastlv.first->child(idx)); - // ++idx; - // } else { - parent_stack.push_back(std::make_pair(lastlv.first->child(idx), 0U)); - //} - } + } // else + ILA_CHECK(lastlv.first->get_child_cnt() != 0); + parent_stack.push_back(std::make_pair(lastlv.first->get_child().at(idx), 0U)); + child_stack.push_back({}); } // end of while - func(inout); + ILA_CHECK(child_stack.size() == 1); + ILA_CHECK(child_stack.at(0).size() == 1); + return child_stack.at(0).at(0); } // TraverseRfExpr bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr& in) { @@ -670,7 +674,7 @@ void TypeAnalysisUtility::AnnotateType(const RfExpr& inout) { } // end if no annotation } else { // op for (size_t idx = 0; idx < inout->get_child_cnt(); ++idx) - AnnotateType(inout->child(idx)); + AnnotateType(inout->get_child().at(idx)); infer_type_based_on_op_child(inout); // for each child } // end if-else- op @@ -712,7 +716,7 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { unsigned maxw = 0; for (size_t idx = 0; idx < nchild; idx++) { RfMapVarType t = - inout->child(idx)->get_annotation()->type; + inout->get_child().at(idx)->get_annotation()->type; if (t.is_bv()) maxw = std::max(maxw, t.unified_width()); } @@ -728,7 +732,7 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { inout->get_op() == verilog_expr::voperator::LSR || inout->get_op() == verilog_expr::voperator::AT) { // the left type assert(inout->get_child_cnt() == 2); - inout->set_annotation(inout->child(0)->get_annotation()); + inout->set_annotation(inout->get_child().at(0)->get_annotation()); return; } else if (inout->get_op() == verilog_expr::voperator::DELAY) { // arg 1: width of first @@ -742,7 +746,7 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { } // set return type to be the same as the first one - inout->set_annotation(inout->child(0)->get_annotation()); + inout->set_annotation(inout->get_child().at(0)->get_annotation()); return; } else if (inout->get_op() == verilog_expr::voperator::GTE || @@ -762,7 +766,7 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { return; } else if (inout->get_op() == verilog_expr::voperator::INDEX) { RfMapVarType child_type = - inout->child(0)->get_annotation()->type; + inout->get_child().at(0)->get_annotation()->type; auto new_annotation = std::make_shared(); if (child_type.is_array()) @@ -776,7 +780,7 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { inout->get_op() == verilog_expr::voperator::IDX_PRT_SEL_MINUS) { assert(inout->get_child().size() == 3); unsigned diff = 0; - bool succ = _compute_const(inout->child(2), diff /*ref*/); + bool succ = _compute_const(inout->get_child().at(2), diff /*ref*/); ILA_ASSERT(succ); auto new_annotation = std::make_shared(); @@ -790,8 +794,8 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { assert(inout->get_child_cnt() == 3); unsigned l, r; - bool succ = _compute_const(inout->child(1), l /*ref*/); - succ = succ && _compute_const(inout->child(2), r /*ref*/); + bool succ = _compute_const(inout->get_child().at(1), l /*ref*/); + succ = succ && _compute_const(inout->get_child().at(2), r /*ref*/); ILA_ASSERT(succ); auto new_annotation = std::make_shared(); @@ -800,11 +804,11 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { return; } else if (inout->get_op() == verilog_expr::voperator::STORE_OP) { - inout->set_annotation(inout->child(0)->get_annotation()); + inout->set_annotation(inout->get_child().at(0)->get_annotation()); return; } else if (inout->get_op() == verilog_expr::voperator::TERNARY) { - inout->set_annotation(inout->child(1)->get_annotation()); + inout->set_annotation(inout->get_child().at(1)->get_annotation()); return; } else if (inout->get_op() == verilog_expr::voperator::FUNCTION_APP) { ILA_ASSERT(false); @@ -817,7 +821,7 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { unsigned sumw = 0; for (size_t idx = 0; idx < nchild; idx++) { RfMapVarType t = - (inout->child(idx)->get_annotation()->type); + (inout->get_child().at(idx)->get_annotation()->type); sumw += t.unified_width(); } auto new_annotation = std::make_shared(); @@ -827,9 +831,9 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { } else if (inout->get_op() == verilog_expr::voperator::REPEAT) { assert(inout->get_child_cnt() == 2); unsigned ntimes; - if (!_compute_const(inout->child(0), ntimes)) + if (!_compute_const(inout->get_child().at(0), ntimes)) ILA_ASSERT(false); - auto tp = (inout->child(1)->get_annotation()->type); + auto tp = (inout->get_child().at(1)->get_annotation()->type); auto new_annotation = std::make_shared(); new_annotation->type = RfMapVarType(tp.unified_width() * ntimes); diff --git a/src/vtarget-out/directive.cc b/src/vtarget-out/directive.cc index ea5009f4f..6e11f2631 100644 --- a/src/vtarget-out/directive.cc +++ b/src/vtarget-out/directive.cc @@ -69,6 +69,7 @@ void IntefaceDirectiveRecorder::VlgAddTopInteface( } for (auto&& w : internal_wires) { gen.add_wire(w.first, w.second, true); + gen.add_output(w.first, w.second); } } diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index 643ec8e73..78028b5e7 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -128,26 +128,36 @@ static std::string const_to_unified_str(const rfmap::RfExpr& in) { return IntToStrCustomBase(n, 10, false); } -static void find_and_replace_array_const( - rfmap::RfExpr& expr, +static std::string GetVlg(const rfmap::RfExpr & e) { + try { + return e->to_verilog(); + } catch (...) { + ILA_ERROR<< "Cannot convert r-expr : " << e; + } + return "(error)"; +} + +static rfmap::RfExpr find_and_replace_array_const( + const rfmap::RfExpr& expr, std::map& array_const_set, // RTL.a.b.c[const] std::unordered_map& extra_wire) { auto fd_rp_array_const_func = [&array_const_set, - &extra_wire](rfmap::RfExpr& inout) { - if (inout->get_op() == verilog_expr::voperator::INDEX && - inout->get_child_cnt() == 2 && inout->child(0)->is_var() && - inout->child(1)->is_constant() && - rfmap::RfExprAstUtility::GetType(inout->child(0)).type.is_array()) { - auto hier_name = inout->child(0)->to_verilog(); - auto cnst = const_to_unified_str(inout->child(1)); + &extra_wire](const rfmap::RfExpr& in) -> rfmap::RfExpr { + if (in->get_op() == verilog_expr::voperator::INDEX && + in->get_child_cnt() == 2 && in->get_child().at(0)->is_var() && + in->get_child().at(1)->is_constant() && + rfmap::RfExprAstUtility::GetType(in->get_child().at(0)).type.is_array()) { + auto hier_name = GetVlg(in->get_child().at(0)); + auto cnst = const_to_unified_str(in->get_child().at(1)); if (cnst == "error") // if cannot convert - return; + return in; auto new_name = ReplaceAll(hier_name, ".", "__DOT__"); new_name += "_" + cnst + "_"; + rfmap::RfExpr ret; if (array_const_set.find(new_name) != array_const_set.end()) { - inout = array_const_set.at(new_name); - return; + ret = array_const_set.at(new_name); + return ret; } const auto last_dot_pos = hier_name.rfind("."); @@ -157,7 +167,7 @@ static void find_and_replace_array_const( hier_name.substr(last_dot_pos + 1) + "[" + cnst + "]"; ILA_CHECK(!IN(new_name, extra_wire)); - auto tp = rfmap::RfExprAstUtility::GetType(inout->child(0)).type; + auto tp = rfmap::RfExprAstUtility::GetType(in->get_child().at(0)).type; auto w = tp.unified_width(); extra_wire.emplace(new_name, @@ -170,12 +180,14 @@ static void find_and_replace_array_const( new_tp->var_ref_type = rfmap::TypeAnnotation::VARTYPE::INTERNAL; new_tp->type = rfmap::RfMapVarType(w); repl->set_annotation(new_tp); - inout = repl; + ret = repl; array_const_set.emplace(new_name, repl); - } + return ret; + } // else + return in; }; - rfmap::RfExprAstUtility::TraverseRfExpr(expr, fd_rp_array_const_func); + return rfmap::RfExprAstUtility::TraverseRfExpr(expr, fd_rp_array_const_func); } // find_and_replace_array_const void VlgSglTgtGen::add_wire_assign_assumption(const std::string& varname, @@ -198,34 +210,34 @@ void VlgSglTgtGen:: const auto& vn = std::get<1>(dspt_vn_rfexpr_eq); const auto& rfe = std::get<2>(dspt_vn_rfexpr_eq); - ILA_DLOG("VTG.ReplWireEq") << vn << " := " << rfe->to_verilog(); + ILA_DLOG("VTG.ReplWireEq") << vn << " := " << GetVlg(rfe); std::get<3>(dspt_vn_rfexpr_eq) = ReplExpr(rfmap_eq(rfmap_var(vn), rfe)); } // for each assign/assumption for (auto& dspt_aspt : all_assumptions) { for (auto& aspt : dspt_aspt.second) { - ILA_DLOG("VTG.ReplAssume") << aspt->to_verilog(); + ILA_DLOG("VTG.ReplAssume") << GetVlg(aspt); aspt = ReplExpr(aspt); } } for (auto& dspt_asst : all_assertions) { for (auto& asst : dspt_asst.second) { - ILA_DLOG("VTG.ReplAssert") << asst->to_verilog(); + ILA_DLOG("VTG.ReplAssert") << GetVlg(asst); asst = ReplExpr(asst); } } for (auto& dspt_asst : all_sanity_assertions) { for (auto& asst : dspt_asst.second) { - ILA_DLOG("VTG.ReplAssert") << asst->to_verilog(); + ILA_DLOG("VTG.ReplAssert") << GetVlg(asst); asst = ReplExpr(asst); } } for (auto& dspt_cvrs : all_covers) { for (auto& cvrs : dspt_cvrs.second) { - ILA_DLOG("VTG.ReplAssert") << cvrs->to_verilog(); + ILA_DLOG("VTG.ReplAssert") << GetVlg(cvrs); cvrs = ReplExpr(cvrs); } } @@ -233,19 +245,19 @@ void VlgSglTgtGen:: if (is_jg) { for (auto& dspt_aspt : all_assumptions) { for (auto& aspt : dspt_aspt.second) - add_a_direct_assumption(aspt->to_verilog(), dspt_aspt.first); + add_a_direct_assumption(GetVlg(aspt), dspt_aspt.first); } for (auto& dspt_asst : all_assertions) { for (auto& asst : dspt_asst.second) - add_a_direct_assertion(asst->to_verilog(), dspt_asst.first); + add_a_direct_assertion(GetVlg(asst), dspt_asst.first); } for (auto& dspt_asst : all_sanity_assertions) { for (auto& asst : dspt_asst.second) - add_a_direct_sanity_assertion(asst->to_verilog(), dspt_asst.first); + add_a_direct_sanity_assertion(GetVlg(asst), dspt_asst.first); } for (auto& dspt_cvrs : all_covers) { for (auto& cvr : dspt_cvrs.second) - add_a_direct_cover_check(cvr->to_verilog(), dspt_cvrs.first); + add_a_direct_cover_check(GetVlg(cvr), dspt_cvrs.first); } @@ -253,7 +265,7 @@ void VlgSglTgtGen:: const auto& vn = std::get<1>(dspt_vn_rfexpr_eq); const auto& eq = std::get<3>(dspt_vn_rfexpr_eq); // we know it is eq(vn, rhs); - vlg_wrapper.add_assign_stmt(vn, eq->child(1)->to_verilog()); + vlg_wrapper.add_assign_stmt(vn, GetVlg(eq->get_child().at(1))); } return; } // end of is_jg (will not continue if using jg) @@ -287,20 +299,20 @@ void VlgSglTgtGen:: // below will also update `rtl_extra_wire` for (auto& dspt_aspt : all_assumptions) { for (auto& aspt : dspt_aspt.second) { - find_and_replace_array_const(aspt, array_const_set, rtl_extra_wire); + aspt = find_and_replace_array_const(aspt, array_const_set, rtl_extra_wire); // this will find array[const] and replace as a word reference } } for (auto& dspt_asst : all_assertions) { for (auto& asst : dspt_asst.second) { - find_and_replace_array_const(asst, array_const_set, rtl_extra_wire); + asst = find_and_replace_array_const(asst, array_const_set, rtl_extra_wire); } } for (auto& dspt_vn_rfexpr_eq : assign_or_assumptions) { auto& eq = std::get<3>(dspt_vn_rfexpr_eq); - find_and_replace_array_const(eq, array_const_set, rtl_extra_wire); + eq = find_and_replace_array_const(eq, array_const_set, rtl_extra_wire); } // last step @@ -312,7 +324,7 @@ void VlgSglTgtGen:: const auto& dspt = std::get<0>(dspt_vn_rfexpr_eq); const auto& wn = std::get<1>(dspt_vn_rfexpr_eq); - ILA_DLOG("VTG.AddWireEq") << eq->to_verilog(); + ILA_DLOG("VTG.AddWireEq") << GetVlg(eq); std::map array_var; if (rfmap::RfExprAstUtility::HasArrayVar(eq, array_var)) { @@ -321,12 +333,13 @@ void VlgSglTgtGen:: << " properties, please enable YosysSmtArrayForRegFile"; add_smt_assumption(eq, dspt); } else - vlg_wrapper.add_assign_stmt(wn, eq->child(1)->to_verilog()); + vlg_wrapper.add_assign_stmt( + wn, GetVlg(eq->get_child().at(1))); } for (const auto& dspt_aspt : all_assumptions) { for (const auto& aspt : dspt_aspt.second) { - ILA_DLOG("VTG.AddAssume") << aspt->to_verilog(); + ILA_DLOG("VTG.AddAssume") << GetVlg(aspt); std::map array_var; if (rfmap::RfExprAstUtility::HasArrayVar(aspt, array_var)) { @@ -335,19 +348,19 @@ void VlgSglTgtGen:: << " properties, please enable YosysSmtArrayForRegFile"; add_smt_assumption(aspt, dspt_aspt.first); } else - add_a_direct_assumption(aspt->to_verilog(), dspt_aspt.first); + add_a_direct_assumption(GetVlg(aspt), dspt_aspt.first); } } for (const auto& dspt_asst : all_assertions) { for (const auto& asst : dspt_asst.second) { - ILA_DLOG("VTG.AddAssert") << asst->to_verilog(); + ILA_DLOG("VTG.AddAssert") << GetVlg(asst); std::map array_var; if (rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) add_smt_assertion(asst, dspt_asst.first); else - add_a_direct_assertion(asst->to_verilog(), dspt_asst.first); + add_a_direct_assertion(GetVlg(asst), dspt_asst.first); } } @@ -358,7 +371,7 @@ void VlgSglTgtGen:: << "Implementation bug: sanity checking assertion should not contain " "arrays"; - add_a_direct_sanity_assertion(asst->to_verilog(), dspt_asst.first); + add_a_direct_sanity_assertion(GetVlg(asst), dspt_asst.first); } } for (const auto& dspt_cvrs : all_covers) { @@ -368,7 +381,7 @@ void VlgSglTgtGen:: << "Implementation bug: cover checks should not contain " "arrays"; - add_a_direct_cover_check(cvr->to_verilog(), dspt_cvrs.first); + add_a_direct_cover_check(GetVlg(cvr), dspt_cvrs.first); } } diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index 83573e713..b3bf755b9 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -184,6 +184,8 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { vlg_wrapper.add_wire("__IEND__", 1, true); vlg_wrapper.add_wire("__EDCOND__", 1, true); + vlg_wrapper.add_output("__IEND__", 1); + vlg_wrapper.add_output("__EDCOND__", 1); rfmap_add_internal_wire("__IEND__", 1); rfmap_add_internal_wire("__EDCOND__", 1); diff --git a/src/vtarget-out/single_target_connect.cc b/src/vtarget-out/single_target_connect.cc index 30b1bd9f4..0272e6d9c 100644 --- a/src/vtarget-out/single_target_connect.cc +++ b/src/vtarget-out/single_target_connect.cc @@ -316,9 +316,10 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_input_output() { refstr = "**NRESET**"; else if (IN(name_siginfo_pair.first, custom_input)) { auto short_name = name_siginfo_pair.first; - add_wire_assign_assumption( "__VLG_II_" + short_name, custom_input.at(name_siginfo_pair.first), + auto wname = "__VLG_II_" + short_name; + add_wire_assign_assumption( wname, custom_input.at(name_siginfo_pair.first), "vlg_input_wire"); - rfmap_add_internal_wire("__VLG_II_" + short_name, + rfmap_add_internal_wire(wname, name_siginfo_pair.second.get_width() ); refstr = "**CUSTOM_INPUT**"; } diff --git a/src/vtarget-out/single_target_inv_syn_support.cc b/src/vtarget-out/single_target_inv_syn_support.cc index ce3c366ee..1577185c1 100644 --- a/src/vtarget-out/single_target_inv_syn_support.cc +++ b/src/vtarget-out/single_target_inv_syn_support.cc @@ -74,6 +74,8 @@ void VlgSglTgtGen::add_inv_obj_as_assertion(InvariantObject* inv_obj) { for (auto&& name_expr_pair : inv_obj->GetExtraVarDefs()) { vlg_wrapper.add_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair), true); + vlg_wrapper.add_output(std::get<0>(name_expr_pair), + std::get<2>(name_expr_pair)); rfmap_add_internal_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair)); add_wire_assign_assumption( @@ -96,6 +98,8 @@ void VlgSglTgtGen::add_inv_obj_as_assumption(InvariantObject* inv_obj) { for (auto&& name_expr_pair : inv_obj->GetExtraVarDefs()) { vlg_wrapper.add_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair), true); + vlg_wrapper.add_output(std::get<0>(name_expr_pair), + std::get<2>(name_expr_pair)); rfmap_add_internal_wire(std::get<0>(name_expr_pair), std::get<2>(name_expr_pair)); add_wire_assign_assumption( diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 0676c7b0b..4b71fb242 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -157,10 +157,10 @@ void VlgSglTgtGen::ConstructWrapper_add_uf_constraints() { } // ConstructWrapper_add_uf_constraints void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { - for (const auto& delay_unit : refinement_map.aux_delays) { - std::cout << delay_unit.first << " : expr = " - << (delay_unit.second.signal) << std::endl; - } + // for (const auto& delay_unit : refinement_map.aux_delays) { + // std::cout << delay_unit.first << " : expr = " + // << (delay_unit.second.signal) << std::endl; + // } for (const auto& delay_unit : refinement_map.aux_delays) { const auto& name = delay_unit.first; @@ -182,6 +182,7 @@ void VlgSglTgtGen::ConstructWrapper_add_delay_unit() { if (didx == 1) { // delay from signal vlg_wrapper.add_wire(prev_name, width, true); + vlg_wrapper.add_output(prev_name, width); rfmap_add_internal_wire(prev_name, width); add_wire_assign_assumption(prev_name, rhs, "delay_unit"); } @@ -240,6 +241,7 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { } for (const auto& event_alias : tracker.event_alias) { vlg_wrapper.add_wire(event_alias.first, 1); + vlg_wrapper.add_output(event_alias.first, 1); rfmap_add_internal_wire(event_alias.first, 1); // add_wire_assign_assumption add_wire_assign_assumption(event_alias.first, event_alias.second, @@ -261,6 +263,7 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { vlg_wrapper.add_always_stmt("if(" + enter_cond_wire_name + ") begin " + stage_name + " <= 1'b1;"); vlg_wrapper.add_wire(enter_cond_wire_name, 1, true); + vlg_wrapper.add_output(enter_cond_wire_name, 1); rfmap_add_internal_wire(enter_cond_wire_name, 1); ILA_NOT_NULL(stage.enter_rule); add_wire_assign_assumption(enter_cond_wire_name, stage.enter_rule, @@ -278,6 +281,7 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { vlg_wrapper.add_always_stmt(action.LHS + " <= " + action_name + ";"); vlg_wrapper.add_wire(action_name, pos_def_var->second.width, true); + vlg_wrapper.add_output(action_name, pos_def_var->second.width); rfmap_add_internal_wire(action_name, pos_def_var->second.width); add_wire_assign_assumption(action_name, action.RHS, "phase_tracker"); } @@ -287,6 +291,7 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { ") begin " + stage_name + " <= 1'b0;"); vlg_wrapper.add_wire(exit_cond_wire_name, 1, true); + vlg_wrapper.add_output(exit_cond_wire_name, 1); rfmap_add_internal_wire(exit_cond_wire_name, 1); if (stage.exit_rule == nullptr) vlg_wrapper.add_assign_stmt(exit_cond_wire_name, "1'b0"); @@ -304,6 +309,7 @@ void VlgSglTgtGen::ConstructWrapper_add_stage_tracker() { std::string action_name = exit_action_wire_name + std::to_string(idx++); vlg_wrapper.add_always_stmt(action.LHS + " <= " + action_name + ";"); vlg_wrapper.add_wire(action_name, pos_def_var->second.width, true); + vlg_wrapper.add_output(action_name, pos_def_var->second.width); rfmap_add_internal_wire(action_name, pos_def_var->second.width); add_wire_assign_assumption(action_name, action.RHS, "phase_tracker"); } @@ -413,6 +419,13 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { unsigned idx = 0; std::vector> replace_list; + for (auto pos1 = mdef.var_uses.begin(); pos1 != mdef.var_uses.end(); ++pos1) { + for (auto pos2 = mdef.var_uses.begin(); pos2 != mdef.var_uses.end(); ++pos2) { + if(pos1 == pos2) continue; + ILA_ERROR_IF( (*pos1).find(*pos2) != std::string::npos) << *pos2 << " is part of " << *pos1; + } + } + for (const auto& vref : mdef.var_uses) { auto vref_node = rfmap::VerilogRefinementMap::ParseRfExprFromString(vref); @@ -425,6 +438,7 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { auto width = tp.unified_width(); vlg_wrapper.add_wire(new_name, width, true); + vlg_wrapper.add_output(new_name, width); rfmap_add_internal_wire(new_name, width); add_wire_assign_assumption(new_name, vref_node, "monitor_auxvar"); @@ -433,8 +447,12 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { auto vlog_inline = mdef.verilog_inline; for (const auto& old_new_pair : replace_list) { + // std::cout << vlog_inline << std::endl; vlog_inline = ReplaceAll(vlog_inline, old_new_pair.first, old_new_pair.second); + // std::cout << old_new_pair.first << std::endl; + // std::cout << old_new_pair.second << std::endl; + // std::cout << vlog_inline << std::endl; } vlg_wrapper.add_stmt(vlog_inline); diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json index 87218194e..95c1542c7 100644 --- a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder.json @@ -54,15 +54,16 @@ "delay_wb_write" : { "verilog": [ "always @(posedge clk) begin", - " delay_wb_write <= RTL.ex_wb_val;", - "end" + " delay_wb_write <= (#decode# & #afterdecode#) ? RTL.ex_wb_val : delay_wb_write;", + "end", + "assign usefl = RTL.registers[RTL.ex_wb_rd] ;" ], "append-verilog" : [ "module nouse(input wire aa, output wire bb);", " /*keep-for-invariants*/ assign bb=aa;", " endmodule"], - "defs" :[ ["delay_wb_write", 8, "reg"] ], - "refs" :[ "RTL.ex_wb_val" ], + "defs" :[ ["delay_wb_write", 8, "reg"], ["usefl", 8, "wire"] ], + "refs" :[ "RTL.ex_wb_val", "#decode#", "#afterdecode#","RTL.registers[RTL.ex_wb_rd]"], "keep-for-invariants" : true }, diff --git a/test/unit-data/vpipe/simple_pipe.v b/test/unit-data/vpipe/simple_pipe.v index e4a8b2003..1a4fe3225 100644 --- a/test/unit-data/vpipe/simple_pipe.v +++ b/test/unit-data/vpipe/simple_pipe.v @@ -76,10 +76,7 @@ assign rs2= inst[3:2]; assign rd = inst[1:0]; assign id_wen = op == `OP_ADD || op == `OP_SUB || op == `OP_AND; -assign dummy_rf_data = dummy_read_rf == 0 ? registers[0] : - dummy_read_rf == 1 ? registers[1] : - dummy_read_rf == 2 ? registers[2] : - registers[3]; +assign dummy_rf_data = registers[dummy_read_rf]; @@ -199,13 +196,7 @@ end // WB always @(posedge clk ) begin if (ex_wb_reg_wen) begin - case (ex_wb_rd) - 2'd0: registers[0] <= ex_wb_val; - 2'd1: registers[1] <= ex_wb_val; - 2'd2: registers[2] <= ex_wb_val; - 2'd3: registers[3] <= ex_wb_val; - default: registers[0] <= ex_wb_val; // nouse - endcase + registers[ex_wb_rd] <= ex_wb_val; end end diff --git a/test/unit-data/vpipe/simple_pipe_wrong.v b/test/unit-data/vpipe/simple_pipe_wrong.v index 0e83edd96..81b361aee 100644 --- a/test/unit-data/vpipe/simple_pipe_wrong.v +++ b/test/unit-data/vpipe/simple_pipe_wrong.v @@ -194,19 +194,15 @@ always @(posedge clk) begin end end + // WB always @(posedge clk ) begin if (ex_wb_reg_wen) begin - case (ex_wb_rd) - 2'd0: registers[0] <= ex_wb_val; - 2'd1: registers[1] <= ex_wb_val; - 2'd2: registers[2] <= ex_wb_val; - 2'd3: registers[3] <= ex_wb_val; - default: registers[0] <= ex_wb_val; // nouse - endcase + registers[ex_wb_rd] <= ex_wb_val; end end + /*inner_assign_list*/ endmodule From f22ee16b15cd61e977da642a082885b1ea4a5246 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 27 Oct 2021 18:59:50 +0800 Subject: [PATCH 59/78] add aux-var section --- include/ilang/rfmap-in/verilog_rfmap.h | 8 + include/ilang/vtarget-out/vtarget_gen_impl.h | 2 + src/rfmap-in/rfmap_typecheck.cc | 27 +- src/rfmap-in/verilog_rfmap.cc | 268 ++++++++++-------- src/vtarget-out/single_target.cc | 5 + .../single_target_inv_syn_support.cc | 1 + src/vtarget-out/single_target_misc.cc | 12 + src/vtarget-out/vtarget_gen_pono.cc | 3 +- .../vpipe/rfmap/vmap-rfmap-pvholder.json | 7 +- test/unit-data/vpipe/rfmap/vmap.json | 8 +- 10 files changed, 217 insertions(+), 124 deletions(-) diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 12993ac59..7538a525b 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -156,6 +156,13 @@ struct SignalDelay { unsigned upper_bnd; }; +struct AuxVar { + std::string name; + RfExpr val; + unsigned width; + AuxVar(const std::string & n) : name(n), width(0) {} +}; + struct PhaseTracker { struct Assignment { std::string LHS; // a state name @@ -215,6 +222,7 @@ struct VerilogRefinementMap { std::map phase_tracker; std::map value_recorder; std::map customized_monitor; + std::map direct_aux_vars; // ---------------------- inst-cond ------------------------------- // std::map inst_complete_cond; diff --git a/include/ilang/vtarget-out/vtarget_gen_impl.h b/include/ilang/vtarget-out/vtarget_gen_impl.h index 3ca15767b..e8c9a7140 100644 --- a/include/ilang/vtarget-out/vtarget_gen_impl.h +++ b/include/ilang/vtarget-out/vtarget_gen_impl.h @@ -280,6 +280,8 @@ class VlgSglTgtGen { void ConstructWrapper_add_stage_tracker(); /// Add Verilog inline monitor void ConstructWrapper_add_vlg_monitor(); + /// Add direct aux vars + void ConstructWrapper_add_direct_aux_vars(); /// handle all_assumption/all_assertion /// ReplExpr all assertion/assumptions /// ReplExpr will know whether to create diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index d20dd819a..e0f4dc696 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -188,6 +188,10 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { } } // value recorder + for (const auto& n_expr : direct_aux_vars) { + ILA_CHECK(n_expr.second.width == 0); + } // direct aux vars + for (const auto& n_st : customized_monitor) { for (const auto& var_def : n_st.second.var_defs) { all_var_def_types.emplace(var_def.first, var_def.second); @@ -286,7 +290,11 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr( pv.second.condition = TraverseRfExpr(pv.second.condition, func); pv.second.value = TraverseRfExpr(pv.second.value, func); } - // ALERT: do not handle customized recorder + for (auto& n_expr : direct_aux_vars) { + n_expr.second.val = TraverseRfExpr(n_expr.second.val, func); + } + + // ALERT: NOT handle customized_monitor in TraverseRfExpr for (auto& instcond : inst_complete_cond) { if (instcond.second.type == @@ -363,6 +371,23 @@ void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { all_var_def_types.emplace(name_vr.first, internal_var_def); } } // replendish internal defined vars + + for (auto& n_expr : direct_aux_vars) { + if(n_expr.second.width == 0) { + + auto tp = TypeInferTravserRfExpr(n_expr.second.val); + ILA_ERROR_IF(tp.is_array()) + << "Currently does not support to delay a memory variable"; + ILA_ERROR_IF(tp.is_unknown()) + << "Type inference failed on: " << n_expr.second.val->to_verilog(); + n_expr.second.width = tp.unified_width(); + + VarDef internal_var_def; + internal_var_def.width = tp.unified_width(); + internal_var_def.type = VarDef::var_type::WIRE; + all_var_def_types.emplace(n_expr.first, internal_var_def); + } + } } // ComputeDelayValueHolderWidth // relies on typechecker and all_var_def_types diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index c698e9a44..7691f8739 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -937,7 +937,7 @@ VerilogRefinementMap::VerilogRefinementMap( } // additional mapping & assumptions { // phase tracker, value recorder, customized ones - nlohmann::json* monitor_section = GetJsonSection(rf_vmap, {"monitor"}); + nlohmann::json* monitor_section = GetJsonSection(rf_vmap, {"monitor", "monitors"}); if (monitor_section) { ENSURE(monitor_section->is_object(), "`monitor` section should be a map"); for (auto& name_monitor_pair : monitor_section->items()) { @@ -949,131 +949,140 @@ VerilogRefinementMap::VerilogRefinementMap( "monitor `" + name + "` has been defined."); ERRIF(IN(name, value_recorder), "monitor `" + name + "` has been defined."); + ERRIF(IN(name, direct_aux_vars), + "monitor `" + name + "` has been defined."); auto& monitor = name_monitor_pair.value(); - auto* template_field = GetJsonSection(monitor, {"template"}); - if (template_field) { - ENSURE(template_field->is_string(), - "`template` field should be string"); - auto template_name = template_field->get(); - if (SectionNameRelaxedMatch(template_name, "phase tracker") || - SectionNameRelaxedMatch(template_name, "stage tracker") ) { - phase_tracker.emplace(name, PhaseTracker()); - std::string errmsg = JsonRfmapParsePhaseTracker( - phase_tracker.at(name), monitor, name); - ENSURE(errmsg.empty(), errmsg); - } else if (SectionNameRelaxedMatch(template_name, "value recorder")) { - value_recorder.emplace(name, ValueRecorder()); - std::string errmsg = - JsonRfmapParseValueRecorder(value_recorder.at(name), monitor); - ENSURE(errmsg.empty(), errmsg); - } else { - ERRIF(true, - "template name `" + template_name + "` is not recognized."); - } - // end if has template field + if (monitor.is_string()) { + direct_aux_vars.emplace(name, AuxVar(name)); + auto ret = ParseRfMapExpr(monitor.get()); + ILA_NOT_NULL(ret); + direct_aux_vars.at(name).val = ret; } else { - customized_monitor.emplace(name, GeneralVerilogMonitor()); - auto& mnt_ref = customized_monitor.at(name); - { // inline verilog - // has no template - auto* verilog_field = GetJsonSection(monitor, {"verilog"}); - auto* verilog_file_field = - GetJsonSection(monitor, {"verilog-from-file"}); - auto* keep_inv = GetJsonSection( - monitor, {"keep-for-invariant", "keep-for-invariants"}); - - ERRIF( - verilog_field && verilog_file_field, - "`verilog` or `verilog-from-file` fields are mutual exclusive"); - if (keep_inv) { - ENSURE(keep_inv->is_boolean(), - "`keep-for-invariant` should be Boolean"); - mnt_ref.keep_for_invariant = keep_inv->get(); + auto* template_field = GetJsonSection(monitor, {"template"}); + if (template_field) { + ENSURE(template_field->is_string(), + "`template` field should be string"); + auto template_name = template_field->get(); + if (SectionNameRelaxedMatch(template_name, "phase tracker") || + SectionNameRelaxedMatch(template_name, "stage tracker") ) { + phase_tracker.emplace(name, PhaseTracker()); + std::string errmsg = JsonRfmapParsePhaseTracker( + phase_tracker.at(name), monitor, name); + ENSURE(errmsg.empty(), errmsg); + } else if (SectionNameRelaxedMatch(template_name, "value recorder")) { + value_recorder.emplace(name, ValueRecorder()); + std::string errmsg = + JsonRfmapParseValueRecorder(value_recorder.at(name), monitor); + ENSURE(errmsg.empty(), errmsg); + } else { + ERRIF(true, + "template name `" + template_name + "` is not recognized."); } + // end if has template field + } else { + customized_monitor.emplace(name, GeneralVerilogMonitor()); + auto& mnt_ref = customized_monitor.at(name); + { // inline verilog + // has no template + auto* verilog_field = GetJsonSection(monitor, {"verilog"}); + auto* verilog_file_field = + GetJsonSection(monitor, {"verilog-from-file"}); + auto* keep_inv = GetJsonSection( + monitor, {"keep-for-invariant", "keep-for-invariants"}); + + ERRIF( + verilog_field && verilog_file_field, + "`verilog` or `verilog-from-file` fields are mutual exclusive"); + if (keep_inv) { + ENSURE(keep_inv->is_boolean(), + "`keep-for-invariant` should be Boolean"); + mnt_ref.keep_for_invariant = keep_inv->get(); + } - if (verilog_field) { - if (verilog_field->is_string()) { - mnt_ref.verilog_inline = verilog_field->get(); - } else { - ENSURE(verilog_field->is_array(), - "`verilog` field should be a list of string"); - for (auto& ps : *verilog_field) { - ENSURE(ps.is_string(), - "`verilog` field should be a list of string"); - mnt_ref.verilog_inline += ps.get() + "\n"; + if (verilog_field) { + if (verilog_field->is_string()) { + mnt_ref.verilog_inline = verilog_field->get(); + } else { + ENSURE(verilog_field->is_array(), + "`verilog` field should be a list of string"); + for (auto& ps : *verilog_field) { + ENSURE(ps.is_string(), + "`verilog` field should be a list of string"); + mnt_ref.verilog_inline += ps.get() + "\n"; + } } - } - } else if (verilog_file_field) { - ENSURE(verilog_file_field->is_string(), - "`verilog-from-file` expects a string (file name)"); - auto fname = verilog_file_field->get(); - std::ifstream fin(fname); - ENSURE(fin.is_open(), "Cannot read from " + fname); - { - std::stringstream buffer; - buffer << fin.rdbuf(); - mnt_ref.verilog_inline = buffer.str(); - } - } // verilog_file_field : from file - } // inline verilog - - { // append verilog outside the module - // has no template - auto* verilog_field = GetJsonSection(monitor, {"append-verilog"}); - auto* verilog_file_field = - GetJsonSection(monitor, {"append-verilog-from-file"}); - - ERRIF(verilog_field && verilog_file_field, - "`append-verilog` or `append-verilog-from-file` fields are " - "mutual exclusive"); - - if (verilog_field) { - if (verilog_field->is_string()) { - mnt_ref.verilog_append = - verilog_field->get() + "\n"; - } else { - ENSURE(verilog_field->is_array(), - "`append-verilog` field should be a list of string"); - for (auto& ps : *verilog_field) { - ENSURE(ps.is_string(), - "`append-verilog` field should be a list of string"); - mnt_ref.verilog_append += ps.get() + "\n"; + } else if (verilog_file_field) { + ENSURE(verilog_file_field->is_string(), + "`verilog-from-file` expects a string (file name)"); + auto fname = verilog_file_field->get(); + std::ifstream fin(fname); + ENSURE(fin.is_open(), "Cannot read from " + fname); + { + std::stringstream buffer; + buffer << fin.rdbuf(); + mnt_ref.verilog_inline = buffer.str(); } + } // verilog_file_field : from file + } // inline verilog + + { // append verilog outside the module + // has no template + auto* verilog_field = GetJsonSection(monitor, {"append-verilog"}); + auto* verilog_file_field = + GetJsonSection(monitor, {"append-verilog-from-file"}); + + ERRIF(verilog_field && verilog_file_field, + "`append-verilog` or `append-verilog-from-file` fields are " + "mutual exclusive"); + + if (verilog_field) { + if (verilog_field->is_string()) { + mnt_ref.verilog_append = + verilog_field->get() + "\n"; + } else { + ENSURE(verilog_field->is_array(), + "`append-verilog` field should be a list of string"); + for (auto& ps : *verilog_field) { + ENSURE(ps.is_string(), + "`append-verilog` field should be a list of string"); + mnt_ref.verilog_append += ps.get() + "\n"; + } + } + } else if (verilog_file_field) { + ENSURE(verilog_file_field->is_string(), + "`append-verilog-from-file` expects a string (file name)"); + auto fname = verilog_file_field->get(); + std::ifstream fin(fname); + ENSURE(fin.is_open(), "Cannot read from " + fname); + { + std::stringstream buffer; + buffer << fin.rdbuf(); + mnt_ref.verilog_append = buffer.str() + "\n"; + } + } // append-verilog_file_field : from file + } // verilog_append verilog + + auto* ref_field = GetJsonSection(monitor, {"refs"}); + if (ref_field) { // refs + ENSURE(ref_field->is_array(), + "`refs` field should be a list of string"); + for (auto& p : *ref_field) { + ENSURE(p.is_string(), "`refs` field should be a list of string"); + auto var_name = p.get(); + ILA_WARN_IF(IN(var_name, mnt_ref.var_uses)) + << "`" + var_name + "` has been declared already"; + mnt_ref.var_uses.insert(p.get()); } - } else if (verilog_file_field) { - ENSURE(verilog_file_field->is_string(), - "`append-verilog-from-file` expects a string (file name)"); - auto fname = verilog_file_field->get(); - std::ifstream fin(fname); - ENSURE(fin.is_open(), "Cannot read from " + fname); - { - std::stringstream buffer; - buffer << fin.rdbuf(); - mnt_ref.verilog_append = buffer.str() + "\n"; - } - } // append-verilog_file_field : from file - } // verilog_append verilog - - auto* ref_field = GetJsonSection(monitor, {"refs"}); - if (ref_field) { // refs - ENSURE(ref_field->is_array(), - "`refs` field should be a list of string"); - for (auto& p : *ref_field) { - ENSURE(p.is_string(), "`refs` field should be a list of string"); - auto var_name = p.get(); - ILA_WARN_IF(IN(var_name, mnt_ref.var_uses)) - << "`" + var_name + "` has been declared already"; - mnt_ref.var_uses.insert(p.get()); - } - } // if ref_field - - auto* def_field = GetJsonSection(monitor, {"defs"}); - if (def_field) { // defs - auto err_msg = JsonRfMapParseVarDefs(mnt_ref.var_defs, *def_field); - ENSURE(err_msg.empty(), err_msg); - } // if def_field - } // else if it is verilog monitor (general) + } // if ref_field + + auto* def_field = GetJsonSection(monitor, {"defs"}); + if (def_field) { // defs + auto err_msg = JsonRfMapParseVarDefs(mnt_ref.var_defs, *def_field); + ENSURE(err_msg.empty(), err_msg); + } // if def_field + } // else if it is verilog monitor (general) + } // end of if is_string()--else } // for each monitor } // if has monitor field } // monitor block @@ -1284,18 +1293,39 @@ bool VerilogRefinementMap::SelfCheckField() const { { // GeneralVerilogMonitor, for ids are okay, no bad names std::set var_def_names; for (const auto& n_st : phase_tracker) { - + // const auto & phase_tracker_name = n_st.first; for (const auto& var_def : n_st.second.event_alias) { + ERRIF(!is_valid_id_name(var_def.first), + "Monitor name " + var_def.first + " is not valid"); ERRIF(IN(var_def.first, var_def_names), "Variable " + n_st.first + " has been defined already"); var_def_names.insert(var_def.first); } for (const auto& var_def : n_st.second.var_defs) { + ERRIF(!is_valid_id_name(var_def.first), + "Monitor name " + var_def.first + " is not valid"); ERRIF(IN(var_def.first, var_def_names), "Variable " + n_st.first + " has been defined already"); var_def_names.insert(var_def.first); } + for (const auto& st : n_st.second.rules) { + ERRIF(!is_valid_id_name(st.stage_name), + "stage name " + st.stage_name + " is not valid"); + + ERRIF(IN(st.stage_name, var_def_names), + "Variable " + n_st.first + " has been defined already"); + var_def_names.insert(st.stage_name); + } + } + + for (const auto& n_expr : direct_aux_vars) { + ERRIF(!is_valid_id_name(n_expr.first), + "Monitor name " + n_expr.first + " is not valid"); + ERRIF(IN(n_expr.first, var_def_names), + "Monitor name " + n_expr.first + " has been used"); + var_def_names.insert(n_expr.first); } + for (const auto& n_st : value_recorder) { ERRIF(!is_valid_id_name(n_st.first), "Monitor name " + n_st.first + " is not valid"); diff --git a/src/vtarget-out/single_target.cc b/src/vtarget-out/single_target.cc index 3c5b0ffe8..b6e64134d 100644 --- a/src/vtarget-out/single_target.cc +++ b/src/vtarget-out/single_target.cc @@ -359,6 +359,11 @@ void VlgSglTgtGen::ConstructWrapper() { ConstructWrapper_add_post_value_holder(); ConstructWrapper_add_delay_unit(); ConstructWrapper_add_stage_tracker(); + // you cannot always add aux vars + // because it may refer to other aux vars (like post value holder) + // unless we have a way to check hierarchically + // the dependency + ConstructWrapper_add_direct_aux_vars(); } ConstructWrapper_add_vlg_monitor(); diff --git a/src/vtarget-out/single_target_inv_syn_support.cc b/src/vtarget-out/single_target_inv_syn_support.cc index 1577185c1..5df7fd539 100644 --- a/src/vtarget-out/single_target_inv_syn_support.cc +++ b/src/vtarget-out/single_target_inv_syn_support.cc @@ -251,6 +251,7 @@ void VlgSglTgtGen::ConstructWrapper_inv_syn_cond_signals() { rfmap_add_internal_wire("__START__", 1); rfmap_add_replacement("decode", "__START__"); rfmap_add_internal_wire("__STARTED__", 1); + rfmap_add_replacement("afterdecode", "__STARTED__"); } } // namespace ilang diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 4b71fb242..aae15a62e 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -389,6 +389,18 @@ void VlgSglTgtGen::ConstructWrapper_add_post_value_holder() { } // for each value recorder } // ConstructWrapper_add_post_value_holder +/// Add direct aux vars +void VlgSglTgtGen::ConstructWrapper_add_direct_aux_vars() { + for (const auto & n_expr : refinement_map.direct_aux_vars) { + const auto & n = n_expr.first; + auto w = n_expr.second.width; + ILA_CHECK(w!=0); + vlg_wrapper.add_wire(n,w,true); + vlg_wrapper.add_output(n,w); + add_wire_assign_assumption(n, n_expr.second.val, "direct_aux_var"); + } +} + void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { if (refinement_map.customized_monitor.empty()) return; diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index 2af81efc1..4afb1a14b 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -198,7 +198,7 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { // here we intentionally leave out the property interface file. fout << "echo \"* Run Pono to check assumption sanity...\"" << std::endl; - fout << pono << options << " sanity.btor2 " << std::endl; + fout << pono << options << extra_smt_properties << " sanity.btor2 " << std::endl; fout << "SanityResult=$?" << std::endl; } else { fout << "SanityResult=3" << std::endl; @@ -212,6 +212,7 @@ void VlgSglTgtGen_Pono::Export_script(const std::string& script_name) { for (unsigned idx = 0; idx < all_cover_assert_property_names.size(); ++idx) { auto cover_fname = "cover" + std::to_string(idx)+".btor2"; std::string cover_options = " -e bmc " + _vtg_config.PonoOtherOptions; + cover_options += extra_smt_properties; fout << "echo \"* Parsing cover check input #" < Date: Mon, 1 Nov 2021 15:37:31 +0800 Subject: [PATCH 60/78] fix wrapper path --- src/rfmap-in/verilog_rfmap.cc | 4 +++- src/vtarget-out/vtarget_gen_pono.cc | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 7691f8739..92cd7238f 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -99,6 +99,8 @@ RfExpr ParseRfMapExpr(const std::string& in) { } RfExpr ParseRfMapExprJson(nlohmann::json& in) { + if(in.is_null()) + return ParseRfMapExpr("1'b1 == 1'b1"); // true return ParseRfMapExpr(in.get()); } @@ -1071,7 +1073,7 @@ VerilogRefinementMap::VerilogRefinementMap( ENSURE(p.is_string(), "`refs` field should be a list of string"); auto var_name = p.get(); ILA_WARN_IF(IN(var_name, mnt_ref.var_uses)) - << "`" + var_name + "` has been declared already"; + << "`" + var_name + "` has been declared already in `refs`"; mnt_ref.var_uses.insert(p.get()); } } // if ref_field diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index 4afb1a14b..c0f03af7a 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -264,7 +264,7 @@ void VlgSglTgtGen_Pono::GenYosysScript( write_btor_options += _vtg_config.BtorSingleProperty ? " -s" : ""; ys_script_fout << "read_verilog -sv " - << os_portable_append_dir(_output_path, top_file_name) + << top_file_name // os_portable_append_dir(_output_path, top_file_name) << std::endl; ys_script_fout << "prep -top " << top_mod_name << std::endl; From fb1c9d9b9a1b6e78c54d1aebc605bfa30b73ba49 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Wed, 3 Nov 2021 11:27:09 +0800 Subject: [PATCH 61/78] annotation for width --- include/ilang/rfmap-in/verilog_rfmap.h | 2 ++ include/ilang/verilog-in/verilog_analysis.h | 6 ++-- .../verilog-in/verilog_analysis_wrapper.h | 3 +- include/ilang/vtarget-out/vlg_mod.h | 5 +++- src/rfmap-in/verilog_rfmap.cc | 30 ++++++++++++++----- src/verilog-in/verilog_analysis.cc | 16 ++++++---- src/verilog-in/verilog_analysis_wrapper.cc | 5 ++-- src/vtarget-out/gen_util.cc | 4 ++- src/vtarget-out/vlg_mod.cc | 8 +++-- src/vtarget-out/vtarget_gen_pono.cc | 4 ++- test/t_verilog_analysis.cc | 6 ++-- test/t_verilog_mod.cc | 2 +- 12 files changed, 64 insertions(+), 27 deletions(-) diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index 7538a525b..d2ebdba02 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -232,6 +232,8 @@ struct VerilogRefinementMap { // // std::map width_info; // this is needed in case our width inference failed + std::map + range_info; // this is needed in case our width inference failed // member function : return true if checking passed bool SelfCheckField() const; diff --git a/include/ilang/verilog-in/verilog_analysis.h b/include/ilang/verilog-in/verilog_analysis.h index 7915a2117..1267ed6b5 100644 --- a/include/ilang/verilog-in/verilog_analysis.h +++ b/include/ilang/verilog-in/verilog_analysis.h @@ -63,7 +63,8 @@ class SignalInfoReg : public SignalInfoBase { SignalInfoReg(ast_reg_declaration* def, const std::string& full_name, VerilogAnalyzerBase::hierarchical_name_type tp, const std::map* const width_info, - const VerilogAnalyzer* _ana); + const VerilogAnalyzer* _ana, + const std::map* const range_info); /// Return its definition ast_reg_declaration* get_def() { return _def; } }; // class SignalInfoPort @@ -187,7 +188,8 @@ class VerilogAnalyzer : public VerilogAnalyzerBase { /// Find a signal SignalInfoBase get_signal(const std::string& net_name, - const std::map* const width_info = NULL) const; + const std::map* const width_info = NULL, + const std::map* const range_info = NULL) const; /// Return the location of a module's endmodule statement vlg_loc_t get_endmodule_loc(const std::string& inst_name) const; /// Return the module name of a net --- will check if the module names are diff --git a/include/ilang/verilog-in/verilog_analysis_wrapper.h b/include/ilang/verilog-in/verilog_analysis_wrapper.h index 8eac4915e..3ba79903b 100644 --- a/include/ilang/verilog-in/verilog_analysis_wrapper.h +++ b/include/ilang/verilog-in/verilog_analysis_wrapper.h @@ -247,7 +247,8 @@ class VerilogInfo { SignalInfoBase get_signal(const std::string& net_name) const; /// Find a signal (and use the width info, if width is unknown) SignalInfoBase get_signal(const std::string& net_name, - const std::map& width_info) const; + const std::map& width_info, + const std::map& range_info) const; /// whether this analyzer is in bad state bool in_bad_state() const; diff --git a/include/ilang/vtarget-out/vlg_mod.h b/include/ilang/vtarget-out/vlg_mod.h index 62484e9dc..403e5944c 100644 --- a/include/ilang/vtarget-out/vlg_mod.h +++ b/include/ilang/vtarget-out/vlg_mod.h @@ -89,7 +89,8 @@ class VerilogModifier { /// \param[in] the style: 0 auto deteremined, 1 Old, 2 New VerilogModifier(VerilogInfo* _vlg_info_ptr, port_decl_style_t port_decl_style, bool add_keep_or_not, - const std::map& _sup_width_info); // + const std::map& _sup_width_info, + const std::map& _sup_range_info); // /// Destructor: ~VerilogModifier(); /// do the work : read from fin and append to fout, fout needs to be open with @@ -129,6 +130,8 @@ class VerilogModifier { bool _add_keep_or_not; /// the supplementary width info const std::map& sup_width_info; + /// the supplementary range info + const std::map& sup_range_info; protected: // --------------- HELPERS --------------------------- // diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 92cd7238f..8f89e61d8 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -420,7 +420,7 @@ std::string JsonRfMapParseVarDefs( std::string JsonRfmapParsePhaseTracker(PhaseTracker& tracker, nlohmann::json& monitor, const std::string& tracker_name) { - auto* event_alias = GetJsonSection(monitor, {"event-alias"}); + auto* event_alias = GetJsonSection(monitor, {"event-alias", "signal-alias"}); auto* rules = GetJsonSection(monitor, {"rules"}); auto* aux_var = GetJsonSection(monitor, {"aux-var"}); ERRIF(rules == NULL, "`phase tracker` needs `rules` field"); @@ -616,7 +616,11 @@ VerilogRefinementMap::VerilogRefinementMap( for (auto& i : state_mapping->items()) { IlaVarMapping svmp; auto sname = i.key(); // ila state name - if (i.value().is_string()) { + if (i.value().is_null()) { + svmp.type = IlaVarMapping::StateVarMapType::SINGLE; + svmp.single_map.single_map = ParseRfMapExprJson(i.value()); // 1'b1 == 1'b1 + } + else if (i.value().is_string()) { svmp.type = IlaVarMapping::StateVarMapType::SINGLE; svmp.single_map.single_map = ParseRfMapExprJson(i.value()); } else if (i.value().is_object()) { @@ -886,21 +890,25 @@ VerilogRefinementMap::VerilogRefinementMap( "Expect `functions` to be map:name->list of invocation(object)"); auto* result = GetJsonSection(elem, {"result"}); auto* arg = GetJsonSection(elem, {"arg", "args"}); - ENSURE(result && arg, + ENSURE(result, "Expect invocation object has `result` and `arg` field"); ENSURE(result->is_string(), "Expect type string in `result` field of invocation object"); + if(arg) { ENSURE( arg->is_array(), "Expect type list(string) in `arg` field of invocation object"); + } apply_obj.func_applications.push_back( UninterpretedFunctionApplication::Apply()); auto& curr_invocation = apply_obj.func_applications.back(); curr_invocation.result_map = ParseRfMapExprJson(*result); - std::vector argList = - arg->get>(); - for (const auto& arg : argList) - curr_invocation.arg_map.push_back(ParseRfMapExpr(arg)); + if(arg) { + std::vector argList = + arg->get>(); + for (const auto& arg : argList) + curr_invocation.arg_map.push_back(ParseRfMapExpr(arg)); + } } } // for each invocation } // if func_section @@ -1168,6 +1176,14 @@ VerilogRefinementMap::VerilogRefinementMap( if (width_anno && width_anno->is_object()) { for (auto&& nw : width_anno->items()) { width_info.insert(std::make_pair(nw.key(), nw.value().get())); + ERRIF(nw.value().get() <= 0 , (nw.key() + "'s width <=0")); + } + } + auto* range_anno = GetJsonSection(*annotation, {"range"}); + if (range_anno && range_anno->is_object()) { + for (auto&& nw : range_anno->items()) { + range_info.insert(std::make_pair(nw.key(), nw.value().get())); + ERRIF(nw.value().get() <= 0 , (nw.key() + "'s range <=0")); } } } // end of annotation diff --git a/src/verilog-in/verilog_analysis.cc b/src/verilog-in/verilog_analysis.cc index b66c88bf9..e0b281233 100644 --- a/src/verilog-in/verilog_analysis.cc +++ b/src/verilog-in/verilog_analysis.cc @@ -633,7 +633,8 @@ VerilogAnalyzer::name2loc(const std::string& net_name) const { /// Find a signal SignalInfoBase VerilogAnalyzer::get_signal( const std::string& net_name, - const std::map* const width_info) const { + const std::map* const width_info, + const std::map* const range_info) const { SignalInfoBase bad_signal("", "", 0, hierarchical_name_type::NONE, vlg_loc_t(), 0); @@ -670,7 +671,7 @@ SignalInfoBase VerilogAnalyzer::get_signal( case O_REG_w_INTERNAL_DEF: case REG: return SignalInfoReg((ast_reg_declaration*)ast_ptr, net_name, tp_, - width_info, this); + width_info, this, range_info); case MODULE: ILA_ERROR << "Module instance:" << net_name << " is not a signal."; return bad_signal; @@ -756,7 +757,7 @@ VerilogAnalyzer::module_io_vec_t VerilogAnalyzer::get_top_module_io( case O_REG_w_INTERNAL_DEF: retIoVec.insert( {short_name, SignalInfoReg((ast_reg_declaration*)ast_ptr, port_name, - tp_, width_info, this)}); + tp_, width_info, this, NULL)}); break; default: ILA_ASSERT(false) << "Implementation bug."; @@ -838,6 +839,9 @@ unsigned range_to_width(ast_range* range, const std::string& full_name, const VerilogAnalyzer* _ana, int width = -1) { if (range == NULL) return 1; + if(width > 0) + return width; + ast_expression* left = range->upper; ast_expression* right = range->lower; @@ -903,7 +907,8 @@ SignalInfoReg::SignalInfoReg(ast_reg_declaration* def, const std::string& full_name, VerilogAnalyzerBase::hierarchical_name_type tp, const std::map* const width_info, - const VerilogAnalyzer* _ana) + const VerilogAnalyzer* _ana, + const std::map* const range_info) : SignalInfoBase(Split(full_name, ".").back(), full_name, range_to_width(def->range, full_name, _ana, width_info == NULL @@ -912,7 +917,8 @@ SignalInfoReg::SignalInfoReg(ast_reg_declaration* def, ? width_info->at(full_name) : -1)), tp, VerilogAnalyzer::Meta2Loc(def->meta), - addr_range_to_width(def->identifier, full_name, _ana, -1) + addr_range_to_width(def->identifier, full_name, _ana, + range_info == NULL ? -1 : (IN_p(full_name, range_info) ? range_info->at(full_name) : -1) ) ), _def(def) { ILA_WARN_IF(_width == 0) diff --git a/src/verilog-in/verilog_analysis_wrapper.cc b/src/verilog-in/verilog_analysis_wrapper.cc index 37a83b5a2..8b2abdd18 100644 --- a/src/verilog-in/verilog_analysis_wrapper.cc +++ b/src/verilog-in/verilog_analysis_wrapper.cc @@ -82,10 +82,11 @@ SignalInfoBase VerilogInfo::get_signal(const std::string& net_name) const { /// Find a signal (and use the width info, if width is unknown) SignalInfoBase VerilogInfo::get_signal(const std::string& net_name, - const std::map& width_info) const { + const std::map& width_info, + const std::map& range_info) const { const VerilogAnalyzer* _ptr = dynamic_cast(_analyzer); ILA_NOT_NULL(_ptr); - return _ptr->get_signal(net_name, &width_info); + return _ptr->get_signal(net_name, &width_info, &range_info); } bool VerilogInfo::in_bad_state() const { diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index c9cb8650f..35af1c3d0 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -187,7 +187,9 @@ VlgSglTgtGen::VarTypeCheckForRfExprParsing(const std::string& vname) { } // else if if (StrStartsWith(vname, "RTL.")) { ILA_ERROR_IF(!TryFindVlgState(vname)) << "Cannot find rtl var: " << vname; - auto sig_info = vlg_info_ptr->get_signal(vname); + auto sig_info = vlg_info_ptr->get_signal(vname, + refinement_map.width_info, + refinement_map.range_info); auto aw_range = sig_info.get_addr_range_size(); auto dw = sig_info.get_width(); diff --git a/src/vtarget-out/vlg_mod.cc b/src/vtarget-out/vlg_mod.cc index 0c85a0870..b3078f0cd 100644 --- a/src/vtarget-out/vlg_mod.cc +++ b/src/vtarget-out/vlg_mod.cc @@ -14,9 +14,11 @@ namespace ilang { /// Constructor: do nothing VerilogModifier::VerilogModifier( VerilogInfo* _vlg_info_ptr, port_decl_style_t port_decl_style, - bool add_keep_or_not, const std::map& _sup_width_info) + bool add_keep_or_not, const std::map& _sup_width_info, + const std::map& _sup_range_info) : vlg_info_ptr(_vlg_info_ptr), _port_decl_style(port_decl_style), - _add_keep_or_not(add_keep_or_not), sup_width_info(_sup_width_info) {} + _add_keep_or_not(add_keep_or_not), sup_width_info(_sup_width_info), + sup_range_info(_sup_range_info) {} /// Destructor: do nothing VerilogModifier::~VerilogModifier() {} @@ -150,7 +152,7 @@ void VerilogModifier::FinishRecording() { /// record the name to add a keep there void VerilogModifier::RecordKeepSignalName(const std::string& vlg_sig_name) { - auto vlg_sig_info = vlg_info_ptr->get_signal(vlg_sig_name); + auto vlg_sig_info = vlg_info_ptr->get_signal(vlg_sig_name,sup_width_info,sup_range_info ); auto loc = vlg_info_ptr->name2loc(vlg_sig_name); // check for repetition: diff --git a/src/vtarget-out/vtarget_gen_pono.cc b/src/vtarget-out/vtarget_gen_pono.cc index c0f03af7a..943cb3f85 100644 --- a/src/vtarget-out/vtarget_gen_pono.cc +++ b/src/vtarget-out/vtarget_gen_pono.cc @@ -549,7 +549,9 @@ void VlgSglTgtGen_Pono::Export_modify_verilog() { VerilogModifier vlg_mod(vlg_info_ptr, static_cast( _vtg_config.PortDeclStyle), - _vtg_config.PonoAddKeep, refinement_map.width_info); + _vtg_config.PonoAddKeep, + refinement_map.width_info, + refinement_map.range_info); for (auto&& wn_extraw : rtl_extra_wire) { ILA_CHECK(StrStartsWith(wn_extraw.first, "RTL__DOT__")); diff --git a/test/t_verilog_analysis.cc b/test/t_verilog_analysis.cc index cdfe18adb..07535e605 100644 --- a/test/t_verilog_analysis.cc +++ b/test/t_verilog_analysis.cc @@ -221,7 +221,7 @@ TEST(TestVerilogAnalysis, RangeAnalysisOverwriteWidth) { EXPECT_EQ(va.get_signal("m1.i1.sig").get_width(), 2); std::map width_overwrite_map({{"m1.i1.sig", 5}}); - EXPECT_EQ(va.get_signal("m1.i1.sig", width_overwrite_map).get_width(), 5); + EXPECT_EQ(va.get_signal("m1.i1.sig", width_overwrite_map, {}).get_width(), 5); { // no overwrite case VerilogInfo::module_io_vec_t top_io = va.get_top_module_io(); @@ -256,7 +256,7 @@ TEST(TestVerilogAnalysis, RangeAnalysisOverwriteWidth) { EXPECT_EQ(va.get_signal("m1.in1").get_width(), 4); std::map width_overwrite_map({{"m1.in1", 5}}); - EXPECT_EQ(va.get_signal("m1.in1", width_overwrite_map).get_width(), 5); + EXPECT_EQ(va.get_signal("m1.in1", width_overwrite_map, {}).get_width(), 5); { // no overwrite case VerilogInfo::module_io_vec_t top_io = va.get_top_module_io(); @@ -279,7 +279,7 @@ TEST(TestVerilogAnalysis, RangeAnalysisOverwriteWidth) { std::map width_overwrite_map3({{"m1.in2", 128}}); - EXPECT_EQ(va.get_signal("m1.in2", width_overwrite_map3).get_width(), 128); + EXPECT_EQ(va.get_signal("m1.in2", width_overwrite_map3, {}).get_width(), 128); { // overwrite case diff --git a/test/t_verilog_mod.cc b/test/t_verilog_mod.cc index 0aea8217c..896a2addf 100644 --- a/test/t_verilog_mod.cc +++ b/test/t_verilog_mod.cc @@ -37,7 +37,7 @@ TEST(TestVerilogMod, Modify) { VerilogInfo va(VerilogInfo::path_vec_t(), VerilogInfo::path_vec_t({fn}), "m1"); - VerilogModifier vm(&va, VerilogModifier::port_decl_style_t::AUTO, true, {}); + VerilogModifier vm(&va, VerilogModifier::port_decl_style_t::AUTO, true, {}, {}); vm.RecordKeepSignalName("m1.__COUNTER_start__n3"); vm.RecordKeepSignalName("m1.__ILA_proc_decode_of_Add__"); From 4924f922972a7ae46bd8fee79054769e85f6ff5a Mon Sep 17 00:00:00 2001 From: yue Date: Thu, 4 Nov 2021 12:29:52 -0400 Subject: [PATCH 62/78] fix vexparser build on win ci. ProgramData path is hard-coded --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 940d9801e..6d728f89e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -147,7 +147,7 @@ jobs: cd vexpparser md build cd build - cmake .. -DCMAKE_CXX_FLAGS=/I\ %ProgramData%\\chocolatey\\lib\\winflexbison3\\tools + cmake .. -DFLEXLEXER_INCLUDE_PATH=c:\ProgramData\chocolatey\lib\winflexbison3\tools\ cmake --build . --target install displayName: 'vexpparser' From ca7ae82d51e68107def2f25220a9159bc06c3299 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 5 Nov 2021 11:34:05 +0800 Subject: [PATCH 63/78] fix vlg_mod test failure --- test/t_verilog_mod.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/t_verilog_mod.cc b/test/t_verilog_mod.cc index 896a2addf..1bb4bcdf8 100644 --- a/test/t_verilog_mod.cc +++ b/test/t_verilog_mod.cc @@ -37,7 +37,9 @@ TEST(TestVerilogMod, Modify) { VerilogInfo va(VerilogInfo::path_vec_t(), VerilogInfo::path_vec_t({fn}), "m1"); - VerilogModifier vm(&va, VerilogModifier::port_decl_style_t::AUTO, true, {}, {}); + std::map empty_annotation; + VerilogModifier vm(&va, VerilogModifier::port_decl_style_t::AUTO, + true, empty_annotation, empty_annotation); vm.RecordKeepSignalName("m1.__COUNTER_start__n3"); vm.RecordKeepSignalName("m1.__ILA_proc_decode_of_Add__"); From dd66f8241211aebaeca225a98c51732d039b8526 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 5 Nov 2021 12:57:57 +0800 Subject: [PATCH 64/78] disable overwriting warning --- src/verilog-in/verilog_analysis.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/verilog-in/verilog_analysis.cc b/src/verilog-in/verilog_analysis.cc index e0b281233..c6767d0a0 100644 --- a/src/verilog-in/verilog_analysis.cc +++ b/src/verilog-in/verilog_analysis.cc @@ -858,14 +858,13 @@ unsigned range_to_width(ast_range* range, const std::string& full_name, unsigned rr = (unsigned)eval.Eval(right); unsigned analyzed_width = std::max(lr, rr) - std::min(lr, rr) + 1; - // this will provide width when we cannot get width - // or there is error, o.w. we will trust the width from - if (width > 0) { - ILA_WARN_IF(!eval.error()) - << "Overwriting width of signal: " << full_name << " to " << width - << "(w=" << analyzed_width << " by analysis)"; - return width; - } + // overwriting will end this procedure first. + // if (width > 0) { + // ILA_WARN_IF(!eval.error()) + // << "Overwriting width of signal: " << full_name << " to " << width + // << "(w=" << analyzed_width << " by analysis)"; + // return width; + //} return analyzed_width; } From 94490b82b99437d2d0fecc5ab8342a67c4630f00 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 5 Nov 2021 12:58:45 +0800 Subject: [PATCH 65/78] update vexp ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 0aeb63535..4892ccfaa 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 0aeb63535e0a8d9a60d696881cafc99cdc195c30 +Subproject commit 4892ccfaa3c04a9da72ee062399c114501477788 From d7e0df6b3a4ccf86883d3b6d6afab5cb5236c302 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 8 Nov 2021 09:00:37 +0800 Subject: [PATCH 66/78] more cmake macro def --- azure-pipelines.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6d728f89e..edfa93469 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -120,7 +120,7 @@ jobs: cd glog md build cd build - cmake .. + cmake .. -DFLEXLEXER_INCLUDE_PATH=c:\ProgramData\chocolatey\lib\winflexbison3\tools\ cmake --build . --target install displayName: 'glog' @@ -155,7 +155,7 @@ jobs: md build cd build # For building the test, we need CMAKE_MSVC_RUNTIME_LIBRARY (which will be supported in CMake 3.15+) - cmake .. -DILANG_BUILD_TEST=OFF -DBUILD_SHARED_LIBS=OFF -DILANG_BUILD_INVSYN=OFF -DZ3_INCLUDE_DIR=$(Build.Repository.LocalPath)/z3/include -DZ3_LIBRARY=$(Build.Repository.LocalPath)/z3/bin/libz3.lib -DZ3_EXEC=$(Build.Repository.LocalPath)/z3/bin/z3.exe + cmake .. -DILANG_BUILD_TEST=OFF -DBUILD_SHARED_LIBS=OFF -DILANG_BUILD_INVSYN=OFF -DZ3_INCLUDE_DIR=$(Build.Repository.LocalPath)/z3/include -DZ3_LIBRARY=$(Build.Repository.LocalPath)/z3/bin/libz3.lib -DZ3_EXEC=$(Build.Repository.LocalPath)/z3/bin/z3.exe -DFLEXLEXER_INCLUDE_PATH=c:\ProgramData\chocolatey\lib\winflexbison3\tools\ cmake --build . cmake --build . --target install displayName: 'build' @@ -164,7 +164,7 @@ jobs: cd starter md build cd build - cmake .. -DZ3_INCLUDE_DIR=$(Build.Repository.LocalPath)/z3/include -DZ3_LIBRARY=$(Build.Repository.LocalPath)/z3/bin/libz3.lib -DZ3_EXEC=$(Build.Repository.LocalPath)/z3/bin/z3.exe + cmake .. -DZ3_INCLUDE_DIR=$(Build.Repository.LocalPath)/z3/include -DZ3_LIBRARY=$(Build.Repository.LocalPath)/z3/bin/libz3.lib -DZ3_EXEC=$(Build.Repository.LocalPath)/z3/bin/z3.exe -DFLEXLEXER_INCLUDE_PATH=c:\ProgramData\chocolatey\lib\winflexbison3\tools\ cmake --build . displayName: 'starter' From 93124229713712d5d2681d56b20b181af0059fb6 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 26 Nov 2021 15:43:03 +0800 Subject: [PATCH 67/78] update vexpparser ref --- extern/vexpparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vexpparser b/extern/vexpparser index 4892ccfaa..4b6131e7b 160000 --- a/extern/vexpparser +++ b/extern/vexpparser @@ -1 +1 @@ -Subproject commit 4892ccfaa3c04a9da72ee062399c114501477788 +Subproject commit 4b6131e7be72a962c2e75e884dbb5a9424b7703d From af7b268fc1ed19d2ab327498fff98208d402f662 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 28 Nov 2021 14:43:13 +0800 Subject: [PATCH 68/78] add quantified support in rfexpr --- include/ilang/rfmap-in/rfmap_typecheck.h | 33 +- src/rfmap-in/rfexpr_to_smt.cc | 18 +- src/rfmap-in/rfmap_typecheck.cc | 377 ++++++++++++++++++----- src/rfmap-in/verilog_rfmap.cc | 4 +- src/vtarget-out/gen_util.cc | 4 +- src/vtarget-out/single_target_as.cc | 15 +- src/vtarget-out/single_target_misc.cc | 2 +- test/t_rfexpr_smt_out.cc | 40 ++- 8 files changed, 386 insertions(+), 107 deletions(-) diff --git a/include/ilang/rfmap-in/rfmap_typecheck.h b/include/ilang/rfmap-in/rfmap_typecheck.h index 6d6a369be..ee669988c 100644 --- a/include/ilang/rfmap-in/rfmap_typecheck.h +++ b/include/ilang/rfmap-in/rfmap_typecheck.h @@ -87,7 +87,8 @@ class TypeAnalysisUtility { public: /// Annotate the type of a refinement expression /// and this process will be recursive - static void AnnotateType(const RfExpr& inout); + static void AnnotateType(const RfExpr& inout, + const std::map & quantified_var_type); protected: // internal use only, does not do recursion itself @@ -97,9 +98,27 @@ class TypeAnalysisUtility { }; // struct TypeAnalysisUtility class RfExprAstUtility { +private: + /// will only replace the free var, so we need to keep track + /// if some var inside are quantified, in that case, should not mask + static RfExpr ReplaceQuantifiedVar(const std::string &n, + const RfExpr & in, const RfExpr & newexpr, + const std::set & quantified_var); + + /// expand the current one, should be invoked from the leaf node + static RfExpr QuantifierInstantiation(const RfExpr& in); + public: - static bool HasArrayVar(const RfExpr& in, - std::map& array_var); + /// determine if a rf expr has array variable in it + static bool HasArrayVar(const RfExpr& in); + /// determine if a rf expr has quantifier in it + static bool HasQuantifier(const RfExpr& in); + /// for pono, this will cause to use text + /// FORALL -> /\ /\ /\ ... (JasperGold) + /// EXISTS -> \/ \/ \/ ... + static RfExpr FindExpandQuantifier(const RfExpr& in); + + /// determine if a rf expr is a boolean expr static bool IsLastLevelBooleanOp(const RfExpr& in); /// get the variables from a expression @@ -110,6 +129,10 @@ class RfExprAstUtility { /// because we will be creating new rfexpr static RfExpr TraverseRfExpr(const RfExpr& inout, std::function func); + /// will modify where the pointer is pointing to + /// because we will be creating new rfexpr + static void TraverseRfExprNoModify(const RfExpr& inout, + std::function func); /// check to make sure no null ptr static void RfMapNoNullNode(const RfExpr& in); }; @@ -118,7 +141,7 @@ struct RfExprVarReplUtility { public: /// used by vtarget_gen to replace rtl/ila vars - RfExpr ReplacingRtlIlaVar(const RfExpr& in); + RfExpr ReplacingRtlIlaVar(const RfExpr& in, const std::set & quantified_vars); /// Register internal variables and also the mapping void RegisterInternalVariableWithMapping(const std::string& n, @@ -187,7 +210,7 @@ struct TypedVerilogRefinementMap : public VerilogRefinementMap, // (1) value holder/delay : width determination // will use all_var_def_types & typechecker // (2) vlg-monitor replace-var - RfMapVarType TypeInferTravserRfExpr(const RfExpr& in); + RfMapVarType TypeInferTravserRfExpr(const RfExpr& in, const std::map local_var_def); protected: // used in TypedVerilogRefinementMap::TypeInferTravserRfExpr diff --git a/src/rfmap-in/rfexpr_to_smt.cc b/src/rfmap-in/rfexpr_to_smt.cc index 6863d3d6b..0c3af4e36 100644 --- a/src/rfmap-in/rfexpr_to_smt.cc +++ b/src/rfmap-in/rfexpr_to_smt.cc @@ -43,7 +43,8 @@ static std::vector voperator_str_smt = { /*Placeholder*/ "MK_CONST", "MK_VAR", - "#notsupported" // delay + "#notsupported", // delay + "#special", "#special" // forall and exist }; static RfMapVarType get_type(const RfExpr& in) { @@ -436,6 +437,21 @@ std::string RfExpr2Smt::to_smt2(const RfExpr& in, SmtType expected_type) { return type_convert(expected_type, SmtType(parent_tp, false), ret); } + + if(op_ == verilog_expr::voperator::FORALL || op_ == verilog_expr::voperator::EXIST) { + ILA_ASSERT(in->get_child_cnt() == 1); + ILA_ASSERT(in->get_str_parameter().size() == 1); + ILA_ASSERT(in->get_parameter().size() == 1); + const std::string & qvar = in->get_str_parameter().at(0); + auto width = in->get_parameter().at(0); + + std::string c1 = + to_smt2(child_.at(0), SmtType(get_type(child_.at(0)), true)); + std::string quantifier = op_ == verilog_expr::voperator::FORALL ? "forall" : "exists"; + std::string ret = "(" + quantifier + " ((" + qvar + " (_ BitVec " + std::to_string(width) + "))) " + c1 + ")"; + return type_convert(expected_type, SmtType(), ret); // convert bool : SmtType() to expected type + } + throw verilog_expr::VexpException( verilog_expr::ExceptionCause::UntranslatedSmtlib2); diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index e0f4dc696..a01bbd274 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -8,6 +8,7 @@ #include #include #include +#include namespace ilang { namespace rfmap { @@ -50,7 +51,7 @@ void TypedVerilogRefinementMap::initialize() { } // initialize // this function will iteratively make a new copy of the whole AST. -RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar(const RfExpr& in) { +RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar(const RfExpr& in, const std::set & quantified_vars) { // skip state memory mapped // provide a function to ReplExpr... @@ -60,6 +61,8 @@ RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar(const RfExpr& in) { auto var_ptr = std::dynamic_pointer_cast(in); ILA_NOT_NULL(var_ptr); auto n = var_ptr->get_name(); + if(quantified_vars.find(n.first) != quantified_vars.end()) + return in; // will not replace a quantified variable ILA_CHECK(var_replacement.find(n.first) != var_replacement.end()) << "variable " << n.first << " has no replacement"; @@ -70,8 +73,18 @@ RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar(const RfExpr& in) { } // else is op std::vector retchild; - for (size_t idx = 0; idx < in->get_child_cnt(); ++idx) { - retchild.push_back(ReplacingRtlIlaVar(in->get_child().at(idx))); + bool has_quantifier = + in->get_op() == verilog_expr::voperator::EXIST || + in->get_op() == verilog_expr::voperator::FORALL; + if(has_quantifier) { + std::set new_quantified_vars(quantified_vars); + ILA_ASSERT(in->get_child_cnt() == 1 && in->get_str_parameter().size() == 1); + new_quantified_vars.insert(in->get_str_parameter().at(0)); // the quantified var + retchild.push_back(ReplacingRtlIlaVar(in->get_child().at(0), new_quantified_vars)); + } else { + for (size_t idx = 0; idx < in->get_child_cnt(); ++idx) { + retchild.push_back(ReplacingRtlIlaVar(in->get_child().at(idx), quantified_vars)); + } } auto ret = in->MakeCopyWithNewChild(retchild); ret->set_annotation(in->get_annotation()); @@ -80,9 +93,9 @@ RfExpr RfExprVarReplUtility::ReplacingRtlIlaVar(const RfExpr& in) { RfExpr TypedVerilogRefinementMap::collect_inline_value_recorder_func( const RfExpr& in) { - if (in->get_op() != verilog_expr::voperator::AT) + if (in->get_op() != verilog_expr::voperator::AT) return in; - + auto recorder_name = new_id() + "recorder"; auto new_node = verilog_expr::VExprAst::MakeVar(recorder_name); @@ -109,8 +122,7 @@ RfExpr TypedVerilogRefinementMap::collect_inline_delay_func(const RfExpr& in) { // else assert(in->get_parameter().size() == in->get_str_parameter().size()); assert(in->get_child().size() == 1 || in->get_child().size() == 2); - assert(in->get_parameter().size() == 1 || - in->get_parameter().size() == 2); + assert(in->get_parameter().size() == 1 || in->get_parameter().size() == 2); auto delay_name = new_id() + "delay"; auto new_node = VExprAst::MakeVar(delay_name); @@ -118,15 +130,14 @@ RfExpr TypedVerilogRefinementMap::collect_inline_delay_func(const RfExpr& in) { if (in->get_parameter().size() == 1) { // Single a ##n int delay = in->get_parameter().at(0); - aux_delays.emplace(delay_name, - SignalDelay(in->get_child().at(0), delay)); + aux_delays.emplace(delay_name, SignalDelay(in->get_child().at(0), delay)); // std::cout << "SingleDelay:" <get_child().at(0) <get_parameter().size() == 2 // RANGE/INF a ##[n,m] / ##[n,0] 0 represents $ int delay = in->get_parameter().at(0); int delay_upper = in->get_parameter().at(1); - aux_delays.emplace(delay_name, SignalDelay(in->get_child().at(0), - delay, delay_upper)); + aux_delays.emplace(delay_name, + SignalDelay(in->get_child().at(0), delay, delay_upper)); // std::cout << "2Delay:" <get_child().at(0) < func) { for (auto& sv : ila_state_var_map) { if (sv.second.type == IlaVarMapping::StateVarMapType::SINGLE) - sv.second.single_map.single_map = TraverseRfExpr(sv.second.single_map.single_map, func); + sv.second.single_map.single_map = + TraverseRfExpr(sv.second.single_map.single_map, func); else if (sv.second.type == IlaVarMapping::StateVarMapType::CONDITIONAL) { for (auto& c : sv.second.single_map.cond_map) { c.first = TraverseRfExpr(c.first, func); @@ -251,7 +263,8 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr( for (auto& sv : ila_input_var_map) { if (sv.second.type == IlaVarMapping::StateVarMapType::SINGLE) - sv.second.single_map.single_map = TraverseRfExpr(sv.second.single_map.single_map, func); + sv.second.single_map.single_map = + TraverseRfExpr(sv.second.single_map.single_map, func); else /* if(sv.second.type == IlaVarMapping::StateVarMapType::CONDITIONAL) */ { for (auto& c : sv.second.single_map.cond_map) { @@ -278,7 +291,7 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr( a.second = TraverseRfExpr(a.second, func); for (auto& r : ptracker.second.rules) { r.enter_rule = TraverseRfExpr(r.enter_rule, func); - if(r.exit_rule) + if (r.exit_rule) r.exit_rule = TraverseRfExpr(r.exit_rule, func); for (auto& act : r.enter_action) act.RHS = TraverseRfExpr(act.RHS, func); @@ -299,7 +312,8 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr( for (auto& instcond : inst_complete_cond) { if (instcond.second.type == InstructionCompleteCondition::ConditionType::SIGNAL) - instcond.second.ready_signal = TraverseRfExpr(instcond.second.ready_signal, func); + instcond.second.ready_signal = + TraverseRfExpr(instcond.second.ready_signal, func); for (auto& cond : instcond.second.start_condition) cond = TraverseRfExpr(cond, func); } @@ -307,7 +321,7 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr( for (auto& a : global_invariants) a = TraverseRfExpr(a, func); - for (auto& p_rf: rtl_interface_connection.input_port_connection) { + for (auto& p_rf : rtl_interface_connection.input_port_connection) { p_rf.second = TraverseRfExpr(p_rf.second, func); } @@ -338,7 +352,7 @@ bool _compute_const(const RfExpr& in, unsigned& out) { void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { for (auto& name_delay_pair : aux_delays) { if (name_delay_pair.second.width == 0) { - auto tp = TypeInferTravserRfExpr(name_delay_pair.second.signal); + auto tp = TypeInferTravserRfExpr(name_delay_pair.second.signal, {}); ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; ILA_ERROR_IF(tp.is_unknown()) @@ -356,7 +370,7 @@ void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { } for (auto& name_vr : value_recorder) { if (name_vr.second.width == 0) { - auto tp = TypeInferTravserRfExpr(name_vr.second.value); + auto tp = TypeInferTravserRfExpr(name_vr.second.value, {}); ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; ILA_ERROR_IF(tp.is_unknown()) @@ -373,9 +387,9 @@ void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { } // replendish internal defined vars for (auto& n_expr : direct_aux_vars) { - if(n_expr.second.width == 0) { + if (n_expr.second.width == 0) { - auto tp = TypeInferTravserRfExpr(n_expr.second.val); + auto tp = TypeInferTravserRfExpr(n_expr.second.val, {}); ILA_ERROR_IF(tp.is_array()) << "Currently does not support to delay a memory variable"; ILA_ERROR_IF(tp.is_unknown()) @@ -391,8 +405,12 @@ void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { } // ComputeDelayValueHolderWidth // relies on typechecker and all_var_def_types -RfMapVarType -TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { +RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr( + const RfExpr& in, const std::map local_var_def) { + + ILA_CHECK(local_var_def.empty()); + // I believe we will never need to go into + // a forall/exists case because it is boolean! if (in->is_constant()) { auto c = std::dynamic_pointer_cast(in) @@ -402,6 +420,14 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { auto n = std::dynamic_pointer_cast(in)->get_name(); + auto local_var_pos = local_var_def.find(n.first); + if (local_var_pos != local_var_def.end()) { + ILA_WARN_IF(n.second) << n.first + << " is regarded as quantified variable, which " + "should not be a special name"; + return RfMapVarType(local_var_pos->second); + } + auto pos_def_var = all_var_def_types.find(n.first); if (n.second) { // is a special name @@ -429,19 +455,18 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { << " determined var " << n.first; return RfMapVarType(pos_def_var->second.width); } - } // if # ... # else not return RfMapVarType(); // unknown type } else { // has op - if ( in->get_child_cnt() == 1 && ( - in->get_op() == voperator::B_AND || // & a - in->get_op() == voperator::B_NAND || // ~& a - in->get_op() == voperator::B_OR || // | a - in->get_op() == voperator::B_NOR || // ~| a - in->get_op() == voperator::B_XOR || // ^ a - in->get_op() == voperator::B_EQU // "^~"|"~^" - ) ) { + if (in->get_child_cnt() == 1 && + (in->get_op() == voperator::B_AND || // & a + in->get_op() == voperator::B_NAND || // ~& a + in->get_op() == voperator::B_OR || // | a + in->get_op() == voperator::B_NOR || // ~| a + in->get_op() == voperator::B_XOR || // ^ a + in->get_op() == voperator::B_EQU // "^~"|"~^" + )) { return RfMapVarType(1); } @@ -461,7 +486,8 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { unsigned nchild = in->get_child_cnt(); unsigned maxw = 0; for (size_t idx = 0; idx < nchild; idx++) { - RfMapVarType t = TypeInferTravserRfExpr(in->get_child().at(idx)); + RfMapVarType t = + TypeInferTravserRfExpr(in->get_child().at(idx), local_var_def); if (t.is_bv()) maxw = std::max(maxw, t.unified_width()); } @@ -472,7 +498,7 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { in->get_op() == verilog_expr::voperator::LSR || in->get_op() == verilog_expr::voperator::AT) { // the left type assert(in->get_child_cnt() == 2); - return TypeInferTravserRfExpr(in->get_child().at(0)); + return TypeInferTravserRfExpr(in->get_child().at(0), local_var_def); } else if (in->get_op() == verilog_expr::voperator::DELAY) { // arg 1: width of first // arg 2: width is 1 !!! @@ -481,7 +507,7 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { return RfMapVarType(1); // set return type to be the same as the first one - return TypeInferTravserRfExpr(in->get_child().at(0)); + return TypeInferTravserRfExpr(in->get_child().at(0), local_var_def); } else if (in->get_op() == verilog_expr::voperator::GTE || in->get_op() == verilog_expr::voperator::LTE || in->get_op() == verilog_expr::voperator::GT || @@ -495,7 +521,8 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { in->get_op() == verilog_expr::voperator::L_OR) { return RfMapVarType(1); } else if (in->get_op() == verilog_expr::voperator::INDEX) { - RfMapVarType child_type = TypeInferTravserRfExpr(in->get_child().at(0)); + RfMapVarType child_type = + TypeInferTravserRfExpr(in->get_child().at(0), local_var_def); if (child_type.is_array()) return RfMapVarType(child_type.unified_width()); // data width // TODO: check index within ? @@ -524,10 +551,10 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { } else if (in->get_op() == verilog_expr::voperator::STORE_OP) { // TODO: check width! // actually not implemented - return TypeInferTravserRfExpr(in->get_child().at(0)); + return TypeInferTravserRfExpr(in->get_child().at(0), local_var_def); } else if (in->get_op() == verilog_expr::voperator::TERNARY) { - auto left = TypeInferTravserRfExpr(in->get_child().at(1)); - auto right = TypeInferTravserRfExpr(in->get_child().at(2)); + auto left = TypeInferTravserRfExpr(in->get_child().at(1), local_var_def); + auto right = TypeInferTravserRfExpr(in->get_child().at(2), local_var_def); if (left.is_array() || right.is_array()) return left; // TODO: check compatibility return RfMapVarType( @@ -538,7 +565,8 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { unsigned nchild = in->get_child_cnt(); unsigned sumw = 0; for (size_t idx = 0; idx < nchild; idx++) { - RfMapVarType t = TypeInferTravserRfExpr(in->get_child().at(idx)); + RfMapVarType t = + TypeInferTravserRfExpr(in->get_child().at(idx), local_var_def); if (t.is_bv()) sumw += t.unified_width(); else @@ -550,8 +578,18 @@ TypedVerilogRefinementMap::TypeInferTravserRfExpr(const RfExpr& in) { unsigned ntimes; if (!_compute_const(in->get_child().at(0), ntimes)) return RfMapVarType(); - auto tp = TypeInferTravserRfExpr(in->get_child().at(1)); + auto tp = TypeInferTravserRfExpr(in->get_child().at(1), local_var_def); return RfMapVarType(tp.unified_width() * ntimes); + } else if (in->get_op() == verilog_expr::voperator::FORALL || + in->get_op() == verilog_expr::voperator::EXIST) { + + return RfMapVarType(1); + // std::map new_var_def; + // const auto& sparam = in->get_str_parameter(); + // const auto& param = in->get_parameter(); + // ILA_CHECK(sparam.size() == 1 && param.size() == 1); + // new_var_def.emplace(sparam.at(0), param.at(0)); + // return TypeInferTravserRfExpr(in->get_child().at(0), new_var_def); } ILA_ASSERT(false) << "BUG: Operator " << int(in->get_op()) << " is not handled"; @@ -573,37 +611,161 @@ void RfExprAstUtility::GetVars( const RfExpr& in, std::unordered_map& vars_out) { // bfs walk std::vector> stack; + std::vector> quantified_vars; stack.push_back(std::make_pair(in, false)); + quantified_vars.push_back({}); while (!stack.empty()) { auto& back = stack.back(); + const auto &curr_quantified_var = quantified_vars.back(); + auto backvar = back.first; if (back.second) { + quantified_vars.pop_back(); stack.pop_back(); continue; } // back.second == false back.second = true; - for (const auto& c : backvar->get_child()) - stack.push_back(std::make_pair(c, false)); if (backvar->is_var()) { ILA_ASSERT(backvar->get_child().size() == 0); verilog_expr::VExprAstVar::VExprAstVarPtr varptr = std::dynamic_pointer_cast(backvar); ILA_NOT_NULL(varptr); - vars_out.emplace(varptr->get_name().first, varptr); - } + const auto name = varptr->get_name().first; + if(curr_quantified_var.find(name) == curr_quantified_var.end()) + vars_out.emplace(name, varptr); // only add it if not quantified + } // end of is_var + else { + auto new_quantified_var(curr_quantified_var); // this is necessary + // because reference could become invalid when you start to push + if(backvar->get_op() == verilog_expr::voperator::FORALL || + backvar->get_op() == verilog_expr::voperator::EXIST) { + new_quantified_var.insert(backvar->get_str_parameter().at(0)); + } + + for (const auto& c : backvar->get_child()) { + stack.push_back(std::make_pair(c, false)); + quantified_vars.push_back(new_quantified_var); + } // end - for each child + } // end of else } // end while (stack is not empty) } // end of GetVars -bool RfExprAstUtility::HasArrayVar(const RfExpr& in, - std::map& array_var) { + +/// will only replace the free var, so we need to keep track +/// if some var inside are quantified, in that case, should not mask +/// EXPECT: newexpr has annnotation !!! +RfExpr RfExprAstUtility::ReplaceQuantifiedVar(const std::string &name, + const RfExpr & in, const RfExpr & newexpr, + const std::set & quantified_var) { + // traverse the tree + if (in->is_var()) { + auto var_ptr = std::dynamic_pointer_cast(in); + ILA_NOT_NULL(var_ptr); + auto n = var_ptr->get_name(); + // will only replace free var + if(quantified_var.find(n.first) != quantified_var.end()) + return in; + if (n.first == name) + return newexpr; + return in; + } else if (in->is_constant()) { + return in; + } + // else is op + std::set p_quantified_var(quantified_var); + if(in->get_op() == verilog_expr::voperator::FORALL || + in->get_op() == verilog_expr::voperator::EXIST) { + ILA_ASSERT(in->get_str_parameter().size() == 1); + p_quantified_var.insert(in->get_str_parameter().at(0)); + } + + std::vector retchild; + for (size_t idx = 0; idx < in->get_child_cnt(); ++idx) { + retchild.push_back( + ReplaceQuantifiedVar( + name, + in->get_child().at(idx), + newexpr, + p_quantified_var + )); + } + auto ret = in->MakeCopyWithNewChild(retchild); + ret->set_annotation(in->get_annotation()); + return ret; +} // END of ReplaceQuantifiedVar + +/// expand the current one, should be invoked from the leaf node +RfExpr RfExprAstUtility::QuantifierInstantiation(const RfExpr& in) { + ILA_CHECK(in->get_op() == verilog_expr::voperator::FORALL || + in->get_op() == verilog_expr::voperator::EXIST); + ILA_ASSERT(in->get_str_parameter().size() == 1); + ILA_ASSERT(in->get_parameter().size() == 1); + ILA_ASSERT(in->get_child_cnt() == 1); + + auto child = in->get_child().at(0); + bool use_and = in->get_op() == verilog_expr::voperator::FORALL; + auto anno = in->get_annotation(); + ILA_WARN_IF(anno && anno->type.unified_width() != 1) + << "FORALL/EXIST has non-Boolean Formula as child"; + + const std::string quantified_var_name = in->get_str_parameter().at(0); + const int quantified_var_width = in->get_parameter().at(0); + ILA_CHECK(quantified_var_width <= 32) + << "Quantifier instantiation for width > 32 is strongly discouraged"; + long long range = std::pow(2,quantified_var_width); + RfExpr ret = nullptr; + for(long long idx = 0; idx < range; ++idx) { + auto new_const = verilog_expr::VExprAst::MakeConstant(10, quantified_var_width, std::to_string(idx)); + + RfVarTypeOrig tp; + tp.type = + RfMapVarType(quantified_var_width); // base, width,... + new_const->set_annotation(std::make_shared(tp)); + RfExpr repl = ReplaceQuantifiedVar(quantified_var_name, child, new_const, {}); + if(ret == nullptr) + ret = repl; + else + ret = verilog_expr::VExprAst::MakeBinaryAst( + use_and ? verilog_expr::voperator::L_AND : verilog_expr::voperator::L_OR, + repl, ret); + ret->set_annotation(anno); + } + return ret; +} // END of QuantifierInstantiation + + +/// determine if a rf expr has quantifier in it +bool RfExprAstUtility::HasQuantifier(const RfExpr& in) { + bool ret = false; + TraverseRfExprNoModify(in, [&ret](const RfExpr &e) -> void { + if(e->get_op() == verilog_expr::voperator::EXIST || + e->get_op() == verilog_expr::voperator::FORALL) + ret = true; + } ); + return ret; +} +/// for pono, this will cause to use text +/// FORALL -> /\ /\ /\ ... (JasperGold) +/// EXISTS -> \/ \/ \/ ... +RfExpr RfExprAstUtility::FindExpandQuantifier(const RfExpr& in) { + return TraverseRfExpr(in, [](const RfExpr &e) -> RfExpr{ + if(e->get_op() == verilog_expr::voperator::EXIST || + e->get_op() == verilog_expr::voperator::FORALL) + return QuantifierInstantiation(e); + // else + return e; + }); +} + +bool RfExprAstUtility::HasArrayVar(const RfExpr& in) { if (in->is_var()) { auto anno = in->get_annotation(); ILA_NOT_NULL(anno); auto memvar = std::dynamic_pointer_cast(in); ILA_NOT_NULL(memvar); if (anno->type.is_array()) { - array_var.emplace(std::get<0>(memvar->get_name()), memvar); + // array_var.emplace(std::get<0>(memvar->get_name()), memvar); return true; } return false; @@ -612,7 +774,9 @@ bool RfExprAstUtility::HasArrayVar(const RfExpr& in, } bool has_array = false; for (size_t idx = 0; idx < in->get_child_cnt(); idx++) { - has_array = has_array || HasArrayVar(in->get_child().at(idx), array_var); + has_array = has_array || HasArrayVar(in->get_child().at(idx)); + if (has_array) + break; } return has_array; } @@ -624,12 +788,33 @@ void RfExprAstUtility::RfMapNoNullNode(const RfExpr& in) { RfMapNoNullNode(in->get_child().at(idx)); } -RfExpr RfExprAstUtility::TraverseRfExpr(const RfExpr& in, - std::function func) { +void RfExprAstUtility::TraverseRfExprNoModify(const RfExpr& in, + std::function func) { + ILA_NOT_NULL(in); + std::vector> parent_stack; + while (!parent_stack.empty()) { + auto& lastlv = parent_stack.back(); + auto cnt = lastlv.first->get_child_cnt(); + auto& idx = lastlv.second; + if (idx >= cnt) { // also cnt could be 0 (leaf) + func(lastlv.first); + parent_stack.pop_back(); + if (!parent_stack.empty()) + ++parent_stack.back().second; + continue; + } + ILA_ASSERT(lastlv.first->get_child_cnt() != 0); + parent_stack.push_back( + std::make_pair(lastlv.first->get_child().at(idx), 0U)); + } +} + +RfExpr RfExprAstUtility::TraverseRfExpr( + const RfExpr& in, std::function func) { ILA_NOT_NULL(in); std::vector> child_stack; child_stack.push_back({}); - child_stack.push_back({}); + child_stack.push_back({}); // Yes, do it twice! std::vector> parent_stack; parent_stack.push_back(std::make_pair(in, 0U)); while (!parent_stack.empty()) { @@ -643,12 +828,13 @@ RfExpr RfExprAstUtility::TraverseRfExpr(const RfExpr& in, child_stack.pop_back(); child_stack.back().push_back(new_node); parent_stack.pop_back(); - if(!parent_stack.empty()) + if (!parent_stack.empty()) ++parent_stack.back().second; continue; } // else ILA_CHECK(lastlv.first->get_child_cnt() != 0); - parent_stack.push_back(std::make_pair(lastlv.first->get_child().at(idx), 0U)); + parent_stack.push_back( + std::make_pair(lastlv.first->get_child().at(idx), 0U)); child_stack.push_back({}); } // end of while ILA_CHECK(child_stack.size() == 1); @@ -679,14 +865,27 @@ bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr& in) { // differences from TypedVerilogRefinementMap::ReplacingRtlIlaVar // 1. no var replacement (__ILA_I_, __ILA_SO_, __DOT__), array[idx] // 2. no special name handling -// 3. this is used only in unit test -void TypeAnalysisUtility::AnnotateType(const RfExpr& inout) { +void TypeAnalysisUtility::AnnotateType(const RfExpr& inout, + const std::map & quantified_var_type) +{ auto tp_annotate = inout->get_annotation(); if (inout->is_var()) { auto ptr = std::dynamic_pointer_cast(inout); + const auto & n = ptr->get_name().first; + if(tp_annotate == nullptr || tp_annotate->type.is_unknown()) { + // if it is a quantified var, then we can annotate its type + auto type_pos = quantified_var_type.find(n); + if(type_pos != quantified_var_type.end()) { + auto width = type_pos->second; + RfVarTypeOrig tp; + tp.type = RfMapVarType(width); // base, width,... + tp_annotate = std::make_shared(tp); + inout->set_annotation(tp_annotate); + } + } ILA_CHECK(tp_annotate != nullptr && !tp_annotate->type.is_unknown()) - << ptr->get_name().first << " has no type annotation"; + << n << " has no type annotation"; } else if (inout->is_constant()) { if (tp_annotate == nullptr || tp_annotate->type.is_unknown()) { RfVarTypeOrig tp; @@ -698,8 +897,21 @@ void TypeAnalysisUtility::AnnotateType(const RfExpr& inout) { inout->set_annotation(std::make_shared(tp)); } // end if no annotation } else { // op - for (size_t idx = 0; idx < inout->get_child_cnt(); ++idx) - AnnotateType(inout->get_child().at(idx)); + bool has_quantifier = + inout->get_op() == verilog_expr::voperator::EXIST || + inout->get_op() == verilog_expr::voperator::FORALL; + if(has_quantifier) { + ILA_ASSERT(inout->get_child_cnt() == 1 && + inout->get_str_parameter().size() == 1 && + inout->get_parameter().size() == 1 + ); + std::map new_quantified_dict (quantified_var_type); + new_quantified_dict.emplace(inout->get_str_parameter().at(0), + inout->get_parameter().at(0)); + AnnotateType(inout->get_child().at(0), new_quantified_dict); + } else + for (size_t idx = 0; idx < inout->get_child_cnt(); ++idx) + AnnotateType(inout->get_child().at(idx), quantified_var_type); infer_type_based_on_op_child(inout); // for each child } // end if-else- op @@ -709,15 +921,14 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { assert(inout->get_op() != verilog_expr::voperator::MK_CONST && inout->get_op() != verilog_expr::voperator::MK_VAR); - if ( inout->get_child_cnt() == 1 && - ( - inout->get_op() == voperator::B_AND || - inout->get_op() == voperator::B_NAND || - inout->get_op() == voperator::B_OR || - inout->get_op() == voperator::B_NOR || - inout->get_op() == voperator::B_XOR || - inout->get_op() == voperator::B_EQU // "^~"|"~^" - ) ) { + if (inout->get_child_cnt() == 1 && + (inout->get_op() == voperator::B_AND || + inout->get_op() == voperator::B_NAND || + inout->get_op() == voperator::B_OR || + inout->get_op() == voperator::B_NOR || + inout->get_op() == voperator::B_XOR || + inout->get_op() == voperator::B_EQU // "^~"|"~^" + )) { auto new_annotation = std::make_shared(); new_annotation->type = RfMapVarType(1); inout->set_annotation(new_annotation); @@ -757,7 +968,8 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { inout->get_op() == verilog_expr::voperator::LSR || inout->get_op() == verilog_expr::voperator::AT) { // the left type assert(inout->get_child_cnt() == 2); - inout->set_annotation(inout->get_child().at(0)->get_annotation()); + inout->set_annotation( + inout->get_child().at(0)->get_annotation()); return; } else if (inout->get_op() == verilog_expr::voperator::DELAY) { // arg 1: width of first @@ -771,7 +983,8 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { } // set return type to be the same as the first one - inout->set_annotation(inout->get_child().at(0)->get_annotation()); + inout->set_annotation( + inout->get_child().at(0)->get_annotation()); return; } else if (inout->get_op() == verilog_expr::voperator::GTE || @@ -829,11 +1042,13 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { return; } else if (inout->get_op() == verilog_expr::voperator::STORE_OP) { - inout->set_annotation(inout->get_child().at(0)->get_annotation()); + inout->set_annotation( + inout->get_child().at(0)->get_annotation()); return; } else if (inout->get_op() == verilog_expr::voperator::TERNARY) { - inout->set_annotation(inout->get_child().at(1)->get_annotation()); + inout->set_annotation( + inout->get_child().at(1)->get_annotation()); return; } else if (inout->get_op() == verilog_expr::voperator::FUNCTION_APP) { ILA_ASSERT(false); @@ -855,15 +1070,29 @@ void TypeAnalysisUtility::infer_type_based_on_op_child(const RfExpr& inout) { return; } else if (inout->get_op() == verilog_expr::voperator::REPEAT) { assert(inout->get_child_cnt() == 2); - unsigned ntimes; + unsigned ntimes = 0; if (!_compute_const(inout->get_child().at(0), ntimes)) ILA_ASSERT(false); - auto tp = (inout->get_child().at(1)->get_annotation()->type); + auto tp = + (inout->get_child().at(1)->get_annotation()->type); auto new_annotation = std::make_shared(); new_annotation->type = RfMapVarType(tp.unified_width() * ntimes); inout->set_annotation(new_annotation); + return; + } else if (inout->get_op() == verilog_expr::voperator::FORALL || + inout->get_op() == verilog_expr::voperator::EXIST) { + assert(inout->get_child_cnt() == 1); + auto child_anno = inout->get_child().at(0)->get_annotation(); + ILA_ERROR_IF(child_anno == nullptr || + !child_anno->type.is_bv() || + child_anno->type.unified_width() != 1) << "type-check: FORALL/EXIST requires Boolean sub-formula"; + + auto new_annotation = std::make_shared(); + new_annotation->type = RfMapVarType(1); + inout->set_annotation(new_annotation); + return; } ILA_ASSERT(false) << "BUG: Operator " << int(inout->get_op()) diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index 8f89e61d8..c36ca301c 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -421,8 +421,8 @@ std::string JsonRfmapParsePhaseTracker(PhaseTracker& tracker, nlohmann::json& monitor, const std::string& tracker_name) { auto* event_alias = GetJsonSection(monitor, {"event-alias", "signal-alias"}); - auto* rules = GetJsonSection(monitor, {"rules"}); - auto* aux_var = GetJsonSection(monitor, {"aux-var"}); + auto* rules = GetJsonSection(monitor, {"rules","rule", "phase", "phases", "stage", "stages"}); + auto* aux_var = GetJsonSection(monitor, {"aux-var", "def", "defs", "var-def", "var-defs"}); ERRIF(rules == NULL, "`phase tracker` needs `rules` field"); if (event_alias) { ERRIF(!event_alias->is_object(), "`event-alias` expects map:name->expr"); diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 35af1c3d0..3688dd02c 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -326,9 +326,9 @@ rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr& in) { << repl->origvar->to_verilog() << " --> " << repl->newvar->to_verilog(); } - auto new_node = refinement_map.ReplacingRtlIlaVar(in); + auto new_node = refinement_map.ReplacingRtlIlaVar(in, {}); // AnnotateType requires all - refinement_map.AnnotateType(new_node); + refinement_map.AnnotateType(new_node, {}); return new_node; } diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index 78028b5e7..2d9da57d9 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -326,8 +326,7 @@ void VlgSglTgtGen:: ILA_DLOG("VTG.AddWireEq") << GetVlg(eq); - std::map array_var; - if (rfmap::RfExprAstUtility::HasArrayVar(eq, array_var)) { + if (rfmap::RfExprAstUtility::HasArrayVar(eq)) { ILA_ERROR_IF(!_vtg_config.YosysSmtArrayForRegFile) << "Requiring array sort in Yosys when generating" << " properties, please enable YosysSmtArrayForRegFile"; @@ -341,8 +340,7 @@ void VlgSglTgtGen:: for (const auto& aspt : dspt_aspt.second) { ILA_DLOG("VTG.AddAssume") << GetVlg(aspt); - std::map array_var; - if (rfmap::RfExprAstUtility::HasArrayVar(aspt, array_var)) { + if (rfmap::RfExprAstUtility::HasArrayVar(aspt)) { ILA_ERROR_IF(!_vtg_config.YosysSmtArrayForRegFile) << "Requiring array sort in Yosys when generating" << " properties, please enable YosysSmtArrayForRegFile"; @@ -356,8 +354,7 @@ void VlgSglTgtGen:: for (const auto& asst : dspt_asst.second) { ILA_DLOG("VTG.AddAssert") << GetVlg(asst); - std::map array_var; - if (rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) + if (rfmap::RfExprAstUtility::HasArrayVar(asst)) add_smt_assertion(asst, dspt_asst.first); else add_a_direct_assertion(GetVlg(asst), dspt_asst.first); @@ -366,8 +363,7 @@ void VlgSglTgtGen:: for (const auto& dspt_asst : all_sanity_assertions) { for (const auto& asst : dspt_asst.second) { - std::map array_var; - ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(asst, array_var)) + ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(asst)) << "Implementation bug: sanity checking assertion should not contain " "arrays"; @@ -376,8 +372,7 @@ void VlgSglTgtGen:: } for (const auto& dspt_cvrs : all_covers) { for (const auto& cvr : dspt_cvrs.second) { - std::map array_var; - ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(cvr, array_var)) + ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(cvr)) << "Implementation bug: cover checks should not contain " "arrays"; diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index aae15a62e..67288288b 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -443,7 +443,7 @@ void VlgSglTgtGen::ConstructWrapper_add_vlg_monitor() { auto vref_node = rfmap::VerilogRefinementMap::ParseRfExprFromString(vref); auto new_name = mname + "_auxvar" + std::to_string(idx++); - auto tp = refinement_map.TypeInferTravserRfExpr(vref_node); + auto tp = refinement_map.TypeInferTravserRfExpr(vref_node, {}); ILA_ERROR_IF(tp.is_unknown()) << "Cannot determine width of " << vref << " in monitor " << mname; diff --git a/test/t_rfexpr_smt_out.cc b/test/t_rfexpr_smt_out.cc index a5614eb17..94b56341c 100644 --- a/test/t_rfexpr_smt_out.cc +++ b/test/t_rfexpr_smt_out.cc @@ -28,21 +28,24 @@ class TypeVars { newv->set_annotation(newtp_ptr); repl.RegisterInternalVariableWithMapping(v.first, rfmap::VarReplacement(v.second, newv)); } - return repl.ReplacingRtlIlaVar(inout); + return repl.ReplacingRtlIlaVar(inout, {}); } }; -#define PRINT_SMT(s, b) do { \ +#define PRINT_SMT(s, b, expand) do { \ std::string rfstr = (s); \ auto rfexpr = rfmap::VerilogRefinementMap::ParseRfExprFromString(rfstr); \ + if(expand) rfexpr = rfmap::RfExprAstUtility::FindExpandQuantifier(rfexpr); \ rfexpr = TypeVars::GiveVarTheirTypes(rfexpr, check_var_type); \ - annotator.AnnotateType(rfexpr); \ + annotator.AnnotateType(rfexpr, {}); \ ILA_DLOG("SMTOUT.TEST") << rfmap::RfExpr2Smt::to_smt2(rfexpr, \ (b) ? rfmap::SmtType() : \ rfmap::SmtType( (rfexpr->get_annotation())->type, false )) \ << std::endl; \ } while(0) +// + TEST(TestRfexpr, ToSmt) { // 1. construct var to rf_var_type map // and the function to map that @@ -68,15 +71,28 @@ TEST(TestRfexpr, ToSmt) { }; rfmap::TypeAnalysisUtility annotator; - - - PRINT_SMT("a[4] == b[4]" , true); // should be (extract) - PRINT_SMT("a[5:4] + c[4:3] != array1[a][2:1]" , true); // extract and select - PRINT_SMT(" c ? array1 : array2 " , false); // should handle array well - PRINT_SMT(" c == 1'b1? array1 : array2 " , false); // should be able to convert - PRINT_SMT(" array3[b+1] " , false); // should set the right type of 1 - PRINT_SMT(" a+b == c " , true); // should expand b, c - + bool expand = false; + { + PRINT_SMT("a[4] == b[4]" , true, expand); // should be (extract) + PRINT_SMT("a[5:4] + c[4:3] != array1[a][2:1]" , true, expand); // extract and select + PRINT_SMT(" c ? array1 : array2 " , false, expand); // should handle array well + PRINT_SMT(" c == 1'b1? array1 : array2 " , false, expand); // should be able to convert + PRINT_SMT(" array3[b+1] " , false, expand); // should set the right type of 1 + PRINT_SMT(" a+b == c " , true, expand); // should expand b, c + PRINT_SMT(" $forall(i:bv16 , array1[i+a] == array2[i]) " , true, expand); // should expand b, c + PRINT_SMT(" $exist(i:bv8 , array1[array3[i]] == array2[{8'd0, i}])" , true, expand); // should expand b, c + } + expand = true; + { + PRINT_SMT("a[4] == b[4]" , true, expand); // should be (extract) + PRINT_SMT("a[5:4] + c[4:3] != array1[a][2:1]" , true, expand); // extract and select + PRINT_SMT(" c ? array1 : array2 " , false, expand); // should handle array well + PRINT_SMT(" c == 1'b1? array1 : array2 " , false, expand); // should be able to convert + PRINT_SMT(" array3[b+1] " , false, expand); // should set the right type of 1 + PRINT_SMT(" a+b == c " , true, expand); // should expand b, c + PRINT_SMT(" $forall(i:bv2 , array1[{ 14'd0, i}+a] == array2[{ 14'd0, i}]) " , true, expand); // should expand b, c + PRINT_SMT(" $exist(i:bv3 , array1[array3[{5'd0,i}]] == array2[{13'd0, i}])" , true, expand); // should expand b, c + } } // TEST(TestRfexpr, ToSmt) } // namespace ilang From 6f96e80c56667b715006045705422addba393c41 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 28 Nov 2021 15:03:32 +0800 Subject: [PATCH 69/78] add quantifier handling in vtg --- include/ilang/rtl_verify.h | 3 +++ src/vtarget-out/gen_util.cc | 10 +++++++-- src/vtarget-out/single_target_as.cc | 32 ++++++++++++++++++++++------- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/include/ilang/rtl_verify.h b/include/ilang/rtl_verify.h index daed69cad..364fcb8c9 100644 --- a/include/ilang/rtl_verify.h +++ b/include/ilang/rtl_verify.h @@ -72,6 +72,8 @@ namespace ilang { // ----------- Options for Pono settings -------------- // /// Whether to force the instruction check to start from reset state bool ForceInstCheckReset; + /// Whether to always instiantiate quantifers in refinement + bool ForceQuantifierInstantiationInRfExpr; /// If true, will generate a separate check that cover the /// the commit condition bool CheckInstrCommitSatisfiable; @@ -214,6 +216,7 @@ namespace ilang { // ----------- Options for Pono settings -------------- // ForceInstCheckReset(false), + ForceQuantifierInstantiationInRfExpr(false), CheckInstrCommitSatisfiable(false), PortDeclStyle(PortDeclStyleT::AUTO), PonoVcdOutputName("cex.vcd"), PonoAddKeep(false), PonoEngine("ind"), diff --git a/src/vtarget-out/gen_util.cc b/src/vtarget-out/gen_util.cc index 3688dd02c..1cc212c7a 100644 --- a/src/vtarget-out/gen_util.cc +++ b/src/vtarget-out/gen_util.cc @@ -305,9 +305,15 @@ VlgSglTgtGen::CreateVarReplacement(const rfmap::RfVar& var, rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr& in) { bool replace_dot = _backend != ModelCheckerSelection::JASPERGOLD; + bool expand_quantifier = _backend != ModelCheckerSelection::PONO || + _vtg_config.ForceQuantifierInstantiationInRfExpr; + + rfmap::RfExpr rfin (in); + if(expand_quantifier) + rfin = rfmap::RfExprAstUtility::FindExpandQuantifier(in); std::unordered_map vars; - refinement_map.GetVars(in, vars); + refinement_map.GetVars(rfin, vars); for (const auto& v : vars) { rfmap::VarReplacement* repl = refinement_map.CheckReplacement(v.first); if (repl == NULL) { @@ -326,7 +332,7 @@ rfmap::RfExpr VlgSglTgtGen::ReplExpr(const rfmap::RfExpr& in) { << repl->origvar->to_verilog() << " --> " << repl->newvar->to_verilog(); } - auto new_node = refinement_map.ReplacingRtlIlaVar(in, {}); + auto new_node = refinement_map.ReplacingRtlIlaVar(rfin, {}); // AnnotateType requires all refinement_map.AnnotateType(new_node, {}); return new_node; diff --git a/src/vtarget-out/single_target_as.cc b/src/vtarget-out/single_target_as.cc index 2d9da57d9..2290d3673 100644 --- a/src/vtarget-out/single_target_as.cc +++ b/src/vtarget-out/single_target_as.cc @@ -244,20 +244,28 @@ void VlgSglTgtGen:: if (is_jg) { for (auto& dspt_aspt : all_assumptions) { - for (auto& aspt : dspt_aspt.second) + for (auto& aspt : dspt_aspt.second) { + ILA_ASSERT(!rfmap::RfExprAstUtility::HasQuantifier(aspt)); add_a_direct_assumption(GetVlg(aspt), dspt_aspt.first); + } } for (auto& dspt_asst : all_assertions) { - for (auto& asst : dspt_asst.second) + for (auto& asst : dspt_asst.second) { + ILA_ASSERT(!rfmap::RfExprAstUtility::HasQuantifier(asst)); add_a_direct_assertion(GetVlg(asst), dspt_asst.first); + } } for (auto& dspt_asst : all_sanity_assertions) { - for (auto& asst : dspt_asst.second) + for (auto& asst : dspt_asst.second) { + ILA_ASSERT(!rfmap::RfExprAstUtility::HasQuantifier(asst)); add_a_direct_sanity_assertion(GetVlg(asst), dspt_asst.first); + } } for (auto& dspt_cvrs : all_covers) { - for (auto& cvr : dspt_cvrs.second) + for (auto& cvr : dspt_cvrs.second) { + ILA_ASSERT(!rfmap::RfExprAstUtility::HasQuantifier(cvr)); add_a_direct_cover_check(GetVlg(cvr), dspt_cvrs.first); + } } @@ -265,6 +273,7 @@ void VlgSglTgtGen:: const auto& vn = std::get<1>(dspt_vn_rfexpr_eq); const auto& eq = std::get<3>(dspt_vn_rfexpr_eq); // we know it is eq(vn, rhs); + ILA_ASSERT(!rfmap::RfExprAstUtility::HasQuantifier(eq)); vlg_wrapper.add_assign_stmt(vn, GetVlg(eq->get_child().at(1))); } return; @@ -326,7 +335,8 @@ void VlgSglTgtGen:: ILA_DLOG("VTG.AddWireEq") << GetVlg(eq); - if (rfmap::RfExprAstUtility::HasArrayVar(eq)) { + if (rfmap::RfExprAstUtility::HasArrayVar(eq) || + rfmap::RfExprAstUtility::HasQuantifier(eq) ) { ILA_ERROR_IF(!_vtg_config.YosysSmtArrayForRegFile) << "Requiring array sort in Yosys when generating" << " properties, please enable YosysSmtArrayForRegFile"; @@ -340,7 +350,8 @@ void VlgSglTgtGen:: for (const auto& aspt : dspt_aspt.second) { ILA_DLOG("VTG.AddAssume") << GetVlg(aspt); - if (rfmap::RfExprAstUtility::HasArrayVar(aspt)) { + if (rfmap::RfExprAstUtility::HasArrayVar(aspt) || + rfmap::RfExprAstUtility::HasQuantifier(aspt) ) { ILA_ERROR_IF(!_vtg_config.YosysSmtArrayForRegFile) << "Requiring array sort in Yosys when generating" << " properties, please enable YosysSmtArrayForRegFile"; @@ -354,7 +365,8 @@ void VlgSglTgtGen:: for (const auto& asst : dspt_asst.second) { ILA_DLOG("VTG.AddAssert") << GetVlg(asst); - if (rfmap::RfExprAstUtility::HasArrayVar(asst)) + if (rfmap::RfExprAstUtility::HasArrayVar(asst) || + rfmap::RfExprAstUtility::HasQuantifier(asst)) add_smt_assertion(asst, dspt_asst.first); else add_a_direct_assertion(GetVlg(asst), dspt_asst.first); @@ -366,6 +378,9 @@ void VlgSglTgtGen:: ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(asst)) << "Implementation bug: sanity checking assertion should not contain " "arrays"; + ILA_CHECK(!rfmap::RfExprAstUtility::HasQuantifier(asst)) + << "Implementation bug: sanity checking assertion should not contain " + "quantifier"; add_a_direct_sanity_assertion(GetVlg(asst), dspt_asst.first); } @@ -375,6 +390,9 @@ void VlgSglTgtGen:: ILA_CHECK(!rfmap::RfExprAstUtility::HasArrayVar(cvr)) << "Implementation bug: cover checks should not contain " "arrays"; + ILA_CHECK(!rfmap::RfExprAstUtility::HasQuantifier(cvr)) + << "Implementation bug: cover checks should not contain " + "quantifier"; add_a_direct_cover_check(GetVlg(cvr), dspt_cvrs.first); } From 19a135845c6f9bacbe0e625f210515f910e8a0ee Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 29 Nov 2021 09:49:53 +0800 Subject: [PATCH 70/78] add quantifier support --- src/rfmap-in/rfmap_typecheck.cc | 3 +- test/t_vtarget_gen.cc | 47 +++++++++++++++++++ test/unit-data/vpipe/vmem/cond-forall.json | 15 ++++++ .../vpipe/vmem/large_small_forall/.gitignore | 3 ++ .../vmem/large_small_forall_jg/.gitignore | 3 ++ test/unit-data/vpipe/vmem/smallarray.v | 36 ++++++++++++++ test/unit-data/vpipe/vmem/vmap-forall.json | 18 +++++++ test/unit-include/memswap.h | 1 + test/unit-src/memswap.cc | 25 ++++++++++ 9 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 test/unit-data/vpipe/vmem/cond-forall.json create mode 100644 test/unit-data/vpipe/vmem/large_small_forall/.gitignore create mode 100644 test/unit-data/vpipe/vmem/large_small_forall_jg/.gitignore create mode 100644 test/unit-data/vpipe/vmem/smallarray.v create mode 100644 test/unit-data/vpipe/vmem/vmap-forall.json diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index a01bbd274..48ad89eca 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -849,7 +849,8 @@ bool RfExprAstUtility::IsLastLevelBooleanOp(const RfExpr& in) { verilog_expr::voperator::C_EQ, verilog_expr::voperator::L_EQ, verilog_expr::voperator::C_NEQ, verilog_expr::voperator::L_NEQ, verilog_expr::voperator::L_NEG, verilog_expr::voperator::L_AND, - verilog_expr::voperator::L_OR}; + verilog_expr::voperator::L_OR, verilog_expr::voperator::FORALL, + verilog_expr::voperator::EXIST}; if (in->is_constant() || in->is_var()) return false; diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index 584dbdf39..763042307 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -402,6 +402,53 @@ TEST(TestVlgTargetGen, MemoryReadAbsReadJasperGold) { vg.GenerateTargets(); } + +TEST(TestVlgTargetGen, MemoryForallEqualPono) { + RtlVerifyConfig vtg_cfg; + + auto ila_model = MemorySwap::BuildSimpleLargeArray(); + + auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; + VerilogVerificationTargetGenerator vg( + {}, // no include + {dirName + "smallarray.v"}, // vlog files + "top", // top_module_name + dirName + "vmap-forall.json", // variable mapping + dirName + "cond-forall.json", // cond path + dirName + "large_small_forall/", // output path + ila_model.get(), + ModelCheckerSelection::PONO, + vtg_cfg); + + EXPECT_FALSE(vg.in_bad_state()); + + vg.GenerateTargets(); +} + + +TEST(TestVlgTargetGen, MemoryForallEqualJg) { + RtlVerifyConfig vtg_cfg; + + auto ila_model = MemorySwap::BuildSimpleLargeArray(); + + auto dirName = std::string(ILANG_TEST_SRC_ROOT) + "/unit-data/vpipe/vmem/"; + VerilogVerificationTargetGenerator vg( + {}, // no include + {dirName + "smallarray.v"}, // vlog files + "top", // top_module_name + dirName + "vmap-forall.json", // variable mapping + dirName + "cond-forall.json", // cond path + dirName + "large_small_forall_jg/", // output path + ila_model.get(), + ModelCheckerSelection::JASPERGOLD, + vtg_cfg); + + EXPECT_FALSE(vg.in_bad_state()); + + vg.GenerateTargets(); +} + + TEST(TestVlgTargetGen, UndetValue) { auto ila_model = UndetVal::BuildModel(); diff --git a/test/unit-data/vpipe/vmem/cond-forall.json b/test/unit-data/vpipe/vmem/cond-forall.json new file mode 100644 index 000000000..78295a070 --- /dev/null +++ b/test/unit-data/vpipe/vmem/cond-forall.json @@ -0,0 +1,15 @@ +{ + "global invariants": [], + + "instructions": [ + { + "instruction": "WRITE", + "ready bound": 1 + }, + { + "instruction": "READ", + "ready bound": 1 + } + ] +} + diff --git a/test/unit-data/vpipe/vmem/large_small_forall/.gitignore b/test/unit-data/vpipe/vmem/large_small_forall/.gitignore new file mode 100644 index 000000000..15bb95a3d --- /dev/null +++ b/test/unit-data/vpipe/vmem/large_small_forall/.gitignore @@ -0,0 +1,3 @@ +READ/* +WRITE/* + diff --git a/test/unit-data/vpipe/vmem/large_small_forall_jg/.gitignore b/test/unit-data/vpipe/vmem/large_small_forall_jg/.gitignore new file mode 100644 index 000000000..15bb95a3d --- /dev/null +++ b/test/unit-data/vpipe/vmem/large_small_forall_jg/.gitignore @@ -0,0 +1,3 @@ +READ/* +WRITE/* + diff --git a/test/unit-data/vpipe/vmem/smallarray.v b/test/unit-data/vpipe/vmem/smallarray.v new file mode 100644 index 000000000..714dd99bc --- /dev/null +++ b/test/unit-data/vpipe/vmem/smallarray.v @@ -0,0 +1,36 @@ +module top(input clk, input rst, input [3:0] addr, input[7:0] data, + input wen, input ren, output [7:0] odata); + +wire array1_sel = addr[3] == 1'b0; +wire array2_sel = addr[3] == 1'b1; +wire [2:0] subaddr = addr[2:0]; +wire[7:0] odata1,odata2; + +reg array1_sel_d1; +always @(posedge clk) begin + array1_sel_d1 <= array1_sel; +end + +subarray a1(.clk(clk), .rst(rst), .addr(subaddr), .data(data), .wen(wen&array1_sel), .ren(ren&array1_sel), .odata(odata1)); +subarray a2(.clk(clk), .rst(rst), .addr(subaddr), .data(data), .wen(wen&array2_sel), .ren(ren&array2_sel), .odata(odata2)); + +assign odata = array1_sel_d1 ? odata1 : odata2; + +endmodule + +module subarray(input clk, input rst, input [2:0] addr, input[7:0] data, + input wen, input ren, output reg [7:0] odata); + + reg [7:0] array[0:7]; + + always @(posedge clk) begin + if(wen) + array[addr] <= data; + end + + always @(posedge clk) begin + if(ren) + odata <= array[addr]; + end + +endmodule diff --git a/test/unit-data/vpipe/vmem/vmap-forall.json b/test/unit-data/vpipe/vmem/vmap-forall.json new file mode 100644 index 000000000..dbe3e7320 --- /dev/null +++ b/test/unit-data/vpipe/vmem/vmap-forall.json @@ -0,0 +1,18 @@ +{ + "state mapping": { + "array":"$forall(i:bv4, ILA.array[i] == ( i < 8 ? RTL.a1.array[i[2:0]] : RTL.a2.array[i[2:0]]) )", + "odata":"RTL.odata"}, + + "RTL interface connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + }, + + "input mapping" : { + "addr" : "RTL.addr", + "data" : "RTL.data", + "ren" : "RTL.ren", + "wen" : "RTL.wen" + } + +} diff --git a/test/unit-include/memswap.h b/test/unit-include/memswap.h index 190ec2c3c..102af43cb 100644 --- a/test/unit-include/memswap.h +++ b/test/unit-include/memswap.h @@ -18,6 +18,7 @@ class MemorySwap { static Ila BuildRfAsMemModelRegEntry6(); static Ila BuildRdModel(); static Ila BuildResetterTest(); + static Ila BuildSimpleLargeArray(); }; // class MemorySwap diff --git a/test/unit-src/memswap.cc b/test/unit-src/memswap.cc index 2c5e15a71..6bddb0c97 100644 --- a/test/unit-src/memswap.cc +++ b/test/unit-src/memswap.cc @@ -31,6 +31,31 @@ Ila MemorySwap::BuildModel() { } +Ila MemorySwap::BuildSimpleLargeArray() { + auto ila = Ila("LargeArray"); + ila.SetValid(BoolConst(true)); + auto wen = ila.NewBvInput("wen", 1); + auto ren = ila.NewBvInput("ren", 1); + auto addr = ila.NewBvInput("addr", 4); + auto data = ila.NewBvInput("data", 8); + auto odata = ila.NewBvState("odata", 8); + + auto array = ila.NewMemState("array", 4, 8); + + { + auto WRITE = ila.NewInstr("WRITE"); + WRITE.SetDecode(wen == 1); + WRITE.SetUpdate(array,Store(array, addr,data)); + } + + { + auto READ = ila.NewInstr("READ"); + READ.SetDecode(ren == 1); + READ.SetUpdate(odata, Load(array, addr)); + } + return ila; +} + Ila MemorySwap::BuildSimpleSwapModel() { // build the ila auto memswap = Ila("MemorySwap"); From 638f8c0b40d266134bfa79b45cd07f6abfa52939 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 30 Nov 2021 13:50:31 +0800 Subject: [PATCH 71/78] add flex lexer include path --- src/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6043b117f..49cafb343 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -157,6 +157,11 @@ else() target_link_libraries(${ILANG_LIB_NAME} PRIVATE vexpparser::vexpparser) endif() +if(DEFINED FLEXLEXER_INCLUDE_PATH) + message(STATUS "Flex include path: ${FLEXLEXER_INCLUDE_PATH}") + include_directories(${FLEXLEXER_INCLUDE_PATH}) +endif() + ## ## vcd parser ## From fb5c41d446bc7159e4901fb793ebad918f27d14f Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 30 Nov 2021 15:53:36 +0800 Subject: [PATCH 72/78] remove ubuntu 16.04 in azure ppl --- azure-pipelines.yml | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index edfa93469..948ba2b78 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -55,28 +55,6 @@ jobs: ./test/unit_tests displayName: 'build' -- job: Ubuntu_1604_LTS - pool: - vmImage: 'ubuntu-16.04' - steps: - - script: | - sudo apt-get update - sudo apt-get install bison - sudo apt-get install flex - sudo apt-get install z3 - sudo apt-get install libz3-dev - sudo apt-get install libfl-dev - sudo apt-get install g++-7 - displayName: 'package' - - script: | - mkdir -p build - cd build - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-7 - cmake --build . - sudo cmake --build . --target install - cmake --build . --target test - displayName: 'build' - - job: Ubuntu_1804_LTS pool: vmImage: 'ubuntu-18.04' From c88eb9c9548223e3c89f809a06e7ecd8d9e32ffe Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 13 Dec 2021 10:51:33 +0800 Subject: [PATCH 73/78] inst complete cond default --- include/ilang/rfmap-in/verilog_rfmap.h | 2 + src/rfmap-in/verilog_rfmap.cc | 18 +++++++ src/vtarget-out/single_target_misc.cc | 6 ++- src/vtarget-out/vtarget_gen_impl.cc | 66 +++++--------------------- test/unit-data/vpipe/rfmap/cond.json | 13 ++--- 5 files changed, 43 insertions(+), 62 deletions(-) diff --git a/include/ilang/rfmap-in/verilog_rfmap.h b/include/ilang/rfmap-in/verilog_rfmap.h index d2ebdba02..412cd0a61 100644 --- a/include/ilang/rfmap-in/verilog_rfmap.h +++ b/include/ilang/rfmap-in/verilog_rfmap.h @@ -226,6 +226,8 @@ struct VerilogRefinementMap { // ---------------------- inst-cond ------------------------------- // std::map inst_complete_cond; + bool global_inst_complete_set; + InstructionCompleteCondition global_inst_complete_cond; std::vector global_invariants; // ---------------------- supplementary_info ------------------------------- diff --git a/src/rfmap-in/verilog_rfmap.cc b/src/rfmap-in/verilog_rfmap.cc index c36ca301c..561d5d8c7 100644 --- a/src/rfmap-in/verilog_rfmap.cc +++ b/src/rfmap-in/verilog_rfmap.cc @@ -1101,6 +1101,24 @@ VerilogRefinementMap::VerilogRefinementMap( { auto* instrs = GetJsonSection(rf_cond, {"instructions"}); auto* invariants = GetJsonSection(rf_cond, {"global invariants"}); + auto* glb_ready_bound = GetJsonSection(rf_cond, {"ready-bound"}); + auto* glb_ready_signal = GetJsonSection(rf_cond, {"ready-signal"}); + ERRIF(glb_ready_bound && glb_ready_signal, + "`ready bound` and `ready signal` are mutual exclusive"); + global_inst_complete_set = glb_ready_bound || glb_ready_signal; + + if (glb_ready_bound) { + ENSURE(glb_ready_bound->is_number_unsigned(), + "`ready-bound` should be an unsigned number"); + global_inst_complete_cond.ready_bound = glb_ready_bound->get(); + global_inst_complete_cond.type = InstructionCompleteCondition::ConditionType::BOUND; + } else if (glb_ready_signal) { + ENSURE(glb_ready_signal->is_string(), + "`ready-signal` should be a string"); + global_inst_complete_cond.ready_signal = ParseRfMapExprJson(*glb_ready_signal); + global_inst_complete_cond.type = InstructionCompleteCondition::ConditionType::SIGNAL; + } + if (instrs) { ENSURE(instrs->is_array(), "`instructions` should be array of object"); for (auto& instr : *instrs) { diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index 67288288b..f75ebd637 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -476,7 +476,11 @@ VlgSglTgtGen::get_current_instruction_rf() { ILA_NOT_NULL(_instr_ptr); const auto& inst_name = _instr_ptr->name().str(); auto pos = refinement_map.inst_complete_cond.find(inst_name); - ILA_ERROR_IF(pos == refinement_map.inst_complete_cond.end()) + if(pos == refinement_map.inst_complete_cond.end() && + refinement_map.global_inst_complete_set) + return refinement_map.global_inst_complete_cond; + ILA_ERROR_IF(pos == refinement_map.inst_complete_cond.end() && + !refinement_map.global_inst_complete_set) << "Cannot find the completion condition for " << inst_name; return pos->second; } // get_current_instruction_rf diff --git a/src/vtarget-out/vtarget_gen_impl.cc b/src/vtarget-out/vtarget_gen_impl.cc index fac3c62bb..8e4ede034 100644 --- a/src/vtarget-out/vtarget_gen_impl.cc +++ b/src/vtarget-out/vtarget_gen_impl.cc @@ -176,19 +176,25 @@ void VlgVerifTgtGen::GenerateTargets(void) { // now let's deal w. instructions in rf_cond if (_vtg_config.target_select == RtlVerifyConfig::BOTH || _vtg_config.target_select == RtlVerifyConfig::INST) { + bool generate_forall_inst = _refinement.global_inst_complete_set; + for (auto&& instr : _refinement.inst_complete_cond) { std::string iname = instr.first; + auto instr_ptr = _ila_ptr->instr(iname); + ILA_ERROR_IF(instr_ptr == nullptr) + << "ila:" << _ila_ptr->name().str() + << " has no instruction:" << iname; + } + for (unsigned inst_idx = 0; inst_idx < _ila_ptr->instr_num() ; ++ inst_idx) { + auto instr_ptr = _ila_ptr->instr(inst_idx); + std::string iname = instr_ptr->name().str(); if (_vtg_config.CheckThisInstructionOnly != "" && _vtg_config.CheckThisInstructionOnly != iname) continue; // skip, not checking this instruction - - auto instr_ptr = _ila_ptr->instr(iname); - if (instr_ptr == nullptr) { - ILA_ERROR << "ila:" << _ila_ptr->name().str() - << " has no instruction:" << iname; + if (!generate_forall_inst && + _refinement.inst_complete_cond.find(iname) == _refinement.inst_complete_cond.end()) continue; - } - + auto sub_output_path = os_portable_append_dir(_output_path, iname); if (_backend == ModelCheckerSelection::PONO) { @@ -212,52 +218,6 @@ void VlgVerifTgtGen::GenerateTargets(void) { target.ExportAll("wrapper.v", "ila.v", "run.sh", "do.tcl"); target.do_not_instantiate(); } -#if 0 - else if (_backend == ModelCheckerSelection::RELCHC) { - // will actually fail : not supported for using relchc for invariant - // targets - auto target = VlgSglTgtGen_Relchc( - sub_output_path, - instr_ptr, // instruction - _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - "wrapper", _vlg_impl_srcs, - _vlg_impl_include_path, _vtg_config, _backend, - target_type_t::INSTRUCTIONS, _advanced_param_ptr); - target.ConstructWrapper(); - target.ExportAll("wrapper.v", "ila.v", "run.sh", "__design_smt.smt2", - "absmem.v"); - target.do_not_instantiate(); - } else if ((_backend & ModelCheckerSelection::YOSYS) == - ModelCheckerSelection::YOSYS) { - // in this case we will have two targets to generate - // one is the target with only the design and - // and the second one should use the smt file it generates - // and create conversion (map) function - - auto target = VlgSglTgtGen_Yosys( - sub_output_path, - instr_ptr, // instruction - _ila_ptr, _cfg, rf_vmap, rf_cond, supplementary_info, vlg_info_ptr, - "wrapper", _vlg_impl_srcs, - _vlg_impl_include_path, _vtg_config, _backend, - target_type_t::INSTRUCTIONS, _advanced_param_ptr, - _chc_target_t::GENERAL_PROPERTY); - target.ConstructWrapper(); - std::string design_file; - if (_backend == ModelCheckerSelection::ABCPDR) - design_file = "wrapper.aig"; - else if ((_backend & ModelCheckerSelection::CHC) == ModelCheckerSelection::CHC) - design_file = "wrapper.smt2"; - else if (_backend == ModelCheckerSelection::BTOR_GENERIC) - design_file = "wrapper.btor2"; - else - design_file = "wrapper.unknfmt"; - - target.ExportAll("wrapper.v", "ila.v", "run.sh", design_file, - "absmem.v"); - target.do_not_instantiate(); - } // end case backend -#endif runnable_script_name.push_back( os_portable_append_dir(sub_output_path, "run.sh")); } // end for instrs diff --git a/test/unit-data/vpipe/rfmap/cond.json b/test/unit-data/vpipe/rfmap/cond.json index 5a8e5959d..9d5baf45e 100644 --- a/test/unit-data/vpipe/rfmap/cond.json +++ b/test/unit-data/vpipe/rfmap/cond.json @@ -18,16 +18,13 @@ " (RTL.reg_2_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd2) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd2) ) )", " (RTL.reg_3_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd3) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd3) ) )" ], + "ready bound" : 1, // this is the default bound "instructions": [ - { - "instruction": "NOP", - "ready bound": 1 - }, - { - "instruction": "ADD", - "ready bound": 1 - }, + // { // no need + // "instruction": "ADD", + // "ready bound": 1 + // }, { "instruction": "SUB", "ready bound": 1 From da73b404525ade5548b5668cbdbfa0b08dcee3d8 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 20 Dec 2021 13:38:32 +0800 Subject: [PATCH 74/78] fix bug --- src/rfmap-in/rfmap_typecheck.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 48ad89eca..016413f3b 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -317,6 +317,10 @@ void TypedVerilogRefinementMap::TraverseAllRfExpr( for (auto& cond : instcond.second.start_condition) cond = TraverseRfExpr(cond, func); } + if (global_inst_complete_set) { + if ( global_inst_complete_cond.type == InstructionCompleteCondition::ConditionType::SIGNAL) + global_inst_complete_cond.ready_signal = TraverseRfExpr(global_inst_complete_cond.ready_signal, func); + } for (auto& a : global_invariants) a = TraverseRfExpr(a, func); From e1ba297e63f78f1bc4a51ab948b5b45c2614cd80 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 20 Dec 2021 13:39:08 +0800 Subject: [PATCH 75/78] new test case --- test/t_vtarget_gen.cc | 4 +- .../rfmap/cond-rfmap-pvholder-reset.json | 5 +++ .../rfmap/vmap-rfmap-pvholder-reset.json | 38 +++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-reset.json create mode 100644 test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-reset.json diff --git a/test/t_vtarget_gen.cc b/test/t_vtarget_gen.cc index 763042307..c966558fa 100644 --- a/test/t_vtarget_gen.cc +++ b/test/t_vtarget_gen.cc @@ -84,9 +84,9 @@ TEST(TestVlgTargetGen, PipeExampleRfmapPostResetStart) { {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files "pipeline_v", // top_module_name os_portable_append_dir(rfDir, - "vmap-rfmap-pvholder.json"), // variable mapping + "vmap-rfmap-pvholder-reset.json"), // variable mapping os_portable_append_dir(rfDir, - "cond-rfmap-pvholder.json"), // instruction-mapping + "cond-rfmap-pvholder-reset.json"), // instruction-mapping os_portable_append_dir(dirName, "verify_pvholder_reset"), // verification dir ila_model.get(), // ILA model ModelCheckerSelection::PONO, // engine diff --git a/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-reset.json b/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-reset.json new file mode 100644 index 000000000..067d2f47c --- /dev/null +++ b/test/unit-data/vpipe/rfmap/cond-rfmap-pvholder-reset.json @@ -0,0 +1,5 @@ +{ + // this is a comment + "ready signal": "#ppl_stage_wb# ## 1" +} + diff --git a/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-reset.json b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-reset.json new file mode 100644 index 000000000..34983898b --- /dev/null +++ b/test/unit-data/vpipe/rfmap/vmap-rfmap-pvholder-reset.json @@ -0,0 +1,38 @@ +{ + "state mapping": { + "r0":[ ["__START__", "RTL.registers[0] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[0]"] ] , + "r1":[ ["__START__", "RTL.registers[1] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[1]"] ] , + "r2":[ ["__START__", "RTL.registers[2] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[2]"] ] , + "r3":[ ["__START__", "RTL.registers[3] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[3]"] ] }, + + + "input mapping": { + "inst":"RTL.inst" + }, + + "rtl-interface-connection" : { + "CLOCK" : "clk", + "RESET" : "rst" + }, + + "monitor" :{ + // pipeline tracker + "ppl_stage" : { + "template" : "phase tracker", + "rules" : [ + { // + "name" : "ex", + "enter" : {"event" : "#decode#"}, + "exit" : {"event" : "1"} + }, + + { // + "name" : "wb", + "enter" : {"event" : "#ppl_stage_ex#"}, + "exit" : {"event" : "1"} + } + ] + + } + } +} From 2dbdbab27959c14c87be8f4edb4fb855abf1121b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 10 Jan 2022 11:11:26 +0800 Subject: [PATCH 76/78] fix typo --- include/ilang/ilang++.h | 6 +++--- src/ilang++.cc | 2 +- src/rfmap-in/rfmap_typecheck.cc | 5 +++++ src/vtarget-out/inv-syn/cex_extract.cc | 12 +++++++----- src/vtarget-out/single_target_cond.cc | 3 +++ src/vtarget-out/single_target_inv_syn_support.cc | 2 ++ test/t_api.cc | 2 +- 7 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/ilang/ilang++.h b/include/ilang/ilang++.h index 8f172eeb3..4e85ead30 100644 --- a/include/ilang/ilang++.h +++ b/include/ilang/ilang++.h @@ -748,12 +748,12 @@ class IlaZ3Unroller { /// \brief The wrapper of Rtl verification target generator -class IlaVerilogRefinemetChecker { +class IlaVerilogRefinementChecker { public: // ------------------------- CONSTRUCTOR/DESTRUCTOR ----------------------- // /// Default constructor - IlaVerilogRefinemetChecker( + IlaVerilogRefinementChecker( const Ila& ila, const std::vector& implementation_include_path, const std::vector& implementation_srcs, @@ -764,7 +764,7 @@ class IlaVerilogRefinemetChecker { ModelCheckerSelection backend, const RtlVerifyConfig& vtg_config = RtlVerifyConfig() ); /// Default virtual destructor. - ~IlaVerilogRefinemetChecker() {}; + ~IlaVerilogRefinementChecker() {}; }; // class RtlVerifier diff --git a/src/ilang++.cc b/src/ilang++.cc index 9f7250069..94b454ddb 100644 --- a/src/ilang++.cc +++ b/src/ilang++.cc @@ -869,7 +869,7 @@ smt::Term ResetAndGetSmtTerm(smt::SmtSolver& solver, const ExprRef& expr, } #endif // SMTSWITCH_INTERFACE -IlaVerilogRefinemetChecker::IlaVerilogRefinemetChecker( +IlaVerilogRefinementChecker::IlaVerilogRefinementChecker( const Ila& ila, const std::vector& implementation_include_path, const std::vector& implementation_srcs, diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 016413f3b..95ba5d3f0 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -219,6 +219,11 @@ void TypedVerilogRefinementMap::CollectInternallyDefinedVars() { all_var_def_types.emplace("afterdecode", tmp); // these are the stage info all_var_def_types.emplace("commit", tmp); + + all_var_def_types.emplace("start", tmp); // these are the stage info + all_var_def_types.emplace("afterstart", tmp); // these are the stage info + all_var_def_types.emplace("end", tmp); + all_var_def_types.emplace("$decode", tmp); // these are the ila.decode/ila.valid info all_var_def_types.emplace("$valid", tmp); diff --git a/src/vtarget-out/inv-syn/cex_extract.cc b/src/vtarget-out/inv-syn/cex_extract.cc index e4396335e..336a79a19 100644 --- a/src/vtarget-out/inv-syn/cex_extract.cc +++ b/src/vtarget-out/inv-syn/cex_extract.cc @@ -172,7 +172,7 @@ CexExtractor::CexExtractor(const std::string& vcd_file_name, parse_from(vcd_file_name, scope, is_reg, reg_only); } -/// create from a existing file +/// create from an existing file CexExtractor::CexExtractor(const std::string& fn) { std::ifstream fin(fn); if (!fin.is_open()) { @@ -200,10 +200,9 @@ CexExtractor::CexExtractor(const std::string& fn) { std::string CexExtractor::GenInvAssert(const std::string& prefix, const std::set& focus_name) const { - - std::string ret = "(1'b1 == 1'b1)"; // true + std::string ret; for (auto&& nv : cex) { - if (!cex_is_reg.at(nv.first)) + if (!cex_is_reg.at(nv.first)) // skipping those that are not registers continue; auto fullname = prepend(prefix, ReplaceAll(nv.first, "[0:0]", "")); auto check_name = fullname; // remove further of [][:] @@ -212,7 +211,10 @@ CexExtractor::GenInvAssert(const std::string& prefix, check_name = check_name.substr(0, pos); if (!focus_name.empty() && !IN(check_name, focus_name)) continue; - ret += "\n&& (" + fullname + " == " + nv.second + ")"; + if (ret.empty()) + ret = "(" + fullname + " == " + nv.second + ")"; + else + ret += "\n&& (" + fullname + " == " + nv.second + ")"; } return ret; } diff --git a/src/vtarget-out/single_target_cond.cc b/src/vtarget-out/single_target_cond.cc index b3bf755b9..80b16d11c 100644 --- a/src/vtarget-out/single_target_cond.cc +++ b/src/vtarget-out/single_target_cond.cc @@ -90,6 +90,7 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { vlg_wrapper.add_reg("__START__", 1); rfmap_add_internal_reg("__START__", 1); rfmap_add_replacement("decode", "__START__"); + rfmap_add_replacement("start", "__START__"); vlg_wrapper.add_stmt("always @(posedge clk) begin"); // how start is triggered if(_vtg_config.ForceInstCheckReset) { @@ -104,6 +105,7 @@ void VlgSglTgtGen::ConstructWrapper_add_cycle_count_moniter() { vlg_wrapper.add_reg("__STARTED__", 1); rfmap_add_internal_reg("__STARTED__", 1); rfmap_add_replacement("afterdecode", "__STARTED__"); + rfmap_add_replacement("afterstart", "__STARTED__"); vlg_wrapper.add_stmt("always @(posedge clk) begin"); vlg_wrapper.add_stmt("if (rst) __STARTED__ <= 0;"); vlg_wrapper.add_stmt( @@ -190,6 +192,7 @@ void VlgSglTgtGen::ConstructWrapper_add_condition_signals() { rfmap_add_internal_wire("__IEND__", 1); rfmap_add_internal_wire("__EDCOND__", 1); rfmap_add_replacement("commit", "__IEND__"); + rfmap_add_replacement("end", "__IEND__"); auto end_no_recur = rfmap_not(rfmap_var("__ENDED__")); diff --git a/src/vtarget-out/single_target_inv_syn_support.cc b/src/vtarget-out/single_target_inv_syn_support.cc index 5df7fd539..b5c2ea93b 100644 --- a/src/vtarget-out/single_target_inv_syn_support.cc +++ b/src/vtarget-out/single_target_inv_syn_support.cc @@ -250,8 +250,10 @@ void VlgSglTgtGen::ConstructWrapper_inv_syn_cond_signals() { rfmap_add_internal_wire("__START__", 1); rfmap_add_replacement("decode", "__START__"); + rfmap_add_replacement("start", "__START__"); rfmap_add_internal_wire("__STARTED__", 1); rfmap_add_replacement("afterdecode", "__STARTED__"); + rfmap_add_replacement("afterstart", "__STARTED__"); } } // namespace ilang diff --git a/test/t_api.cc b/test/t_api.cc index 23f04d549..389bf4b26 100644 --- a/test/t_api.cc +++ b/test/t_api.cc @@ -621,7 +621,7 @@ TEST(TestApi, RtlVerify) { {dirName, "rfmap", "cond.json"}); auto out_name = os_portable_append_dir(dirName, "out3"); - IlaVerilogRefinemetChecker checker( + IlaVerilogRefinementChecker checker( proc, {}, {vlg_name}, "resetter", vmap_name, cond_name, out_name, ModelCheckerSelection::PONO); From 1a406bf6bc6b1b5fb4ab0163a0b8dd6bdbcf2f2c Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 10 Jan 2022 11:11:40 +0800 Subject: [PATCH 77/78] add wire def --- test/unit-data/vpipe/simple_pipe.v | 2 +- test/unit-data/vpipe/simple_pipe_stall_short.v | 8 ++++---- test/unit-data/vpipe/simple_pipe_wrong.v | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit-data/vpipe/simple_pipe.v b/test/unit-data/vpipe/simple_pipe.v index 1a4fe3225..fb37ce94d 100644 --- a/test/unit-data/vpipe/simple_pipe.v +++ b/test/unit-data/vpipe/simple_pipe.v @@ -18,7 +18,7 @@ `define OP_SUB 2'b10 `define OP_AND 2'b11 -module pipeline_v(input clk, input rst, input [7:0] inst, input [1:0] dummy_read_rf, output [7:0] dummy_rf_data +module pipeline_v(input wire clk, input wire rst, input wire [7:0] inst, input wire [1:0] dummy_read_rf, output wire [7:0] dummy_rf_data ); wire [1:0] op; diff --git a/test/unit-data/vpipe/simple_pipe_stall_short.v b/test/unit-data/vpipe/simple_pipe_stall_short.v index b838977e7..e225515f8 100644 --- a/test/unit-data/vpipe/simple_pipe_stall_short.v +++ b/test/unit-data/vpipe/simple_pipe_stall_short.v @@ -21,10 +21,10 @@ `define OP_NAND 2'b11 module pipeline_v( - input clk, input rst, - input [7:0] inst, input inst_valid, output inst_ready, - input stallex, input stallwb, - input [1:0] dummy_read_rf, output [7:0] dummy_rf_data + input wire clk, input wire rst, + input wire [7:0] inst, input wire inst_valid, output wire inst_ready, + input wire stallex, input wire stallwb, + input wire [1:0] dummy_read_rf, output wire [7:0] dummy_rf_data ); // TODO: finish this diff --git a/test/unit-data/vpipe/simple_pipe_wrong.v b/test/unit-data/vpipe/simple_pipe_wrong.v index 81b361aee..77b888324 100644 --- a/test/unit-data/vpipe/simple_pipe_wrong.v +++ b/test/unit-data/vpipe/simple_pipe_wrong.v @@ -17,7 +17,7 @@ `define OP_SUB 2'b10 `define OP_AND 2'b11 -module pipeline_v(input clk, input rst, input [7:0] inst, input [1:0] dummy_read_rf, output [7:0] dummy_rf_data ); +module pipeline_v(input wire clk, input wire rst, input wire [7:0] inst, input wire [1:0] dummy_read_rf, output wire [7:0] dummy_rf_data ); wire [1:0] op; wire [1:0] rs1; From 76a99fa4300a2338feb208fa124443bef94eda87 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 21 Jan 2022 15:27:52 +0800 Subject: [PATCH 78/78] rf expr type resolution --- src/rfmap-in/rfmap_typecheck.cc | 147 ++++++++++++------ src/vtarget-out/single_target_misc.cc | 2 +- test/CMakeLists.txt | 1 + test/t_rfmap_proc.cc | 42 +++++ test/unit-data/vpipe/rfmap_t/cond-1.json | 41 +++++ test/unit-data/vpipe/rfmap_t/vmap-1.json | 108 +++++++++++++ test/unit-data/vpipe/rfmap_t_out/.placeholder | 0 .../unit-data/vpipe/rfmap_t_out/t1/.gitignore | 1 + 8 files changed, 293 insertions(+), 49 deletions(-) create mode 100644 test/t_rfmap_proc.cc create mode 100644 test/unit-data/vpipe/rfmap_t/cond-1.json create mode 100644 test/unit-data/vpipe/rfmap_t/vmap-1.json create mode 100644 test/unit-data/vpipe/rfmap_t_out/.placeholder create mode 100644 test/unit-data/vpipe/rfmap_t_out/t1/.gitignore diff --git a/src/rfmap-in/rfmap_typecheck.cc b/src/rfmap-in/rfmap_typecheck.cc index 95ba5d3f0..e9a4a0451 100644 --- a/src/rfmap-in/rfmap_typecheck.cc +++ b/src/rfmap-in/rfmap_typecheck.cc @@ -359,58 +359,99 @@ bool _compute_const(const RfExpr& in, unsigned& out) { // relies on TypeInferTravserRfExpr // and therefore, all_var_def_types void TypedVerilogRefinementMap::ComputeDelayValueHolderWidth() { - for (auto& name_delay_pair : aux_delays) { - if (name_delay_pair.second.width == 0) { - auto tp = TypeInferTravserRfExpr(name_delay_pair.second.signal, {}); - ILA_ERROR_IF(tp.is_array()) - << "Currently does not support to delay a memory variable"; - ILA_ERROR_IF(tp.is_unknown()) - << "Type inference failed on: " - << name_delay_pair.second.signal->to_verilog(); - name_delay_pair.second.width = tp.unified_width(); - - // replendish all_var_def_types - VarDef internal_var_def; - internal_var_def.width = tp.unified_width(); - internal_var_def.type = VarDef::var_type::REG; - - all_var_def_types.emplace(name_delay_pair.first, internal_var_def); + + + unsigned failed_cnt = 0; + unsigned prev_failed_cnt = 0; + unsigned iter = 0; + do { + prev_failed_cnt = failed_cnt; + failed_cnt = 0; + for (auto& name_delay_pair : aux_delays) { + if (name_delay_pair.second.width == 0) { + auto tp = TypeInferTravserRfExpr(name_delay_pair.second.signal, {}); + ILA_CHECK(!tp.is_array()) + << "Currently does not support to delay a memory variable"; + + if (tp.is_array() || tp.is_unknown() || tp.unified_width() == 0) { + failed_cnt ++; + continue; + } + + name_delay_pair.second.width = tp.unified_width(); + + // replendish all_var_def_types + VarDef internal_var_def; + internal_var_def.width = tp.unified_width(); + internal_var_def.type = VarDef::var_type::REG; + + all_var_def_types.emplace(name_delay_pair.first, internal_var_def); + } } - } - for (auto& name_vr : value_recorder) { - if (name_vr.second.width == 0) { - auto tp = TypeInferTravserRfExpr(name_vr.second.value, {}); - ILA_ERROR_IF(tp.is_array()) - << "Currently does not support to delay a memory variable"; - ILA_ERROR_IF(tp.is_unknown()) - << "Type inference failed on: " << name_vr.second.value->to_verilog(); - name_vr.second.width = tp.unified_width(); - - // replendish all_var_def_types - VarDef internal_var_def; - internal_var_def.width = tp.unified_width(); - internal_var_def.type = VarDef::var_type::REG; - - all_var_def_types.emplace(name_vr.first, internal_var_def); + for (auto& name_vr : value_recorder) { + if (name_vr.second.width == 0) { + auto tp = TypeInferTravserRfExpr(name_vr.second.value, {}); + ILA_CHECK(!tp.is_array()) + << "Currently does not support to delay a memory variable"; + + if (tp.is_array() || tp.is_unknown() || tp.unified_width() == 0) { + failed_cnt ++; + continue; + } + + name_vr.second.width = tp.unified_width(); + + // replendish all_var_def_types + VarDef internal_var_def; + internal_var_def.width = tp.unified_width(); + internal_var_def.type = VarDef::var_type::REG; + + all_var_def_types.emplace(name_vr.first, internal_var_def); + } + } // replendish internal defined vars + + for (auto& n_expr : direct_aux_vars) { + if (n_expr.second.width == 0) { + + auto tp = TypeInferTravserRfExpr(n_expr.second.val, {}); + ILA_CHECK(!tp.is_array()) + << "Currently does not support to delay a memory variable"; + + if (tp.is_array() || tp.is_unknown() || tp.unified_width() == 0 ) { + failed_cnt ++; + continue; + } + n_expr.second.width = tp.unified_width(); + + VarDef internal_var_def; + internal_var_def.width = tp.unified_width(); + internal_var_def.type = VarDef::var_type::WIRE; + all_var_def_types.emplace(n_expr.first, internal_var_def); + } + } // end of for (auto& n_expr : direct_aux_vars) + ILA_ASSERT(prev_failed_cnt >= failed_cnt || prev_failed_cnt == 0); + ILA_INFO_IF(failed_cnt > 0) << "Rf Expr Type Resolution: iter " + << (iter++) << " remaining: " << failed_cnt; + }while(prev_failed_cnt != failed_cnt && failed_cnt != 0); + // the last round : report failed ones + ILA_INFO_IF(prev_failed_cnt > 0) << "Rf Expr Type Resolution: iter " + << (iter++) << " remaining: " << failed_cnt; + + for (auto& name_delay_pair : aux_delays) { + ILA_ERROR_IF (name_delay_pair.second.width == 0) + << "Type inference failed on: " + << name_delay_pair.second.signal->to_verilog(); } - } // replendish internal defined vars - for (auto& n_expr : direct_aux_vars) { - if (n_expr.second.width == 0) { - - auto tp = TypeInferTravserRfExpr(n_expr.second.val, {}); - ILA_ERROR_IF(tp.is_array()) - << "Currently does not support to delay a memory variable"; - ILA_ERROR_IF(tp.is_unknown()) - << "Type inference failed on: " << n_expr.second.val->to_verilog(); - n_expr.second.width = tp.unified_width(); - - VarDef internal_var_def; - internal_var_def.width = tp.unified_width(); - internal_var_def.type = VarDef::var_type::WIRE; - all_var_def_types.emplace(n_expr.first, internal_var_def); + for (auto& name_vr : value_recorder) { + ILA_ERROR_IF (name_vr.second.width == 0) + << "Type inference failed on: " << name_vr.second.value->to_verilog(); + } + + for (auto& n_expr : direct_aux_vars) { + ILA_ERROR_IF(n_expr.second.width == 0) + << "Type inference failed on: " << n_expr.second.val->to_verilog(); } - } } // ComputeDelayValueHolderWidth // relies on typechecker and all_var_def_types @@ -564,8 +605,16 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr( } else if (in->get_op() == verilog_expr::voperator::TERNARY) { auto left = TypeInferTravserRfExpr(in->get_child().at(1), local_var_def); auto right = TypeInferTravserRfExpr(in->get_child().at(2), local_var_def); + if (left.is_unknown() && right.is_unknown()) + return RfMapVarType(); // unknown + if (left.is_unknown()) + return right; + if (right.is_unknown()) + return left; + if (left.is_array() || right.is_array()) return left; // TODO: check compatibility + return RfMapVarType( std::max(left.unified_width(), right.unified_width())); } else if (in->get_op() == verilog_expr::voperator::FUNCTION_APP) { @@ -588,6 +637,8 @@ RfMapVarType TypedVerilogRefinementMap::TypeInferTravserRfExpr( if (!_compute_const(in->get_child().at(0), ntimes)) return RfMapVarType(); auto tp = TypeInferTravserRfExpr(in->get_child().at(1), local_var_def); + if (tp.is_unknown()) + return RfMapVarType(); // unknown return RfMapVarType(tp.unified_width() * ntimes); } else if (in->get_op() == verilog_expr::voperator::FORALL || in->get_op() == verilog_expr::voperator::EXIST) { diff --git a/src/vtarget-out/single_target_misc.cc b/src/vtarget-out/single_target_misc.cc index f75ebd637..4031e46db 100644 --- a/src/vtarget-out/single_target_misc.cc +++ b/src/vtarget-out/single_target_misc.cc @@ -394,7 +394,7 @@ void VlgSglTgtGen::ConstructWrapper_add_direct_aux_vars() { for (const auto & n_expr : refinement_map.direct_aux_vars) { const auto & n = n_expr.first; auto w = n_expr.second.width; - ILA_CHECK(w!=0); + ILA_CHECK(w!=0); // aux var should have its width vlg_wrapper.add_wire(n,w,true); vlg_wrapper.add_output(n,w); add_wire_assign_assumption(n, n_expr.second.val, "direct_aux_var"); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5174459ac..5ff2ff882 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -77,6 +77,7 @@ package_add_test(${ILANG_TEST_MAIN} t_smt_switch_itf.cc t_smt_trans.cc t_rfexpr_smt_out.cc + t_rfmap_proc.cc t_sort.cc t_symbol.cc t_unroll_seq.cc diff --git a/test/t_rfmap_proc.cc b/test/t_rfmap_proc.cc new file mode 100644 index 000000000..bec180e58 --- /dev/null +++ b/test/t_rfmap_proc.cc @@ -0,0 +1,42 @@ +/// \file +/// Unit test for generating Verilog verification target + +#include +#include +#include +#include + +#include "unit-include/config.h" +#include "unit-include/memswap.h" +#include "unit-include/pipe_ila.h" +#include "unit-include/util.h" + +namespace ilang { + +typedef std::vector P; + +TEST(TestRfmapProcess, TypeResolve) { + auto ila_model = SimplePipe::BuildModel(); + + auto dirName = os_portable_append_dir(ILANG_TEST_DATA_DIR, "vpipe"); + auto rfDir = os_portable_append_dir(dirName, "rfmap_t"); + auto outDir = os_portable_append_dir(os_portable_append_dir(dirName, "rfmap_t_out"), "t1"); + auto vtg_config = RtlVerifyConfig(); + + VerilogVerificationTargetGenerator vg( + {}, // no include + {os_portable_append_dir(dirName, "simple_pipe.v")}, // vlog files + "pipeline_v", // top_module_name + os_portable_append_dir(rfDir, "vmap-1.json"), // variable mapping + os_portable_append_dir(rfDir, "cond-1.json"), // instruction-mapping + outDir, // verification dir + ila_model.get(), // ILA model + ModelCheckerSelection::PONO, // engine + vtg_config); + + EXPECT_FALSE(vg.in_bad_state()); + vg.GenerateTargets(); +} // TEST(TestRfmapProcess, TypeResolve) + + +}; // namespace ilang diff --git a/test/unit-data/vpipe/rfmap_t/cond-1.json b/test/unit-data/vpipe/rfmap_t/cond-1.json new file mode 100644 index 000000000..8a2f1bcf6 --- /dev/null +++ b/test/unit-data/vpipe/rfmap_t/cond-1.json @@ -0,0 +1,41 @@ +{ + // this is a comment + "global invariants": [ + " (RTL.reg_0_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd0) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd1) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd2) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b00 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd3) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd0) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd1) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd2) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b10 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd3) ) && ( (RTL.ex_wb_reg_wen == 0) || (RTL.ex_wb_rd != 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd0) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd1) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd2) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b11 ) |-> ( ( (RTL.id_ex_reg_wen == 1) && (RTL.id_ex_rd == 2'd3) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd3) ) )", + " (RTL.reg_0_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd0) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd0) ) )", + " (RTL.reg_1_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd1) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd1) ) )", + " (RTL.reg_2_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd2) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd2) ) )", + " (RTL.reg_3_w_stage == 2'b01 ) |-> ( ( (RTL.id_ex_reg_wen == 0) || (RTL.id_ex_rd != 2'd3) ) && ( (RTL.ex_wb_reg_wen == 1) && (RTL.ex_wb_rd == 2'd3) ) )" + ], + + "instructions": [ + { + "instruction": "NOP", + "ready signal": "#stage_tracker# == 2" + }, + { + "instruction": "ADD", + "ready signal": "#stage_tracker# == 2" + }, + { + "instruction": "SUB", + "ready signal": "#stage_tracker# == 2" + }, + { + "instruction": "AND", + "ready signal": "#ppl_stage_wb# ## 1" + } + ] +} + diff --git a/test/unit-data/vpipe/rfmap_t/vmap-1.json b/test/unit-data/vpipe/rfmap_t/vmap-1.json new file mode 100644 index 000000000..1c39e5dd1 --- /dev/null +++ b/test/unit-data/vpipe/rfmap_t/vmap-1.json @@ -0,0 +1,108 @@ +{ + "state mapping": { + "r0":[ ["__START__", "#r0_pvholder#"] , ["1'b1", "RTL.registers[0]"] ] , + "r1":[ ["__START__", "RTL.registers[1] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[1]"] ] , + "r2":[ ["__START__", "RTL.registers[2] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[2]"] ] , + "r3":[ ["__START__", "RTL.registers[3] @ ppl_stage_wb"] , ["1'b1", "RTL.registers[3]"] ] }, + + + "input mapping": { + "inst":"RTL.inst" + }, + + "rtl-interface-connection" : { + "CLOCK" : "clk", + "RESET" : "rst", + "INPUT" : { + "dummy_read_rf" : "#dummy_read_rf#" + // if you use it here, you must define it in a keep-for-invariants block !!! + } + }, + + "monitor" :{ + // monitor 1 : value recorder + "r0_pvholder" : { // this is just a name + "template" : "value recorder", + "cond": "#stage_tracker# == 1", + "val":"RTL.registers[0]" + }, + + // monitor 2 : arb verilog - stage tracker and append verilog + "stage_tracker" : { + "verilog": + ["always @(posedge clk) begin", + " if (rst ) stage_tracker <= 0;", + " else if ( __START__ ) stage_tracker <= 0;", + " else if (__STARTED__ && !__ENDED__) stage_tracker <= stage_tracker + 1;", + "end"], + "append-verilog" : "module nouse2(input wire a, output wire b); assign b=a; endmodule", + "defs" :[ ["stage_tracker", 2, "reg"] ], + "refs" :[] + }, + + // monitor 3 : ref/def test + "ref_test" : { + "verilog": + ["always @(posedge clk) begin", + " if (__START__) ref_test <= 0;", + " else if (__STARTED__ && !__ENDED__ && stage_tracker == 1) ref_test <= RTL.registers[0] + 1;", + "end"], + "defs" :[ ["ref_test", 2, "reg"] ], + "refs" :[ "RTL.registers[0]" ] + }, + + // a monitor that always exists + "delay_wb_write" : { + "verilog": + [ "always @(posedge clk) begin", + " delay_wb_write <= (#decode# & #afterdecode#) ? RTL.ex_wb_val : delay_wb_write;", + "end", + "assign usefl = RTL.registers[RTL.ex_wb_rd] ;" + ], + "append-verilog" : [ + "module nouse(input wire aa, output wire bb);", + " /*keep-for-invariants*/ assign bb=aa;", + " endmodule"], + "defs" :[ ["delay_wb_write", 8, "reg"], ["usefl", 8, "wire"], ["dummy_read_rf", 2, "wire"] ], + "refs" :[ "RTL.ex_wb_val", "#decode#", "#afterdecode#","RTL.registers[RTL.ex_wb_rd]"], + // actually, you should not use #decode# or #afterdecode# here + // because they should not exist when verifying invariants + "keep-for-invariants" : true + }, + + "rt7" : "RTL.inst[0]@0", + "rt2" : "RTL.inst @ 1", + "rt22" : " RTL.inst @ 2", + "rt0" : "rt7 ? rt2 : rt22", + "rt1" : "rt7 ? rt2 : rt0", + + + // pipeline tracker + "ppl_stage" : { + "template" : "phase tracker", + "event-alias" : { + "dsignal" : "ppl_stage_ex ## [1:$] ppl_stage_wb ##1 (1'b1)" + }, + "aux-var" : [["cnt", 2, "reg"]], + "rules" : [ + { // + "name" : "ex", + "enter" : {"event" : "#decode#"}, + "exit" : {"event" : "1", "action": " cnt <= RTL.reg_0_w_stage "} + }, + + { // + "name" : "wb", + "enter" : {"event" : "#ppl_stage_ex#"}, + "exit" : {"event" : "1"} + }, + + { + "name" : "teststage1", + "enter" : "#ppl_stage_ex#" + } + ] + + } + } +} diff --git a/test/unit-data/vpipe/rfmap_t_out/.placeholder b/test/unit-data/vpipe/rfmap_t_out/.placeholder new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit-data/vpipe/rfmap_t_out/t1/.gitignore b/test/unit-data/vpipe/rfmap_t_out/t1/.gitignore new file mode 100644 index 000000000..72e8ffc0d --- /dev/null +++ b/test/unit-data/vpipe/rfmap_t_out/t1/.gitignore @@ -0,0 +1 @@ +*