mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-06 06:03:23 +00:00
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.
This commit is contained in:
parent
0d99522b3c
commit
17163cf43a
23 changed files with 280 additions and 37 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue