vhdlpp: Evaluate power (**) and division remainder (REM) operators.

This commit is contained in:
Maciej Suminski 2015-08-26 17:29:13 +02:00
parent a62a095717
commit 0569474d17
2 changed files with 24 additions and 4 deletions

View File

@ -375,6 +375,22 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
if(fun_ == REM) {
// Special case: division remainder, defined in the VHDL standard 1076-2008/9.2.7
// there is no direct counterpart, therefore output the formula to
// compute a remainder: A rem B = A - (A/B) * B;
out << "((";
errors += emit_operand1(out, ent, scope);
out << ")-((";
errors += emit_operand1(out, ent, scope);
out << ")/(";
errors += emit_operand2(out, ent, scope);
out << "))*(";
errors += emit_operand2(out, ent, scope);
out << "))";
return errors;
}
errors += emit_operand1(out, ent, scope); errors += emit_operand1(out, ent, scope);
switch (fun_) { switch (fun_) {
@ -396,9 +412,8 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope)
case POW: case POW:
out << " ** "; out << " ** ";
break; break;
case REM: case REM: // should not happen as it is handled above, suppress warnings
out << " /* ?remainder? */ "; ivl_assert(*this, 0);
break;
case xCONCAT: case xCONCAT:
ivl_assert(*this, 0); ivl_assert(*this, 0);
out << " /* ?concat? */ "; out << " /* ?concat? */ ";

View File

@ -23,6 +23,7 @@
# include "architec.h" # include "architec.h"
# include <ivl_assert.h> # include <ivl_assert.h>
# include <limits> # include <limits>
# include <cmath>
bool Expression::evaluate(ScopeBase*, int64_t&) const bool Expression::evaluate(ScopeBase*, int64_t&) const
{ {
@ -68,9 +69,13 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
val = val1 % val2; val = val1 % val2;
break; break;
case REM: case REM:
if (val2 == 0)
return false;
val = val1 - (val1 / val2) * val2;
return false; return false;
case POW: case POW:
return false; val = (int64_t) pow(val1, val2);
break;
case xCONCAT: // not possible case xCONCAT: // not possible
return false; return false;
} }