From 3988f935b8715ddeffc994472c146e62448c8749 Mon Sep 17 00:00:00 2001 From: Peter Crozier Date: Wed, 13 May 2020 13:09:08 +0100 Subject: Extend YS_DEBUGTRAP to MacOS. --- kernel/log.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/log.h b/kernel/log.h index dee5d44d7..4b60ffb0d 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -86,7 +86,7 @@ YOSYS_NAMESPACE_BEGIN # endif # if __has_builtin(__builtin_debugtrap) # define YS_DEBUGTRAP __builtin_debugtrap() -# elif defined(__unix__) +# elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) # define YS_DEBUGTRAP raise(SIGTRAP) # else # define YS_DEBUGTRAP do {} while(0) @@ -103,6 +103,9 @@ YOSYS_NAMESPACE_BEGIN # define YS_DEBUGTRAP_IF_DEBUGGING do { \ sighandler_t old = signal(SIGTRAP, SIG_IGN); raise(SIGTRAP); signal(SIGTRAP, old); \ } while(0) +#elif defined(__APPLE__) && defined(__MACH__) +// MacOS +#define YS_DEBUGTRAP_IF_DEBUGGING { sig_t old = signal(SIGTRAP, SIG_IGN); raise(SIGTRAP); signal(SIGTRAP, old); } #else # define YS_DEBUGTRAP_IF_DEBUGGING do {} while(0) #endif -- cgit v1.2.3 From 495dcfc812be0f990bee20fc1ac819c72b8b7e47 Mon Sep 17 00:00:00 2001 From: Peter Crozier Date: Wed, 13 May 2020 14:17:00 +0100 Subject: Consolidate Linux and Mac version of YS_DEBUGTRAP_IF_DEBUGGING. --- kernel/log.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'kernel') diff --git a/kernel/log.h b/kernel/log.h index 4b60ffb0d..6c5de78d7 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -97,15 +97,12 @@ YOSYS_NAMESPACE_BEGIN // if a debugger is attached, and does nothing otherwise. #if defined(_WIN32) # define YS_DEBUGTRAP_IF_DEBUGGING do { if (IsDebuggerPresent()) DebugBreak(); } while(0) -#elif defined(__unix__) +# elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // There is no reliable (or portable) *nix equivalent of IsDebuggerPresent(). However, // debuggers will stop when SIGTRAP is raised, even if the action is set to ignore. # define YS_DEBUGTRAP_IF_DEBUGGING do { \ - sighandler_t old = signal(SIGTRAP, SIG_IGN); raise(SIGTRAP); signal(SIGTRAP, old); \ + auto old = signal(SIGTRAP, SIG_IGN); raise(SIGTRAP); signal(SIGTRAP, old); \ } while(0) -#elif defined(__APPLE__) && defined(__MACH__) -// MacOS -#define YS_DEBUGTRAP_IF_DEBUGGING { sig_t old = signal(SIGTRAP, SIG_IGN); raise(SIGTRAP); signal(SIGTRAP, old); } #else # define YS_DEBUGTRAP_IF_DEBUGGING do {} while(0) #endif -- cgit v1.2.3 From 039c3a59826de4410dd9257262430729fb0b4000 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 19:08:46 -0700 Subject: kernel: Module::makeblackbox() to clear connections + delete wires last --- kernel/rtlil.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel') diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 196e301b6..3e5896813 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -776,6 +776,7 @@ void RTLIL::Module::makeblackbox() connections_.clear(); remove(delwires); + set_bool_attribute(ID::blackbox); } -- cgit v1.2.3 From b66904e9cdef8cd0e0019f9a1a3a7a13abdcc10c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 08:18:04 -0700 Subject: Revert "Merge branch 'eddie/kernel_makeblackbox' into eddie/abc9_auto_dff" This reverts commit e08497c7c9d8a6f7a3eccddf2149c45d9ecff207, reversing changes made to e366fd55122236a21c6daee6765724add840a1f9. --- kernel/rtlil.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'kernel') diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 3e5896813..196e301b6 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -776,7 +776,6 @@ void RTLIL::Module::makeblackbox() connections_.clear(); remove(delwires); - set_bool_attribute(ID::blackbox); } -- cgit v1.2.3 From 7812a2959b9b23b44e8144f9edb139f282d623e1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 10:21:08 -0700 Subject: kernel: TimingInfo to clamp -ve setup/edge-sensitive delays to zero --- kernel/timinginfo.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'kernel') diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index fb4e0930d..36908868c 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -128,11 +128,9 @@ struct TimingInfo int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); int max = std::max(rise_max,fall_max); - if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + max = 0; } for (const auto &d : dst) { auto &v = t.arrival[NameBit(d)]; @@ -152,11 +150,9 @@ struct TimingInfo if (!c.wire->port_input) log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); - if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + max = 0; } for (const auto &s : src) { auto &v = t.required[NameBit(s)]; -- cgit v1.2.3 From b3e2538a140cac36c32b133d4475a052cfc46809 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 14:12:28 -0700 Subject: abc9_ops: fix bypass boxes using (* abc9_bypass *) --- kernel/constids.inc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/constids.inc b/kernel/constids.inc index 6b40a5908..25996d2d8 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -2,10 +2,9 @@ X(A) X(abc9_box) X(abc9_box_id) X(abc9_box_seq) +X(abc9_bypass) X(abc9_carry) X(abc9_flop) -X(abc9_holes) -X(abc9_init) X(abc9_lut) X(abc9_mergeability) X(abc9_scc) -- cgit v1.2.3 From 7146c0339e0b79ec24bc89e7fdf15331436e0e53 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 17:03:28 -0700 Subject: timinginfo: ignore $specify2 cells if EN is false --- kernel/timinginfo.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'kernel') diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index 36908868c..d818e580b 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -82,6 +82,9 @@ struct TimingInfo for (auto cell : module->cells()) { if (cell->type == ID($specify2)) { + auto en = cell->getPort(ID::EN); + if (en.is_fully_const() && !en.as_bool()) + continue; auto src = cell->getPort(ID::SRC); auto dst = cell->getPort(ID::DST); for (const auto &c : src.chunks()) -- cgit v1.2.3 From 2fb4931e5be2c2a0c80ffbca73ad74ebb8c9032f Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Date: Tue, 14 Apr 2020 18:09:05 +0000 Subject: Add specialized `hash()` for type `dict` and use a `dict` instead of a `std::map` for `techmap_cache` and `techmap_do_cache`. --- kernel/hashlib.h | 25 ++++++++++++++++++++----- kernel/rtlil.h | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'kernel') diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 592d6e577..cdbad87c4 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -19,6 +19,12 @@ namespace hashlib { +template struct hash_ops; +template> class dict; +template> class idict; +template> class pool; +template> class mfp; + const int hashtable_size_trigger = 2; const int hashtable_size_factor = 3; @@ -100,6 +106,20 @@ template struct hash_ops> { } }; +template struct hash_ops> { + static inline bool cmp(dict a, dict b) { + return a == b; + } + static inline unsigned int hash(dict a) { + unsigned int h = mkhash_init; + for (auto &it : a) { + h = mkhash(h, hash_ops

