From 149fe83a8dbe37fecc16326163bbc40400147a9a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 14 Jun 2014 20:38:05 +0200 Subject: [PATCH] improved (fixed) conversion of real values to bit vectors --- frontends/ast/ast.cc | 18 ++++++++++++++++++ frontends/ast/ast.h | 1 + frontends/ast/genrtlil.cc | 8 ++++---- frontends/ast/simplify.cc | 14 +++++++------- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index f3cf8fa7a..25ea3a824 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -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(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) { diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 95f0f142f..74a476b5e 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -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 diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 5b43f57ff..8a57a0ee7 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -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 diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 61bc03b9f..ed5ee1721 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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); -- 2.30.2