From 891e4b5b0d16a537e6d1ca0ecbc1ac3bafccecef Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 5 Dec 2013 13:26:17 +0100 Subject: Keep strings as strings in const ternary and concat --- frontends/ast/ast.cc | 14 +++++++++++++- frontends/ast/ast.h | 3 ++- frontends/ast/simplify.cc | 13 ++++++++++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 7d5295a6..0e65f1cb 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -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 &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 &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); } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index e9dfa5ac..f8e27927 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -143,7 +143,7 @@ namespace AST // node content - most of it is unused in most node types std::string str; std::vector 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 &v, bool is_signed); + static AstNode *mkconst_str(const std::vector &v); static AstNode *mkconst_str(const std::string &str); // helper function for creating sign-extended const objects diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index fe4ff3f2..f6df0c17 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1176,6 +1176,7 @@ skip_dynamic_range_lvalue_expansion:; // perform const folding when activated if (const_fold && newNode == NULL) { + bool string_op; std::vector 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: -- cgit v1.2.3