Keep strings as strings in const ternary and concat
authorClifford Wolf <clifford@clifford.at>
Thu, 5 Dec 2013 12:26:17 +0000 (13:26 +0100)
committerClifford Wolf <clifford@clifford.at>
Thu, 5 Dec 2013 12:26:17 +0000 (13:26 +0100)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/simplify.cc

index 7d5295a6ce75d3ab0f1340f4bfda0d68b27fdd56..0e65f1cb7d3020c60f7e46635d55ad7aa184afdf 100644 (file)
@@ -171,6 +171,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2)
        is_output = false;
        is_reg = false;
        is_signed = false;
+       is_string = false;
        range_valid = false;
        port_id = 0;
        range_left = -1;
@@ -591,6 +592,8 @@ bool AstNode::operator==(const AstNode &other) const
                return false;
        if (is_signed != other.is_signed)
                return false;
+       if (is_string != other.is_string)
+               return false;
        if (range_valid != other.range_valid)
                return false;
        if (port_id != other.port_id)
@@ -658,6 +661,14 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
        return node;
 }
 
+// create an AST node for a constant (using a string in bit vector form as value)
+AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
+{
+       AstNode *node = mkconst_str(RTLIL::Const(v).decode_string());
+       log_assert(node->bits == v);
+       return node;
+}
+
 // create an AST node for a constant (using a string as value)
 AstNode *AstNode::mkconst_str(const std::string &str)
 {
@@ -671,6 +682,7 @@ AstNode *AstNode::mkconst_str(const std::string &str)
                }
        }
        AstNode *node = AstNode::mkconst_bits(data, false);
+       node->is_string = true;
        node->str = str;
        return node;
 }
@@ -702,7 +714,7 @@ RTLIL::Const AstNode::asAttrConst()
        RTLIL::Const val;
        val.bits = bits;
 
-       if (!str.empty()) {
+       if (is_string) {
                val.flags |= RTLIL::CONST_FLAG_STRING;
                log_assert(val.decode_string() == str);
        }
index e9dfa5aceb4c1f039a992cf4dd5f0b6e94d43f8b..f8e27927418ff2213c159ec1905a8de84e4eaa21 100644 (file)
@@ -143,7 +143,7 @@ namespace AST
                // node content - most of it is unused in most node types
                std::string str;
                std::vector<RTLIL::State> bits;
-               bool is_input, is_output, is_reg, is_signed, range_valid;
+               bool is_input, is_output, is_reg, is_signed, is_string, range_valid;
                int port_id, range_left, range_right;
                uint32_t integer;
 
@@ -213,6 +213,7 @@ namespace AST
                // helper functions for creating AST nodes for constants
                static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32);
                static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
+               static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
                static AstNode *mkconst_str(const std::string &str);
 
                // helper function for creating sign-extended const objects
index fe4ff3f237129ec62414896144d44f2643255f21..f6df0c170457524f108664fed84b2f8c734d174c 100644 (file)
@@ -1176,6 +1176,7 @@ skip_dynamic_range_lvalue_expansion:;
        // perform const folding when activated
        if (const_fold && newNode == NULL)
        {
+               bool string_op;
                std::vector<RTLIL::State> tmp_bits;
                RTLIL::Const (*const_func)(const RTLIL::Const&, const RTLIL::Const&, bool, bool, int);
                RTLIL::Const dummy_arg;
@@ -1306,7 +1307,10 @@ skip_dynamic_range_lvalue_expansion:;
                                        choice = children[2];
                                if (choice != NULL && choice->type == AST_CONSTANT) {
                                        RTLIL::Const y = choice->bitsAsConst(width_hint, sign_hint);
-                                       newNode = mkconst_bits(y.bits, sign_hint);
+                                       if (choice->is_string && y.bits.size() % 8 == 0 && sign_hint == false)
+                                               newNode = mkconst_str(y.bits);
+                                       else
+                                               newNode = mkconst_bits(y.bits, sign_hint);
                                } else if (children[1]->type == AST_CONSTANT && children[2]->type == AST_CONSTANT) {
                                        RTLIL::Const a = children[1]->bitsAsConst(width_hint, sign_hint);
                                        RTLIL::Const b = children[2]->bitsAsConst(width_hint, sign_hint);
@@ -1319,19 +1323,22 @@ skip_dynamic_range_lvalue_expansion:;
                        }
                        break;
                case AST_CONCAT:
+                       string_op = !children.empty();
                        for (auto it = children.begin(); it != children.end(); it++) {
                                if ((*it)->type != AST_CONSTANT)
                                        goto not_const;
+                               if (!(*it)->is_string)
+                                       string_op = false;
                                tmp_bits.insert(tmp_bits.end(), (*it)->bits.begin(), (*it)->bits.end());
                        }
-                       newNode = mkconst_bits(tmp_bits, false);
+                       newNode = string_op ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
                        break;
                case AST_REPLICATE:
                        if (children.at(0)->type != AST_CONSTANT || children.at(1)->type != AST_CONSTANT)
                                goto not_const;
                        for (int i = 0; i < children[0]->bitsAsConst().as_int(); i++)
                                tmp_bits.insert(tmp_bits.end(), children.at(1)->bits.begin(), children.at(1)->bits.end());
-                       newNode = mkconst_bits(tmp_bits, false);
+                       newNode = children.at(1)->is_string ? mkconst_str(tmp_bits) : mkconst_bits(tmp_bits, false);
                        break;
                default:
                not_const: