Implemented basic real arithmetic
authorClifford Wolf <clifford@clifford.at>
Sat, 14 Jun 2014 06:51:22 +0000 (08:51 +0200)
committerClifford Wolf <clifford@clifford.at>
Sat, 14 Jun 2014 06:51:22 +0000 (08:51 +0200)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/simplify.cc

index 1ce7efc84d60f9c7031c76e3f5f43904e316c691..3af08b9d132f6cb4e89895e1fb51c2dc6b337e43 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <sstream>
 #include <stdarg.h>
-#include <assert.h>
+#include <math.h>
 
 using namespace AST;
 using namespace AST_INTERNAL;
@@ -760,6 +760,35 @@ bool AstNode::asBool()
        return false;
 }
 
+int AstNode::isConst()
+{
+       if (type == AST_CONSTANT)
+               return 1;
+       if (type == AST_REALVALUE)
+               return 2;
+       return 0;
+}
+
+double AstNode::asReal(bool is_signed)
+{
+       if (type == AST_CONSTANT) {
+               RTLIL::Const val;
+               val.bits = bits;
+
+               double p = exp2(val.bits.size()-32);
+               if (val.bits.size() > 32)
+                       val.bits.erase(val.bits.begin(), val.bits.begin()+(val.bits.size()-32));
+               int32_t v = val.as_int() << (32-val.bits.size());
+
+               if (is_signed)
+                       return v * p;
+               return uint32_t(v) * p;
+       }
+       if (type == AST_REALVALUE)
+               return realvalue;
+       return 0;
+}
+
 // create a new AstModule from an AST_MODULE AST node
 static AstModule* process_module(AstNode *ast, bool defer)
 {
index aeb56e352de8d471d0820e9353adf9fffc417294..95f0f142f98dc838c4acaa8cdf9e1ee78466d0a3 100644 (file)
@@ -240,6 +240,10 @@ namespace AST
                RTLIL::Const asAttrConst();
                RTLIL::Const asParaConst();
                bool asBool();
+
+               // helper functions for real valued const eval
+               int isConst(); // return '1' for AST_CONSTANT and '2' for AST_REALVALUE
+               double asReal(bool is_signed);
        };
 
        // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
index fc040baac0bf4682c0f8a09055e370460ac01c99..7e4c265bded498efe73fdf8459ef3f59bb00024f 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <sstream>
 #include <stdarg.h>
-#include <assert.h>
+#include <math.h>
 
 using namespace AST;
 using namespace AST_INTERNAL;
@@ -1433,10 +1433,22 @@ 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 (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);
-                               newNode = mkconst_bits(y.bits, sign_hint);
+                       if (children[0]->isConst() && children[1]->isConst()) {
+                               if (children[0]->isConst() + children[1]->isConst() > 2) {
+                                       newNode = new AstNode(AST_REALVALUE);
+                                       switch (type) {
+                                       case AST_ADD: newNode->realvalue = children[0]->asReal(sign_hint) + children[1]->asReal(sign_hint); break;
+                                       case AST_SUB: newNode->realvalue = children[0]->asReal(sign_hint) - children[1]->asReal(sign_hint); break;
+                                       case AST_MUL: newNode->realvalue = children[0]->asReal(sign_hint) * children[1]->asReal(sign_hint); break;
+                                       case AST_DIV: newNode->realvalue = children[0]->asReal(sign_hint) / children[1]->asReal(sign_hint); break;
+                                       case AST_MOD: newNode->realvalue = fmod(children[0]->asReal(sign_hint), children[1]->asReal(sign_hint)); break;
+                                       default: log_abort();
+                                       }
+                               } else {
+                                       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);
+                                       newNode = mkconst_bits(y.bits, sign_hint);
+                               }
                        }
                        break;
                if (0) { case AST_POS: const_func = RTLIL::const_pos; }