::hash(it.first)); + h = mkhash(h, hash_ops::hash(it.second)); + } + return h; + } +}; + template struct hash_ops> { static inline bool cmp(std::tuple a, std::tuple b) { return a == b; @@ -191,11 +211,6 @@ inline int hashtable_size(int min_size) throw std::length_error("hash table exceeded maximum size."); } -template> class dict; -template> class idict; -template> class pool; -template> class mfp; - template class dict { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 11c45bbec..dad8508c3 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -150,7 +150,7 @@ namespace RTLIL if (!p[0]) return 0; - log_assert(p[0] == '$' || p[0] == '\\'); + log_assert(p[0] == '$' || p[0] == '\\' || strncmp(p, "_TECHMAP_", strlen("_TECHMAP_")) == 0); log_assert(p[1] != 0); auto it = global_id_index_.find((char*)p); -- cgit v1.2.3 From dabeb1e8a136730536d17fd79e6c348d8cdca271 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 20 Apr 2020 15:50:12 -0700 Subject: techmap: prefix special wires with backslash for use as IdString --- kernel/constids.inc | 1 + kernel/rtlil.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/constids.inc b/kernel/constids.inc index aa75a9c09..5c8373513 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -169,6 +169,7 @@ X(techmap_autopurge) X(_TECHMAP_BITS_CONNMAP_) X(_TECHMAP_CELLTYPE_) X(techmap_celltype) +X(_TECHMAP_FAIL_) X(techmap_maccmap) X(_TECHMAP_REPLACE_) X(techmap_simplemap) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index dad8508c3..11c45bbec 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -150,7 +150,7 @@ namespace RTLIL if (!p[0]) return 0; - log_assert(p[0] == '$' || p[0] == '\\' || strncmp(p, "_TECHMAP_", strlen("_TECHMAP_")) == 0); + log_assert(p[0] == '$' || p[0] == '\\'); log_assert(p[1] != 0); auto it = global_id_index_.find((char*)p); -- cgit v1.2.3 From 35b94d1f664928dcf8476a9a6f35e2bb7f647ee1 Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Date: Wed, 22 Apr 2020 22:04:22 +0000 Subject: kernel: Re-implement `dict` hash code as a `dict` member function instead of a specialized template for `hash_ops`. --- kernel/hashlib.h | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'kernel') diff --git a/kernel/hashlib.h b/kernel/hashlib.h index cdbad87c4..18114b6ad 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -19,12 +19,6 @@ namespace hashlib { -template struct hash_ops; -template> class dict; -template> class idict; -template> class pool; -template> class mfp; - const int hashtable_size_trigger = 2; const int hashtable_size_factor = 3; @@ -106,20 +100,6 @@ template struct hash_ops> { } }; -template struct hash_ops> { - static inline bool cmp(dict a, dict b) { - return a == b; - } - static inline unsigned int hash(dict a) { - unsigned int h = mkhash_init; - for (auto &it : a) { - h = mkhash(h, hash_ops

::hash(it.first)); - h = mkhash(h, hash_ops::hash(it.second)); - } - return h; - } -}; - template struct hash_ops> { static inline bool cmp(std::tuple a, std::tuple b) { return a == b; @@ -211,6 +191,11 @@ inline int hashtable_size(int min_size) throw std::length_error("hash table exceeded maximum size."); } +template> class dict; +template> class idict; +template> class pool; +template> class mfp; + template class dict { @@ -630,6 +615,15 @@ public: return !operator==(other); } + unsigned int hash() const { + unsigned int h = mkhash_init; + for (auto &it : entries) { + h = mkhash(h, hash_ops::hash(it.udata.first)); + h = mkhash(h, hash_ops::hash(it.udata.second)); + } + return h; + } + void reserve(size_t n) { entries.reserve(n); } size_t size() const { return entries.size(); } bool empty() const { return entries.empty(); } -- cgit v1.2.3 From 976edb7597692ac04111b3c51b13e18105c14f42 Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Date: Fri, 24 Apr 2020 08:37:16 +0000 Subject: kernel: Ensure `dict` always hashes to the same value given the same contents. --- kernel/hashlib.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'kernel') diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 18114b6ad..1284f3f8d 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -207,6 +207,7 @@ class dict entry_t() { } entry_t(const std::pair &udata, int next) : udata(udata), next(next) { } entry_t(std::pair &&udata, int next) : udata(std::move(udata)), next(next) { } + bool operator<(const entry_t &other) const { return udata.first < other.udata.first; } }; std::vector hashtable; @@ -616,10 +617,12 @@ public: } unsigned int hash() const { + std::vector entries_(entries); //make a copy to preserve const-ness + std::sort(entries_.begin(), entries_.end()); unsigned int h = mkhash_init; - for (auto &it : entries) { - h = mkhash(h, hash_ops::hash(it.udata.first)); - h = mkhash(h, hash_ops::hash(it.udata.second)); + for (unsigned int i = 0; i < entries_.size(); ++i) { + h = mkhash(h, hash_ops::hash(entries_[i].udata.first)); + h = mkhash(h, hash_ops::hash(entries_[i].udata.second)); } return h; } -- cgit v1.2.3 From 67fc0c3698693f049e805211c49d6219f17d7c7d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 May 2020 16:44:35 -0700 Subject: abc9: use (* abc9_keep *) instead of (* abc9_scc *); apply to $_DFF_?_ instead of moving them to $__ prefix --- kernel/constids.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/constids.inc b/kernel/constids.inc index 25996d2d8..345bfaee8 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -5,9 +5,9 @@ X(abc9_box_seq) X(abc9_bypass) X(abc9_carry) X(abc9_flop) +X(abc9_keep) X(abc9_lut) X(abc9_mergeability) -X(abc9_scc) X(abc9_scc_id) X(abcgroup) X(ABITS) -- cgit v1.2.3 From 8297afe92588c881fbf0590a64c81af08e6f20f6 Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Date: Thu, 14 May 2020 22:52:07 +0000 Subject: log: Use `dict` instead of `std::vector` for `log_expect_{error, warning, log}` to better express the intent that each element is unique. --- kernel/log.cc | 20 ++++++++++---------- kernel/log.h | 13 +++++-------- 2 files changed, 15 insertions(+), 18 deletions(-) (limited to 'kernel') diff --git a/kernel/log.cc b/kernel/log.cc index a21ba480a..104bee078 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -42,7 +42,7 @@ std::vector log_files; std::vector log_streams; std::map> log_hdump; std::vector log_warn_regexes, log_nowarn_regexes, log_werror_regexes; -std::vector> log_expect_log, log_expect_warning, log_expect_error; +dict log_expect_log, log_expect_warning, log_expect_error; std::set log_warnings, log_experimentals, log_experimentals_ignored; int log_warnings_count = 0; int log_warnings_count_noexpect = 0; @@ -181,7 +181,7 @@ void logv(const char *format, va_list ap) log_warning("Found log message matching -W regex:\n%s", str.c_str()); for (auto &item : log_expect_log) - if (YS_REGEX_NS::regex_search(linebuffer, item.first)) + if (YS_REGEX_NS::regex_search(linebuffer, item.second.pattern)) item.second.current_count++; linebuffer.clear(); @@ -256,7 +256,7 @@ static void logv_warning_with_prefix(const char *prefix, bool warning_match = false; for (auto &item : log_expect_warning) - if (YS_REGEX_NS::regex_search(message, item.first)) { + if (YS_REGEX_NS::regex_search(message, item.second.pattern)) { item.second.current_count++; warning_match = true; } @@ -349,7 +349,7 @@ static void logv_error_with_prefix(const char *prefix, log_error_atexit(); for (auto &item : log_expect_error) - if (YS_REGEX_NS::regex_search(log_last_error, item.first)) + if (YS_REGEX_NS::regex_search(log_last_error, item.second.pattern)) item.second.current_count++; if (check_expected_logs) @@ -672,31 +672,31 @@ void log_check_expected() for (auto &item : log_expect_warning) { if (item.second.current_count == 0) { log_warn_regexes.clear(); - log_error("Expected warning pattern '%s' not found !\n", item.second.pattern.c_str()); + log_error("Expected warning pattern '%s' not found !\n", item.first.c_str()); } if (item.second.current_count != item.second.expected_count) { log_warn_regexes.clear(); log_error("Expected warning pattern '%s' found %d time(s), instead of %d time(s) !\n", - item.second.pattern.c_str(), item.second.current_count, item.second.expected_count); + item.first.c_str(), item.second.current_count, item.second.expected_count); } } for (auto &item : log_expect_log) { if (item.second.current_count == 0) { log_warn_regexes.clear(); - log_error("Expected log pattern '%s' not found !\n", item.second.pattern.c_str()); + log_error("Expected log pattern '%s' not found !\n", item.first.c_str()); } if (item.second.current_count != item.second.expected_count) { log_warn_regexes.clear(); log_error("Expected log pattern '%s' found %d time(s), instead of %d time(s) !\n", - item.second.pattern.c_str(), item.second.current_count, item.second.expected_count); + item.first.c_str(), item.second.current_count, item.second.expected_count); } } for (auto &item : log_expect_error) if (item.second.current_count == item.second.expected_count) { log_warn_regexes.clear(); - log("Expected error pattern '%s' found !!!\n", item.second.pattern.c_str()); + log("Expected error pattern '%s' found !!!\n", item.first.c_str()); #ifdef EMSCRIPTEN throw 0; #elif defined(_MSC_VER) @@ -707,7 +707,7 @@ void log_check_expected() } else { display_error_log_msg = false; log_warn_regexes.clear(); - log_error("Expected error pattern '%s' not found !\n", item.second.pattern.c_str()); + log_error("Expected error pattern '%s' not found !\n", item.first.c_str()); } } diff --git a/kernel/log.h b/kernel/log.h index dee5d44d7..54bfcb911 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -202,19 +202,16 @@ void log_flush(); struct LogExpectedItem { - LogExpectedItem(std::string pattern, int expected) : - expected_count(expected), - current_count(0), - pattern(pattern) - { - } + LogExpectedItem(const YS_REGEX_TYPE &pat, int expected) : + pattern(pat), expected_count(expected), current_count(0) {} + LogExpectedItem() : expected_count(0), current_count(0) {} + YS_REGEX_TYPE pattern; int expected_count; int current_count; - std::string pattern; }; -extern std::vector> log_expect_log, log_expect_warning, log_expect_error; +extern dict log_expect_log, log_expect_warning, log_expect_error; void log_check_expected(); const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true); -- cgit v1.2.3 From aee439360bba642dcbffe5b803aa9a994b11d183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Mon, 18 May 2020 18:15:03 +0200 Subject: Add force_downto and force_upto wire attributes. Fixes #2058. --- kernel/constids.inc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'kernel') diff --git a/kernel/constids.inc b/kernel/constids.inc index 345bfaee8..93c3a7609 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -79,6 +79,8 @@ X(equiv_merged) X(equiv_region) X(extract_order) X(F) +X(force_downto) +X(force_upto) X(fsm_encoding) X(fsm_export) X(FULL) -- cgit v1.2.3 From 6eea4b3d79590f874caa3ec740785781f3926666 Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Date: Mon, 18 May 2020 17:10:01 +0000 Subject: kernel: Try an order-independent approach to hashing `dict`. Co-Authored-By: David Shah Co-Authored-By: Eddie Hung --- kernel/hashlib.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'kernel') diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 1284f3f8d..5c87b55f5 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -617,12 +617,10 @@ public: } unsigned int hash() const { - std::vector entries_(entries); //make a copy to preserve const-ness - std::sort(entries_.begin(), entries_.end()); unsigned int h = mkhash_init; - for (unsigned int i = 0; i < entries_.size(); ++i) { - h = mkhash(h, hash_ops::hash(entries_[i].udata.first)); - h = mkhash(h, hash_ops::hash(entries_[i].udata.second)); + for (auto &entry : entries) { + h ^= hash_ops::hash(entry.udata.first); + h ^= hash_ops::hash(entry.udata.second); } return h; } -- cgit v1.2.3 From 8f87ccec9b6ed3c9bb8280830b506b28324a60d8 Mon Sep 17 00:00:00 2001 From: Rupert Swarbrick Date: Tue, 26 May 2020 11:51:06 +0100 Subject: Use c_str(), not str() for IdString/std::string == and != operators These operators work by fetching the string from the global string table and then comparing with the std::string that was passed in as rhs. Using str() means that we create a std::string (strlen; malloc; memcpy), compare for equality (another memcmp if they have the same length) and then finally free the string. Using c_str() means that we pass the const char* straight to std::string's equality operator. This ends up as a call to std::string::compare (the const char* flavour), which is essentially strcmp. --- kernel/rtlil.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 11c45bbec..10bfc13f2 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -296,8 +296,8 @@ namespace RTLIL // The methods below are just convenience functions for better compatibility with std::string. - bool operator==(const std::string &rhs) const { return str() == rhs; } - bool operator!=(const std::string &rhs) const { return str() != rhs; } + bool operator==(const std::string &rhs) const { return c_str() == rhs; } + bool operator!=(const std::string &rhs) const { return c_str() != rhs; } bool operator==(const char *rhs) const { return strcmp(c_str(), rhs) == 0; } bool operator!=(const char *rhs) const { return strcmp(c_str(), rhs) != 0; } -- cgit v1.2.3 From 17b5f23f20d6cadc8ce6220e457880720aae4866 Mon Sep 17 00:00:00 2001 From: Rupert Swarbrick Date: Fri, 22 May 2020 16:59:24 +0100 Subject: Use default copy constructor for RTLIL::SigBit There was a handwritten copy constructor, which I'm not sure was actually legal C++ (it unconditionally read from the 'data' member of a union, which wouldn't have been written if wire was true). It was also a bit less efficient than the constructor you get from the compiler by default (which is allowed to just copy the memory). This gives a marginal (~0.25%) decrease in code size when compiled with GCC 9.3. --- kernel/rtlil.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 11c45bbec..4a23a2d06 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -721,7 +721,7 @@ struct RTLIL::SigBit SigBit(const RTLIL::SigChunk &chunk); SigBit(const RTLIL::SigChunk &chunk, int index); SigBit(const RTLIL::SigSpec &sig); - SigBit(const RTLIL::SigBit &sigbit); + SigBit(const RTLIL::SigBit &sigbit) = default; RTLIL::SigBit &operator =(const RTLIL::SigBit &other) = default; bool operator <(const RTLIL::SigBit &other) const; @@ -1494,7 +1494,6 @@ inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire) : wire(wire), offset(0) { log_as inline RTLIL::SigBit::SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire != nullptr); } inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data[0]; } inline RTLIL::SigBit::SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data[index]; } -inline RTLIL::SigBit::SigBit(const RTLIL::SigBit &sigbit) : wire(sigbit.wire), data(sigbit.data){ if (wire) offset = sigbit.offset; } inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const { if (wire == other.wire) -- cgit v1.2.3 From 7ff306ccdb47415e3a483adad87076327399434f Mon Sep 17 00:00:00 2001 From: Rupert Swarbrick Date: Tue, 26 May 2020 15:19:39 +0100 Subject: Minor optimisation in Module::wire() and Module::cell() The existing code does a search to figure out whether id is in the dict (with the call to count()), and then looks it up again to get the result (with the call to at()). This version calls find() instead, avoiding the double lookup. Code size increases slightly (6kb). I think this is because the contents of find() are getting inlined, and then inlined into lots of the callsites for cell() and wire(). Looking at the compiled code before this patch, you just get a (non-inlined) call to count() followed by a call to at(). After the patch, the contents of find() have been inlined (so you see do_hash, then do_lookup). The result for each function is about 30 bytes / 40% bigger, which presumably also enlarges call-sites that inline it. --- kernel/rtlil.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 11c45bbec..76c5b5304 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1134,8 +1134,14 @@ public: return design->selected_member(name, member->name); } - RTLIL::Wire* wire(RTLIL::IdString id) { return wires_.count(id) ? wires_.at(id) : nullptr; } - RTLIL::Cell* cell(RTLIL::IdString id) { return cells_.count(id) ? cells_.at(id) : nullptr; } + RTLIL::Wire* wire(RTLIL::IdString id) { + auto it = wires_.find(id); + return it == wires_.end() ? nullptr : it->second; + } + RTLIL::Cell* cell(RTLIL::IdString id) { + auto it = cells_.find(id); + return it == cells_.end() ? nullptr : it->second; + } RTLIL::ObjRange wires() { return RTLIL::ObjRange(&wires_, &refcount_wires_); } RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } -- cgit v1.2.3 From 17163cf43a6b6eec9aac44f6a4463dda54b8ed68 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 8 Apr 2020 19:30:47 +0200 Subject: Add flooring modulo operator The $div and $mod cells use truncating division semantics (rounding towards 0), as defined by e.g. Verilog. Another rounding mode, flooring (rounding towards negative infinity), can be used in e.g. VHDL. The new $modfloor cell provides this flooring modulo (also known as "remainder" in several languages, but this name is ambiguous). This commit also fixes the handling of $mod in opt_expr, which was previously optimized as if it was $modfloor. --- kernel/calc.cc | 25 +++++++++++++++++++++++++ kernel/celledges.cc | 2 +- kernel/celltypes.h | 3 ++- kernel/rtlil.cc | 3 ++- kernel/rtlil.h | 3 +++ kernel/satgen.h | 31 ++++++++++++++++++++++--------- 6 files changed, 55 insertions(+), 12 deletions(-) (limited to 'kernel') diff --git a/kernel/calc.cc b/kernel/calc.cc index 4a4840771..38a529128 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -489,6 +489,7 @@ RTLIL::Const RTLIL::const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2 return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); } +// truncating division RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { int undef_bit_pos = -1; @@ -502,6 +503,7 @@ RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2 return big2const(result_neg ? -(a / b) : (a / b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); } +// truncating modulo RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { int undef_bit_pos = -1; @@ -515,6 +517,29 @@ RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2 return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); } +RTLIL::Const RTLIL::const_modfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) +{ + int undef_bit_pos = -1; + BigInteger a = const2big(arg1, signed1, undef_bit_pos); + BigInteger b = const2big(arg2, signed2, undef_bit_pos); + if (b.isZero()) + return RTLIL::Const(RTLIL::State::Sx, result_len); + + BigInteger::Sign a_sign = a.getSign(); + BigInteger::Sign b_sign = b.getSign(); + a = a_sign == BigInteger::negative ? -a : a; + b = b_sign == BigInteger::negative ? -b : b; + BigInteger truncated = a_sign == BigInteger::negative ? -(a % b) : (a % b); + BigInteger modulo; + + if (truncated == 0 || (a_sign == b_sign)) { + modulo = truncated; + } else { + modulo = b_sign == BigInteger::negative ? truncated - b : truncated + b; + } + return big2const(modulo, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); +} + RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { int undef_bit_pos = -1; diff --git a/kernel/celledges.cc b/kernel/celledges.cc index 54e0168e2..488ee9d02 100644 --- a/kernel/celledges.cc +++ b/kernel/celledges.cc @@ -187,7 +187,7 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL return true; } - // FIXME: $mul $div $mod $slice $concat + // FIXME: $mul $div $mod $modfloor $slice $concat // FIXME: $lut $sop $alu $lcu $macc $fa return false; diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 450865ce9..37c251f7e 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -114,7 +114,7 @@ struct CellTypes ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), - ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow), + ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($modfloor), ID($pow), ID($logic_and), ID($logic_or), ID($concat), ID($macc) }; @@ -304,6 +304,7 @@ struct CellTypes HANDLE_CELL_TYPE(mul) HANDLE_CELL_TYPE(div) HANDLE_CELL_TYPE(mod) + HANDLE_CELL_TYPE(modfloor) HANDLE_CELL_TYPE(pow) HANDLE_CELL_TYPE(pos) HANDLE_CELL_TYPE(neg) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 196e301b6..f2480ba5a 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -948,7 +948,7 @@ namespace { return; } - if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow))) { + if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($modfloor), ID($pow))) { param_bool(ID::A_SIGNED); param_bool(ID::B_SIGNED); port(ID::A, param(ID::A_WIDTH)); @@ -1949,6 +1949,7 @@ DEF_METHOD(Sub, max(sig_a.size(), sig_b.size()), ID($sub)) DEF_METHOD(Mul, max(sig_a.size(), sig_b.size()), ID($mul)) DEF_METHOD(Div, max(sig_a.size(), sig_b.size()), ID($div)) DEF_METHOD(Mod, max(sig_a.size(), sig_b.size()), ID($mod)) +DEF_METHOD(ModFloor, max(sig_a.size(), sig_b.size()), ID($modfloor)) DEF_METHOD(LogicAnd, 1, ID($logic_and)) DEF_METHOD(LogicOr, 1, ID($logic_or)) #undef DEF_METHOD diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 423c0b4bd..6bb759928 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -466,6 +466,7 @@ namespace RTLIL RTLIL::Const const_sub (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_mul (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_div (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); + RTLIL::Const const_modfloor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_mod (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_pow (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); @@ -1204,6 +1205,7 @@ public: RTLIL::Cell* addMul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addDiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addMod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addPow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed = false, bool b_signed = false, const std::string &src = ""); RTLIL::Cell* addLogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); @@ -1303,6 +1305,7 @@ public: RTLIL::SigSpec Mul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec Div (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec Mod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec ModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec Pow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool a_signed = false, bool b_signed = false, const std::string &src = ""); RTLIL::SigSpec LogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = ""); diff --git a/kernel/satgen.h b/kernel/satgen.h index 88b84b7e6..1d257aa2c 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -279,7 +279,7 @@ struct SatGen bool arith_undef_handled = false; bool is_arith_compare = cell->type.in(ID($lt), ID($le), ID($ge), ID($gt)); - if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod)) || is_arith_compare)) + if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($modfloor)) || is_arith_compare)) { std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); std::vector undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep); @@ -293,7 +293,7 @@ struct SatGen int undef_any_b = ez->expression(ezSAT::OpOr, undef_b); int undef_y_bit = ez->OR(undef_any_a, undef_any_b); - if (cell->type.in(ID($div), ID($mod))) { + if (cell->type.in(ID($div), ID($mod), ID($modfloor))) { std::vector b = importSigSpec(cell->getPort(ID::B), timestep); undef_y_bit = ez->OR(undef_y_bit, ez->NOT(ez->expression(ezSAT::OpOr, b))); } @@ -935,7 +935,7 @@ struct SatGen return true; } - if (cell->type.in(ID($div), ID($mod))) + if (cell->type.in(ID($div), ID($mod), ID($modfloor))) { std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); std::vector b = importDefSigSpec(cell->getPort(ID::B), timestep); @@ -970,16 +970,28 @@ struct SatGen } std::vector y_tmp = ignore_div_by_zero ? yy : ez->vec_var(y.size()); + + // modulo calculation + std::vector modulo_trunc; + int floored_eq_trunc; + if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) { + modulo_trunc = ez->vec_ite(a.back(), ez->vec_neg(chain_buf), chain_buf); + // floor == trunc when sgn(a) == sgn(b) or trunc == 0 + floored_eq_trunc = ez->OR(ez->IFF(a.back(), b.back()), ez->NOT(ez->expression(ezSAT::OpOr, modulo_trunc))); + } else { + modulo_trunc = chain_buf; + floored_eq_trunc = ez->CONST_TRUE; + } + if (cell->type == ID($div)) { if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(ez->XOR(a.back(), b.back()), ez->vec_neg(y_u), y_u))); else ez->assume(ez->vec_eq(y_tmp, y_u)); - } else { - if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) - ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(a.back(), ez->vec_neg(chain_buf), chain_buf))); - else - ez->assume(ez->vec_eq(y_tmp, chain_buf)); + } else if (cell->type == ID($mod)) { + ez->assume(ez->vec_eq(y_tmp, modulo_trunc)); + } else if (cell->type == ID($modfloor)) { + ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(floored_eq_trunc, modulo_trunc, ez->vec_add(modulo_trunc, b)))); } if (ignore_div_by_zero) { @@ -996,7 +1008,8 @@ struct SatGen div_zero_result.insert(div_zero_result.end(), cell->getPort(ID::A).size(), ez->CONST_TRUE); div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE); } - } else { + } else if (cell->type.in(ID($mod), ID($modfloor))) { + // a mod 0 = a int copy_a_bits = min(cell->getPort(ID::A).size(), cell->getPort(ID::B).size()); div_zero_result.insert(div_zero_result.end(), a.begin(), a.begin() + copy_a_bits); if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) -- cgit v1.2.3 From edd8ff2c0778d97808869488cc7394151456c4ca Mon Sep 17 00:00:00 2001 From: Xiretza Date: Tue, 21 Apr 2020 12:51:58 +0200 Subject: Add flooring division operator The $div and $mod cells use truncating division semantics (rounding towards 0), as defined by e.g. Verilog. Another rounding mode, flooring (rounding towards negative infinity), can be used in e.g. VHDL. The new $divfloor cell provides this flooring division. This commit also fixes the handling of $div in opt_expr, which was previously optimized as if it was $divfloor. --- kernel/calc.cc | 22 ++++++++++++++++++++++ kernel/celledges.cc | 2 +- kernel/celltypes.h | 3 ++- kernel/rtlil.cc | 3 ++- kernel/rtlil.h | 3 +++ kernel/satgen.h | 21 +++++++++++++++++---- 6 files changed, 47 insertions(+), 7 deletions(-) (limited to 'kernel') diff --git a/kernel/calc.cc b/kernel/calc.cc index 38a529128..ae18809d3 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -517,6 +517,28 @@ RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2 return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); } +RTLIL::Const RTLIL::const_divfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) +{ + int undef_bit_pos = -1; + BigInteger a = const2big(arg1, signed1, undef_bit_pos); + BigInteger b = const2big(arg2, signed2, undef_bit_pos); + if (b.isZero()) + return RTLIL::Const(RTLIL::State::Sx, result_len); + + bool result_pos = (a.getSign() == BigInteger::negative) == (b.getSign() == BigInteger::negative); + a = a.getSign() == BigInteger::negative ? -a : a; + b = b.getSign() == BigInteger::negative ? -b : b; + BigInteger result; + + if (result_pos || a == 0) { + result = a / b; + } else { + // bigint division with negative numbers is wonky, make sure we only negate at the very end + result = -((a + b - 1) / b); + } + return big2const(result, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0)); +} + RTLIL::Const RTLIL::const_modfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { int undef_bit_pos = -1; diff --git a/kernel/celledges.cc b/kernel/celledges.cc index 488ee9d02..314e7c77e 100644 --- a/kernel/celledges.cc +++ b/kernel/celledges.cc @@ -187,7 +187,7 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL return true; } - // FIXME: $mul $div $mod $modfloor $slice $concat + // FIXME: $mul $div $mod $divfloor $modfloor $slice $concat // FIXME: $lut $sop $alu $lcu $macc $fa return false; diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 37c251f7e..db54436cb 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -114,7 +114,7 @@ struct CellTypes ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), - ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($modfloor), ID($pow), + ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow), ID($logic_and), ID($logic_or), ID($concat), ID($macc) }; @@ -304,6 +304,7 @@ struct CellTypes HANDLE_CELL_TYPE(mul) HANDLE_CELL_TYPE(div) HANDLE_CELL_TYPE(mod) + HANDLE_CELL_TYPE(divfloor) HANDLE_CELL_TYPE(modfloor) HANDLE_CELL_TYPE(pow) HANDLE_CELL_TYPE(pos) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f2480ba5a..ca4201b53 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -948,7 +948,7 @@ namespace { return; } - if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($modfloor), ID($pow))) { + if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow))) { param_bool(ID::A_SIGNED); param_bool(ID::B_SIGNED); port(ID::A, param(ID::A_WIDTH)); @@ -1949,6 +1949,7 @@ DEF_METHOD(Sub, max(sig_a.size(), sig_b.size()), ID($sub)) DEF_METHOD(Mul, max(sig_a.size(), sig_b.size()), ID($mul)) DEF_METHOD(Div, max(sig_a.size(), sig_b.size()), ID($div)) DEF_METHOD(Mod, max(sig_a.size(), sig_b.size()), ID($mod)) +DEF_METHOD(DivFloor, max(sig_a.size(), sig_b.size()), ID($divfloor)) DEF_METHOD(ModFloor, max(sig_a.size(), sig_b.size()), ID($modfloor)) DEF_METHOD(LogicAnd, 1, ID($logic_and)) DEF_METHOD(LogicOr, 1, ID($logic_or)) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 6bb759928..140813326 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -466,6 +466,7 @@ namespace RTLIL RTLIL::Const const_sub (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_mul (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_div (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); + RTLIL::Const const_divfloor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_modfloor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_mod (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_pow (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); @@ -1205,6 +1206,7 @@ public: RTLIL::Cell* addMul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addDiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addMod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); + RTLIL::Cell* addDivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addPow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed = false, bool b_signed = false, const std::string &src = ""); @@ -1305,6 +1307,7 @@ public: RTLIL::SigSpec Mul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec Div (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec Mod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); + RTLIL::SigSpec DivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec ModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec Pow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool a_signed = false, bool b_signed = false, const std::string &src = ""); diff --git a/kernel/satgen.h b/kernel/satgen.h index 1d257aa2c..3929a8708 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -279,7 +279,7 @@ struct SatGen bool arith_undef_handled = false; bool is_arith_compare = cell->type.in(ID($lt), ID($le), ID($ge), ID($gt)); - if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($modfloor)) || is_arith_compare)) + if (model_undef && (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor)) || is_arith_compare)) { std::vector undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep); std::vector undef_b = importUndefSigSpec(cell->getPort(ID::B), timestep); @@ -293,7 +293,7 @@ struct SatGen int undef_any_b = ez->expression(ezSAT::OpOr, undef_b); int undef_y_bit = ez->OR(undef_any_a, undef_any_b); - if (cell->type.in(ID($div), ID($mod), ID($modfloor))) { + if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) { std::vector b = importSigSpec(cell->getPort(ID::B), timestep); undef_y_bit = ez->OR(undef_y_bit, ez->NOT(ez->expression(ezSAT::OpOr, b))); } @@ -935,7 +935,7 @@ struct SatGen return true; } - if (cell->type.in(ID($div), ID($mod), ID($modfloor))) + if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) { std::vector a = importDefSigSpec(cell->getPort(ID::A), timestep); std::vector b = importDefSigSpec(cell->getPort(ID::B), timestep); @@ -990,6 +990,19 @@ struct SatGen ez->assume(ez->vec_eq(y_tmp, y_u)); } else if (cell->type == ID($mod)) { ez->assume(ez->vec_eq(y_tmp, modulo_trunc)); + } else if (cell->type == ID($divfloor)) { + if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) + ez->assume(ez->vec_eq(y_tmp, ez->vec_ite( + ez->XOR(a.back(), b.back()), + ez->vec_neg(ez->vec_ite( + ez->vec_reduce_or(modulo_trunc), + ez->vec_add(y_u, ez->vec_const_unsigned(1, y_u.size())), + y_u + )), + y_u + ))); + else + ez->assume(ez->vec_eq(y_tmp, y_u)); } else if (cell->type == ID($modfloor)) { ez->assume(ez->vec_eq(y_tmp, ez->vec_ite(floored_eq_trunc, modulo_trunc, ez->vec_add(modulo_trunc, b)))); } @@ -998,7 +1011,7 @@ struct SatGen ez->assume(ez->expression(ezSAT::OpOr, b)); } else { std::vector div_zero_result; - if (cell->type == ID($div)) { + if (cell->type.in(ID($div), ID($divfloor))) { if (cell->parameters[ID::A_SIGNED].as_bool() && cell->parameters[ID::B_SIGNED].as_bool()) { std::vector all_ones(y.size(), ez->CONST_TRUE); std::vector only_first_one(y.size(), ez->CONST_FALSE); -- cgit v1.2.3 From 7c89738382a6262852781511882c1191423bdc39 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 2 May 2020 11:24:19 +0200 Subject: Add comments for mod/div semantics to rtlil.h --- kernel/rtlil.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'kernel') diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 140813326..a418c9996 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1204,7 +1204,9 @@ public: RTLIL::Cell* addAdd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addSub (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addMul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); + // truncating division RTLIL::Cell* addDiv (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); + // truncating modulo RTLIL::Cell* addMod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addDivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); RTLIL::Cell* addModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = ""); @@ -1305,7 +1307,9 @@ public: RTLIL::SigSpec Add (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec Sub (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec Mul (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); + // truncating division RTLIL::SigSpec Div (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); + // truncating modulo RTLIL::SigSpec Mod (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec DivFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); RTLIL::SigSpec ModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = ""); -- cgit v1.2.3 From efa7424fb93943d746a344d08e5e879d983709e9 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 27 May 2020 05:20:39 +0000 Subject: Restrict RTLIL::IdString to not contain whitespace or control chars. This is an existing invariant (most backends can't cope with these) but one that was not checked or documented. --- kernel/rtlil.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'kernel') diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 11c45bbec..898c54a3a 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -150,9 +150,6 @@ namespace RTLIL if (!p[0]) return 0; - log_assert(p[0] == '$' || p[0] == '\\'); - log_assert(p[1] != 0); - auto it = global_id_index_.find((char*)p); if (it != global_id_index_.end()) { #ifndef YOSYS_NO_IDS_REFCNT @@ -165,6 +162,11 @@ namespace RTLIL return it->second; } + log_assert(p[0] == '$' || p[0] == '\\'); + log_assert(p[1] != 0); + for (const char *c = p; *c; c++) + log_assert((unsigned)*c > (unsigned)' '); + #ifndef YOSYS_NO_IDS_REFCNT if (global_free_idx_list_.empty()) { if (global_id_storage_.empty()) { -- cgit v1.2.3