static cast: support changing size and signedness
authorKazuki Sakamoto <sakamoto@splhack.org>
Sun, 14 Jun 2020 22:15:59 +0000 (15:15 -0700)
committerKazuki Sakamoto <sakamoto@splhack.org>
Sat, 20 Jun 2020 00:39:20 +0000 (17:39 -0700)
Support SystemVerilog Static Cast
- size
- signedness
- (type is not supposted yet)

Fix #535

frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
frontends/verilog/verilog_lexer.l
frontends/verilog/verilog_parser.y

index 03fd272dafd43c0af4bf1360353582d4d9cd4bf3..9520ae32c764eef1ce3ede0ef0246d1012b41724 100644 (file)
@@ -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)
index 46864a4e1b6a0c4c674536bc4d4d420edc18f02f..9a5aa15f941844a7168c2b15f77ee5081ad4e135 100644 (file)
@@ -76,6 +76,7 @@ namespace AST
                AST_TO_SIGNED,
                AST_TO_UNSIGNED,
                AST_SELFSZ,
+               AST_CAST_SIZE,
                AST_CONCAT,
                AST_REPLICATE,
                AST_BIT_NOT,
index 9546558aae34709a87bd4958b9a7bddd4ee6e885..e878d0dd2bacf131e2461bbee0356e07eda5d4e3 100644 (file)
@@ -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;
index 5f026dfed890f2dad0f1ff4b29b30ba839417381..1d5dd91a7ac602012ddd1b1458d09c12c6496071 100644 (file)
@@ -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:
index e6fa6361e076926d1d8a12bbf0e273fbd9860892..6195bb14962bf7834163177554a9252493a5d992 100644 (file)
@@ -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; }
index 15c231f3b98b1b02f4724b0b2df14ced514259a5..bbf1a436b80986926db746b5c8f3716a25282e17 100644 (file)
@@ -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: