diff options
author | Kazuki Sakamoto <sakamoto@splhack.org> | 2020-06-14 15:15:59 -0700 |
---|---|---|
committer | Kazuki Sakamoto <sakamoto@splhack.org> | 2020-06-19 17:39:20 -0700 |
commit | 185bbbe681d02874796e70a1ee147f4b8dca6cbb (patch) | |
tree | 31ad1e634e09fdd40776a8c44a407d2b6d416f69 | |
parent | 338ecbe02f8bb3cc4d69de1445c7f398a814b4e4 (diff) | |
download | yosys-185bbbe681d02874796e70a1ee147f4b8dca6cbb.tar.gz yosys-185bbbe681d02874796e70a1ee147f4b8dca6cbb.tar.bz2 yosys-185bbbe681d02874796e70a1ee147f4b8dca6cbb.zip |
static cast: support changing size and signedness
Support SystemVerilog Static Cast
- size
- signedness
- (type is not supposted yet)
Fix #535
-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 | 1 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 2 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 19 |
6 files changed, 48 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 5f026dfed..1d5dd91a7 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: diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index e6fa6361e..6195bb149 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 15c231f3b..bbf1a436b 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -298,6 +298,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) %left '+' '-' %left '*' '/' '%' %left OP_POW +%left OP_CAST %right UNARY_OPS %define parse.error verbose @@ -3001,6 +3002,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: |