improved (fixed) conversion of real values to bit vectors
authorClifford Wolf <clifford@clifford.at>
Sat, 14 Jun 2014 18:38:05 +0000 (20:38 +0200)
committerClifford Wolf <clifford@clifford.at>
Sat, 14 Jun 2014 19:00:51 +0000 (21:00 +0200)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc

index f3cf8fa7a618a03e483d1ec5e29f2d6615c30fda..25ea3a8248ded68a4eec8322cf016a0daad9c2d1 100644 (file)
@@ -794,6 +794,24 @@ double AstNode::asReal(bool is_signed)
        log_abort();
 }
 
+RTLIL::Const AstNode::realAsConst(int width)
+{
+       double v = round(realvalue);
+       RTLIL::Const result;
+       if (!isfinite(v)) {
+               result.bits = std::vector<RTLIL::State>(width, RTLIL::State::Sx);
+       } else {
+               bool is_negative = v < 0;
+               if (is_negative)
+                       v *= -1;
+               for (int i = 0; i < width; i++, v /= 2)
+                       result.bits.push_back((int(v) & 1) ? RTLIL::State::S1 : RTLIL::State::S0);
+               if (is_negative)
+                       result = const_neg(result, result, false, false, result.bits.size());
+       }
+       return result;
+}
+
 // create a new AstModule from an AST_MODULE AST node
 static AstModule* process_module(AstNode *ast, bool defer)
 {
index 95f0f142f98dc838c4acaa8cdf9e1ee78466d0a3..74a476b5ebffe72a6d26092fe7adcaa18fc9de87 100644 (file)
@@ -244,6 +244,7 @@ namespace AST
                // helper functions for real valued const eval
                int isConst(); // return '1' for AST_CONSTANT and '2' for AST_REALVALUE
                double asReal(bool is_signed);
+               RTLIL::Const realAsConst(int width);
        };
 
        // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
index 5b43f57ff9cfc4eb98aefb63d2d1757d145a32b6..8a57a0ee7967bd2141a1d78f53408c73414d7ff2 100644 (file)
@@ -915,10 +915,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 
        case AST_REALVALUE:
                {
-                       int intvalue = round(realvalue);
-                       log("Warning: converting real value %e to integer %d at %s:%d.\n",
-                                       realvalue, intvalue, filename.c_str(), linenum);
-                       return RTLIL::SigSpec(intvalue);
+                       RTLIL::SigSpec sig = realAsConst(width_hint);
+                       log("Warning: converting real value %e to binary %s at %s:%d.\n",
+                                       realvalue, log_signal(sig), filename.c_str(), linenum);
+                       return sig;
                }
 
        // simply return the corresponding RTLIL::SigSpec for an AST_IDENTIFIER node
index 61bc03b9f09f1f7e16704cfd3bcf9d11fbfc5fbd..ed5ee1721f901b3ed3ebf45462968f7f3f47fb10 100644 (file)
@@ -527,18 +527,18 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
        // trim/extend parameters
        if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
                if (children.size() > 1 && children[1]->type == AST_RANGE) {
+                       if (!children[1]->range_valid)
+                               log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
+                       int width = children[1]->range_left - children[1]->range_right + 1;
                        if (children[0]->type == AST_REALVALUE) {
-                               int intvalue = round(children[0]->realvalue);
-                               log("Warning: converting real value %e to integer %d at %s:%d.\n",
-                                               children[0]->realvalue, intvalue, filename.c_str(), linenum);
+                               RTLIL::Const constvalue = children[0]->realAsConst(width);
+                               log("Warning: converting real value %e to binary %s at %s:%d.\n",
+                                               realvalue, log_signal(constvalue), filename.c_str(), linenum);
                                delete children[0];
-                               children[0] = mkconst_int(intvalue, sign_hint);
+                               children[0] = mkconst_bits(constvalue.bits, sign_hint);
                                did_something = true;
                        }
                        if (children[0]->type == AST_CONSTANT) {
-                               if (!children[1]->range_valid)
-                                       log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
-                               int width = children[1]->range_left - children[1]->range_right + 1;
                                if (width != int(children[0]->bits.size())) {
                                        RTLIL::SigSpec sig(children[0]->bits);
                                        sig.extend_u0(width, children[0]->is_signed);