diff options
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/ast/ast.cc | 1 | ||||
-rw-r--r-- | frontends/ast/ast.h | 1 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 24 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 8 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 2 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 19 |
6 files changed, 55 insertions, 0 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 03fd272da..9520ae32c 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -95,6 +95,7 @@ std::string AST::type2str(AstNodeType type) X(AST_TO_SIGNED) X(AST_TO_UNSIGNED) X(AST_SELFSZ) + X(AST_CAST_SIZE) X(AST_CONCAT) X(AST_REPLICATE) X(AST_BIT_NOT) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 46864a4e1..9a5aa15f9 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -76,6 +76,7 @@ namespace AST AST_TO_SIGNED, AST_TO_UNSIGNED, AST_SELFSZ, + AST_CAST_SIZE, AST_CONCAT, AST_REPLICATE, AST_BIT_NOT, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 9546558aa..e878d0dd2 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -814,6 +814,16 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint); break; + case AST_CAST_SIZE: + while (children.at(0)->simplify(true, false, false, 1, -1, false, false)) { } + if (children.at(0)->type != AST_CONSTANT) + log_file_error(filename, location.first_line, "Static cast with non constant expression!\n"); + children.at(1)->detectSignWidthWorker(width_hint, sign_hint); + width_hint = children.at(0)->bitsAsConst().as_int(); + if (width_hint <= 0) + log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n"); + break; + case AST_CONCAT: for (auto child : children) { sub_width_hint = 0; @@ -1289,6 +1299,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) return sig; } + // changing the size of signal can be done directly using RTLIL::SigSpec + case AST_CAST_SIZE: { + RTLIL::SigSpec size = children[0]->genRTLIL(); + RTLIL::SigSpec sig = children[1]->genRTLIL(); + if (!size.is_fully_const()) + log_file_error(filename, location.first_line, "Static cast with non constant expression!\n"); + int width = size.as_int(); + if (width <= 0) + log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n"); + sig.extend_u0(width, sign_hint); + is_signed = sign_hint; + return sig; + } + // concatenation of signals can be done directly using RTLIL::SigSpec case AST_CONCAT: { RTLIL::SigSpec sig; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index c819924a0..c4df5c0a0 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -950,6 +950,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case AST_TO_SIGNED: case AST_TO_UNSIGNED: case AST_SELFSZ: + case AST_CAST_SIZE: case AST_CONCAT: case AST_REPLICATE: case AST_REDUCE_AND: @@ -3487,6 +3488,13 @@ replace_fcall_later:; } } break; + case AST_CAST_SIZE: + if (children.at(0)->type == AST_CONSTANT && children.at(1)->type == AST_CONSTANT) { + int width = children[0]->bitsAsConst().as_int(); + RTLIL::Const val = children[1]->bitsAsConst(width); + newNode = mkconst_bits(val.bits, children[1]->is_signed); + } + break; case AST_CONCAT: string_op = !children.empty(); for (auto it = children.begin(); it != children.end(); it++) { diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 028106381..f2241066f 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -517,6 +517,8 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { "<<<" { return OP_SSHL; } ">>>" { return OP_SSHR; } +"'" { return OP_CAST; } + "::" { return TOK_PACKAGESEP; } "++" { return TOK_INCREMENT; } "--" { return TOK_DECREMENT; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 96d9299fe..0fdf2b516 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -299,6 +299,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %left '+' '-' %left '*' '/' '%' %left OP_POW +%left OP_CAST %right UNARY_OPS %define parse.error verbose @@ -3042,6 +3043,24 @@ basic_expr: $$ = new AstNode(AST_LOGIC_NOT, $3); SET_AST_NODE_LOC($$, @1, @3); append_attr($$, $2); + } | + TOK_SIGNED OP_CAST '(' expr ')' { + if (!sv_mode) + frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); + $$ = new AstNode(AST_TO_SIGNED, $4); + SET_AST_NODE_LOC($$, @1, @4); + } | + TOK_UNSIGNED OP_CAST '(' expr ')' { + if (!sv_mode) + frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); + $$ = new AstNode(AST_TO_UNSIGNED, $4); + SET_AST_NODE_LOC($$, @1, @4); + } | + basic_expr OP_CAST '(' expr ')' { + if (!sv_mode) + frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode."); + $$ = new AstNode(AST_CAST_SIZE, $1, $4); + SET_AST_NODE_LOC($$, @1, @4); }; concat_list: |