From d06258f74f724ea3ed26ec9341dd64a51e320ccf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 1 Feb 2014 13:50:23 +0100 Subject: [PATCH] Added constant size expression support of sized constants --- README | 4 ++++ frontends/ast/ast.cc | 1 + frontends/ast/ast.h | 1 + frontends/ast/genrtlil.cc | 8 ++++++++ frontends/ast/simplify.cc | 12 ++++++++++++ frontends/verilog/parser.y | 22 ++++++++++++++++++++++ 6 files changed, 48 insertions(+) diff --git a/README b/README index f0c9bc747..ee5eb7979 100644 --- a/README +++ b/README @@ -275,6 +275,10 @@ Verilog Attributes and non-standard features always block: "assert();". It is transformed to a $assert cell that is supported by the "sat" and "write_btor" commands. +- Sized constants (the syntax 's?[bodh]) support constant + expressions as . 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 ==================================== diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 40f7826f1..96608ae37 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -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) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index caae679a1..01702c3cf 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -61,6 +61,7 @@ namespace AST AST_ASSERT, AST_FCALL, + AST_TO_BITS, AST_TO_SIGNED, AST_TO_UNSIGNED, AST_CONCAT, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 6001e278a..99d8566dc 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -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; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 5a2d1ae6c..f19befe2a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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; diff --git a/frontends/verilog/parser.y b/frontends/verilog/parser.y index b0c4db8ae..5b6bf58c2 100644 --- a/frontends/verilog/parser.y +++ b/frontends/verilog/parser.y @@ -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) -- 2.30.2