aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPeter Crozier <peter@crozier.com>2020-06-03 17:19:28 +0100
committerGitHub <noreply@github.com>2020-06-03 17:19:28 +0100
commit0d3f7ea011288e1a1fadd4ae27f1e8a57d729053 (patch)
tree07bde0d9f492233728070234aed2abd45fbd464d /kernel
parent17f050d3c6b8934141c42f96a3418de67a687b2c (diff)
parent46ed0db2ec883a4ce330c81f321511e36e35c0b3 (diff)
downloadyosys-0d3f7ea011288e1a1fadd4ae27f1e8a57d729053.tar.gz
yosys-0d3f7ea011288e1a1fadd4ae27f1e8a57d729053.tar.bz2
yosys-0d3f7ea011288e1a1fadd4ae27f1e8a57d729053.zip
Merge branch 'master' into struct
Diffstat (limited to 'kernel')
-rw-r--r--kernel/calc.cc47
-rw-r--r--kernel/celledges.cc2
-rw-r--r--kernel/celltypes.h4
-rw-r--r--kernel/constids.inc8
-rw-r--r--kernel/hashlib.h10
-rw-r--r--kernel/log.cc20
-rw-r--r--kernel/log.h19
-rw-r--r--kernel/rtlil.cc4
-rw-r--r--kernel/rtlil.h35
-rw-r--r--kernel/satgen.h42
-rw-r--r--kernel/timinginfo.h19
11 files changed, 156 insertions, 54 deletions
diff --git a/kernel/calc.cc b/kernel/calc.cc
index 4a4840771..ae18809d3 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,51 @@ 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;
+ 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..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 $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 450865ce9..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($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,8 @@ 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)
HANDLE_CELL_TYPE(neg)
diff --git a/kernel/constids.inc b/kernel/constids.inc
index 6b40a5908..383d7c615 100644
--- a/kernel/constids.inc
+++ b/kernel/constids.inc
@@ -2,13 +2,12 @@ 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_keep)
X(abc9_lut)
X(abc9_mergeability)
-X(abc9_scc)
X(abc9_scc_id)
X(abcgroup)
X(ABITS)
@@ -80,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)
@@ -170,6 +171,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/hashlib.h b/kernel/hashlib.h
index 592d6e577..5c87b55f5 100644
--- a/kernel/hashlib.h
+++ b/kernel/hashlib.h
@@ -207,6 +207,7 @@ class dict
entry_t() { }
entry_t(const std::pair<K, T> &udata, int next) : udata(udata), next(next) { }
entry_t(std::pair<K, T> &&udata, int next) : udata(std::move(udata)), next(next) { }
+ bool operator<(const entry_t &other) const { return udata.first < other.udata.first; }
};
std::vector<int> hashtable;
@@ -615,6 +616,15 @@ public:
return !operator==(other);
}
+ unsigned int hash() const {
+ unsigned int h = mkhash_init;
+ for (auto &entry : entries) {
+ h ^= hash_ops<K>::hash(entry.udata.first);
+ h ^= hash_ops<T>::hash(entry.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(); }
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<FILE*> log_files;
std::vector<std::ostream*> log_streams;
std::map<std::string, std::set<std::string>> log_hdump;
std::vector<YS_REGEX_TYPE> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
-std::vector<std::pair<YS_REGEX_TYPE,LogExpectedItem>> log_expect_log, log_expect_warning, log_expect_error;
+dict<std::string, LogExpectedItem> log_expect_log, log_expect_warning, log_expect_error;
std::set<std::string> 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..516744b50 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)
@@ -97,11 +97,11 @@ 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)
#else
# define YS_DEBUGTRAP_IF_DEBUGGING do {} while(0)
@@ -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<std::pair<YS_REGEX_TYPE,LogExpectedItem>> log_expect_log, log_expect_warning, log_expect_error;
+extern dict<std::string, LogExpectedItem> log_expect_log, log_expect_warning, log_expect_error;
void log_check_expected();
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 196e301b6..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($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,8 @@ 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))
#undef DEF_METHOD
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 11c45bbec..8228523d5 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()) {
@@ -296,8 +298,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; }
@@ -466,6 +468,8 @@ 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);
@@ -721,7 +725,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;
@@ -1134,8 +1138,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<RTLIL::Wire*> wires() { return RTLIL::ObjRange<RTLIL::Wire*>(&wires_, &refcount_wires_); }
RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); }
@@ -1196,8 +1206,12 @@ 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 = "");
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 = "");
@@ -1295,8 +1309,12 @@ 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 = "");
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 = "");
@@ -1494,7 +1512,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)
diff --git a/kernel/satgen.h b/kernel/satgen.h
index 88b84b7e6..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)) || 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<int> undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
std::vector<int> 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($divfloor), ID($modfloor))) {
std::vector<int> 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($divfloor), ID($modfloor)))
{
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
std::vector<int> b = importDefSigSpec(cell->getPort(ID::B), timestep);
@@ -970,23 +970,48 @@ struct SatGen
}
std::vector<int> y_tmp = ignore_div_by_zero ? yy : ez->vec_var(y.size());
+
+ // modulo calculation
+ std::vector<int> 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 {
+ } 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(a.back(), ez->vec_neg(chain_buf), chain_buf)));
+ 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, chain_buf));
+ 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))));
}
if (ignore_div_by_zero) {
ez->assume(ez->expression(ezSAT::OpOr, b));
} else {
std::vector<int> 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<int> all_ones(y.size(), ez->CONST_TRUE);
std::vector<int> only_first_one(y.size(), ez->CONST_FALSE);
@@ -996,7 +1021,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())
diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h
index fb4e0930d..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())
@@ -128,11 +131,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 +153,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)];