Added constant size expression support of sized constants
authorClifford Wolf <clifford@clifford.at>
Sat, 1 Feb 2014 12:50:23 +0000 (13:50 +0100)
committerClifford Wolf <clifford@clifford.at>
Sat, 1 Feb 2014 12:50:23 +0000 (13:50 +0100)
README
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
frontends/verilog/parser.y

diff --git a/README b/README
index f0c9bc747321197136ef7b7e4a95f5b02f417ff0..ee5eb797904163afc4b144994ff477aece2ee447 100644 (file)
--- a/README
+++ b/README
@@ -275,6 +275,10 @@ Verilog Attributes and non-standard features
   always block: "assert(<expression>);". It is transformed to a $assert cell
   that is supported by the "sat" and "write_btor" commands.
 
+- Sized constants (the syntax <size>'s?[bodh]<value>) support constant
+  expressions as <size>. If the expresion is not a simple identifier, it
+  must be put in parentheses. Examples: WIDTH'd42, (4+2)'b101010
+
 
 Workarounds for known build problems
 ====================================
index 40f7826f1aba3f2a0dd0f20172a876bbb1be3257..96608ae37d6c68a42abe4d34834266d6e9ae4ee2 100644 (file)
@@ -82,6 +82,7 @@ std::string AST::type2str(AstNodeType type)
        X(AST_PREFIX)
        X(AST_ASSERT)
        X(AST_FCALL)
+       X(AST_TO_BITS)
        X(AST_TO_SIGNED)
        X(AST_TO_UNSIGNED)
        X(AST_CONCAT)
index caae679a11d8e1af70bbd0734853d1fa237dbda6..01702c3cfef970717a67126654542ca2537b054f 100644 (file)
@@ -61,6 +61,7 @@ namespace AST
                AST_ASSERT,
 
                AST_FCALL,
+               AST_TO_BITS,
                AST_TO_SIGNED,
                AST_TO_UNSIGNED,
                AST_CONCAT,
index 6001e278a4adffe8c977f943073d9f330ee7613b..99d8566dca1e7fc240cf8b74e0e4e53894719283 100644 (file)
@@ -664,6 +664,14 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint)
                        sign_hint = false;
                break;
 
+       case AST_TO_BITS:
+               while (children[0]->simplify(true, false, false, 1, -1, false) == true) { }
+               if (children[0]->type != AST_CONSTANT)
+                       log_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+               children[1]->detectSignWidthWorker(sub_width_hint, sign_hint);
+               width_hint = std::max(width_hint, children[0]->bitsAsConst().as_int());
+               break;
+
        case AST_TO_SIGNED:
                children.at(0)->detectSignWidthWorker(width_hint, sub_sign_hint);
                break;
index 5a2d1ae6c4e8847c08f0bf6f79077f7a25f3f304..f19befe2ab22d8c12ff6d000ca041f01b389fe1f 100644 (file)
@@ -258,6 +258,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                }
                break;
 
+       case AST_TO_BITS:
        case AST_TO_SIGNED:
        case AST_TO_UNSIGNED:
        case AST_CONCAT:
@@ -442,6 +443,17 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                goto apply_newNode;
        }
 
+       // evaluate TO_BITS nodes
+       if (type == AST_TO_BITS) {
+               if (children[0]->type != AST_CONSTANT)
+                       log_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+               if (children[1]->type != AST_CONSTANT)
+                       log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+               RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed);
+               newNode = mkconst_bits(new_value.bits, children[1]->is_signed);
+               goto apply_newNode;
+       }
+
        // annotate constant ranges
        if (type == AST_RANGE) {
                bool old_range_valid = range_valid;
index b0c4db8ae08bfed08e84ae9aaa40ceab72034b13..5b6bf58c287f1721ca5d447ae3d67bdc6e39a819 100644 (file)
@@ -1051,6 +1051,28 @@ basic_expr:
        rvalue {
                $$ = $1;
        } |
+       '(' expr ')' TOK_CONST {
+               if ($4->substr(0, 1) != "'")
+                       frontend_verilog_yyerror("Syntax error.");
+               AstNode *bits = $2;
+               AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back());
+               if (val == NULL)
+                       log_error("Value conversion failed: `%s'\n", $4->c_str());
+               $$ = new AstNode(AST_TO_BITS, bits, val);
+               delete $4;
+       } |
+       hierarchical_id TOK_CONST {
+               if ($2->substr(0, 1) != "'")
+                       frontend_verilog_yyerror("Syntax error.");
+               AstNode *bits = new AstNode(AST_IDENTIFIER);
+               bits->str = *$1;
+               AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back());
+               if (val == NULL)
+                       log_error("Value conversion failed: `%s'\n", $2->c_str());
+               $$ = new AstNode(AST_TO_BITS, bits, val);
+               delete $1;
+               delete $2;
+       } |
        TOK_CONST {
                $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back());
                if ($$ == NULL)