summaryrefslogtreecommitdiff
path: root/frontends
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2013-11-07 22:20:00 +0100
committerClifford Wolf <clifford@clifford.at>2013-11-07 22:20:00 +0100
commitfc6dc0d7b8d3580df50558473c5d6365fd303191 (patch)
treea0a27650eaed7654dd6b43c12c6b87c7e531c38a /frontends
parentd7cb62ac96c34a13707112718fe06353a4f34526 (diff)
Fixed handling of power operator
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/genrtlil.cc28
-rw-r--r--frontends/ast/simplify.cc4
2 files changed, 22 insertions, 10 deletions
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 0c9c9be7..2e8ab749 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -1070,6 +1070,23 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
return binop2rtlil(this, type_name, width, left, right);
}
+ // generate cells for binary operations: $pow
+ case AST_POW:
+ {
+ int right_width;
+ bool right_signed;
+ children[1]->detectSignWidth(right_width, right_signed);
+ if (width_hint < 0)
+ detectSignWidth(width_hint, sign_hint);
+ RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
+ RTLIL::SigSpec right = children[1]->genRTLIL(right_width, right_signed);
+ int width = width_hint > 0 ? width_hint : left.width;
+ is_signed = children[0]->is_signed;
+ if (!flag_noopt && left.is_fully_const() && left.as_int() == 2 && !right_signed)
+ return binop2rtlil(this, "$shl", width, RTLIL::SigSpec(1, left.width), right);
+ return binop2rtlil(this, "$pow", width, left, right);
+ }
+
// generate cells for binary operations: $lt, $le, $eq, $ne, $ge, $gt
if (0) { case AST_LT: type_name = "$lt"; }
if (0) { case AST_LE: type_name = "$le"; }
@@ -1088,19 +1105,18 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
return sig;
}
- // generate cells for binary operations: $add, $sub, $mul, $div, $mod, $pow
+ // generate cells for binary operations: $add, $sub, $mul, $div, $mod
if (0) { case AST_ADD: type_name = "$add"; }
if (0) { case AST_SUB: type_name = "$sub"; }
if (0) { case AST_MUL: type_name = "$mul"; }
if (0) { case AST_DIV: type_name = "$div"; }
if (0) { case AST_MOD: type_name = "$mod"; }
- if (0) { case AST_POW: type_name = "$pow"; }
{
if (width_hint < 0)
detectSignWidth(width_hint, sign_hint);
RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
- RTLIL::SigSpec right = type == AST_POW ? children[1]->genRTLIL() : children[1]->genRTLIL(width_hint, sign_hint);
- int width = type == AST_POW ? left.width : std::max(left.width, right.width);
+ RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
+ int width = std::max(left.width, right.width);
if (width > width_hint && width_hint > 0)
width = width_hint;
if (width < width_hint) {
@@ -1110,12 +1126,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
width = width_hint;
if (type == AST_MUL)
width = std::min(left.width + right.width, width_hint);
- if (type == AST_POW)
- width = width_hint;
}
is_signed = children[0]->is_signed && children[1]->is_signed;
- if (!flag_noopt && type == AST_POW && left.is_fully_const() && left.as_int() == 2)
- return binop2rtlil(this, "$shl", width, RTLIL::SigSpec(1, left.width), right);
return binop2rtlil(this, type_name, width, left, right);
}
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 449ade43..5c0130d4 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -1017,9 +1017,10 @@ skip_dynamic_range_lvalue_expansion:;
if (0) { case AST_SHIFT_RIGHT: const_func = RTLIL::const_shr; }
if (0) { case AST_SHIFT_SLEFT: const_func = RTLIL::const_sshl; }
if (0) { case AST_SHIFT_SRIGHT: const_func = RTLIL::const_sshr; }
+ if (0) { case AST_POW: const_func = RTLIL::const_pow; }
if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
- RTLIL::Const(children[1]->bits), sign_hint, false, width_hint);
+ RTLIL::Const(children[1]->bits), sign_hint, type == AST_POW ? sign_hint : false, width_hint);
newNode = mkconst_bits(y.bits, sign_hint);
}
break;
@@ -1042,7 +1043,6 @@ skip_dynamic_range_lvalue_expansion:;
if (0) { case AST_MUL: const_func = RTLIL::const_mul; }
if (0) { case AST_DIV: const_func = RTLIL::const_div; }
if (0) { case AST_MOD: const_func = RTLIL::const_mod; }
- if (0) { case AST_POW: const_func = RTLIL::const_pow; }
if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
RTLIL::Const y = const_func(children[0]->bitsAsConst(width_hint, sign_hint),
children[1]->bitsAsConst(width_hint, sign_hint), sign_hint, sign_hint, width_hint);