mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Merge pull request #2179 from splhack/static-cast
Support SystemVerilog Static Cast
This commit is contained in:
commit
8ce4f8790e
|
@ -95,6 +95,7 @@ std::string AST::type2str(AstNodeType type)
|
||||||
X(AST_TO_SIGNED)
|
X(AST_TO_SIGNED)
|
||||||
X(AST_TO_UNSIGNED)
|
X(AST_TO_UNSIGNED)
|
||||||
X(AST_SELFSZ)
|
X(AST_SELFSZ)
|
||||||
|
X(AST_CAST_SIZE)
|
||||||
X(AST_CONCAT)
|
X(AST_CONCAT)
|
||||||
X(AST_REPLICATE)
|
X(AST_REPLICATE)
|
||||||
X(AST_BIT_NOT)
|
X(AST_BIT_NOT)
|
||||||
|
|
|
@ -76,6 +76,7 @@ namespace AST
|
||||||
AST_TO_SIGNED,
|
AST_TO_SIGNED,
|
||||||
AST_TO_UNSIGNED,
|
AST_TO_UNSIGNED,
|
||||||
AST_SELFSZ,
|
AST_SELFSZ,
|
||||||
|
AST_CAST_SIZE,
|
||||||
AST_CONCAT,
|
AST_CONCAT,
|
||||||
AST_REPLICATE,
|
AST_REPLICATE,
|
||||||
AST_BIT_NOT,
|
AST_BIT_NOT,
|
||||||
|
|
|
@ -814,6 +814,16 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
||||||
children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint);
|
children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint);
|
||||||
break;
|
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:
|
case AST_CONCAT:
|
||||||
for (auto child : children) {
|
for (auto child : children) {
|
||||||
sub_width_hint = 0;
|
sub_width_hint = 0;
|
||||||
|
@ -1289,6 +1299,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
return sig;
|
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
|
// concatenation of signals can be done directly using RTLIL::SigSpec
|
||||||
case AST_CONCAT: {
|
case AST_CONCAT: {
|
||||||
RTLIL::SigSpec sig;
|
RTLIL::SigSpec sig;
|
||||||
|
|
|
@ -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_SIGNED:
|
||||||
case AST_TO_UNSIGNED:
|
case AST_TO_UNSIGNED:
|
||||||
case AST_SELFSZ:
|
case AST_SELFSZ:
|
||||||
|
case AST_CAST_SIZE:
|
||||||
case AST_CONCAT:
|
case AST_CONCAT:
|
||||||
case AST_REPLICATE:
|
case AST_REPLICATE:
|
||||||
case AST_REDUCE_AND:
|
case AST_REDUCE_AND:
|
||||||
|
@ -3487,6 +3488,13 @@ replace_fcall_later:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case AST_CONCAT:
|
||||||
string_op = !children.empty();
|
string_op = !children.empty();
|
||||||
for (auto it = children.begin(); it != children.end(); it++) {
|
for (auto it = children.begin(); it != children.end(); it++) {
|
||||||
|
|
|
@ -517,6 +517,8 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
|
||||||
"<<<" { return OP_SSHL; }
|
"<<<" { return OP_SSHL; }
|
||||||
">>>" { return OP_SSHR; }
|
">>>" { return OP_SSHR; }
|
||||||
|
|
||||||
|
"'" { return OP_CAST; }
|
||||||
|
|
||||||
"::" { return TOK_PACKAGESEP; }
|
"::" { return TOK_PACKAGESEP; }
|
||||||
"++" { return TOK_INCREMENT; }
|
"++" { return TOK_INCREMENT; }
|
||||||
"--" { return TOK_DECREMENT; }
|
"--" { return TOK_DECREMENT; }
|
||||||
|
|
|
@ -299,6 +299,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
|
||||||
%left '+' '-'
|
%left '+' '-'
|
||||||
%left '*' '/' '%'
|
%left '*' '/' '%'
|
||||||
%left OP_POW
|
%left OP_POW
|
||||||
|
%left OP_CAST
|
||||||
%right UNARY_OPS
|
%right UNARY_OPS
|
||||||
|
|
||||||
%define parse.error verbose
|
%define parse.error verbose
|
||||||
|
@ -3042,6 +3043,24 @@ basic_expr:
|
||||||
$$ = new AstNode(AST_LOGIC_NOT, $3);
|
$$ = new AstNode(AST_LOGIC_NOT, $3);
|
||||||
SET_AST_NODE_LOC($$, @1, @3);
|
SET_AST_NODE_LOC($$, @1, @3);
|
||||||
append_attr($$, $2);
|
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:
|
concat_list:
|
||||||
|
|
4
tests/svtypes/static_cast_negative.ys
Normal file
4
tests/svtypes/static_cast_negative.ys
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
logger -expect error "Static cast with zero or negative size" 1
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top; wire [7:0] a = (-1)'(a); endmodule
|
||||||
|
EOT
|
4
tests/svtypes/static_cast_nonconst.ys
Normal file
4
tests/svtypes/static_cast_nonconst.ys
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
logger -expect error "Static cast with non constant expression" 1
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top; wire [7:0] a, b = (a)'(0); endmodule
|
||||||
|
EOT
|
64
tests/svtypes/static_cast_simple.sv
Normal file
64
tests/svtypes/static_cast_simple.sv
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
module top;
|
||||||
|
wire [7:0] a, b, c, d;
|
||||||
|
assign a = 8'd16;
|
||||||
|
assign b = 8'd16;
|
||||||
|
assign c = (a * b) >> 8;
|
||||||
|
assign d = (16'(a) * b) >> 8;
|
||||||
|
|
||||||
|
parameter P = 16;
|
||||||
|
|
||||||
|
wire signed [7:0] s0, s1, s2;
|
||||||
|
wire [7:0] u0, u1, u2, u3, u4, u5, u6;
|
||||||
|
assign s0 = -8'd1;
|
||||||
|
assign s1 = 4'(s0);
|
||||||
|
assign s2 = 4'(unsigned'(s0));
|
||||||
|
assign u0 = -8'd1;
|
||||||
|
assign u1 = 4'(u0);
|
||||||
|
assign u2 = 4'(signed'(u0));
|
||||||
|
assign u3 = 8'(4'(s0));
|
||||||
|
assign u4 = 8'(4'(u0));
|
||||||
|
assign u5 = 8'(4'(signed'(-8'd1)));
|
||||||
|
assign u6 = 8'(4'(unsigned'(-8'd1)));
|
||||||
|
|
||||||
|
wire [8:0] n0, n1, n2, n3, n4, n5, n6, n7, n8, n9;
|
||||||
|
assign n0 = s1;
|
||||||
|
assign n1 = s2;
|
||||||
|
assign n2 = 9'(s1);
|
||||||
|
assign n3 = 9'(s2);
|
||||||
|
assign n4 = 9'(unsigned'(s1));
|
||||||
|
assign n5 = 9'(unsigned'(s2));
|
||||||
|
assign n6 = 9'(u0);
|
||||||
|
assign n7 = 9'(u1);
|
||||||
|
assign n8 = 9'(signed'(u0));
|
||||||
|
assign n9 = 9'(signed'(u1));
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
assert(c == 8'b0000_0000);
|
||||||
|
assert(d == 8'b0000_0001);
|
||||||
|
|
||||||
|
assert((P + 1)'(a) == 17'b0_0000_0000_0001_0000);
|
||||||
|
assert((P + 1)'(d - 2) == 17'b1_1111_1111_1111_1111);
|
||||||
|
|
||||||
|
assert(s0 == 8'b1111_1111);
|
||||||
|
assert(s1 == 8'b1111_1111);
|
||||||
|
assert(s2 == 8'b0000_1111);
|
||||||
|
assert(u0 == 8'b1111_1111);
|
||||||
|
assert(u1 == 8'b0000_1111);
|
||||||
|
assert(u2 == 8'b1111_1111);
|
||||||
|
assert(u3 == 8'b1111_1111);
|
||||||
|
assert(u4 == 8'b0000_1111);
|
||||||
|
assert(u5 == 8'b1111_1111);
|
||||||
|
assert(u6 == 8'b0000_1111);
|
||||||
|
|
||||||
|
assert(n0 == 9'b1_1111_1111);
|
||||||
|
assert(n1 == 9'b0_0000_1111);
|
||||||
|
assert(n2 == 9'b1_1111_1111);
|
||||||
|
assert(n3 == 9'b0_0000_1111);
|
||||||
|
assert(n4 == 9'b0_1111_1111);
|
||||||
|
assert(n5 == 9'b0_0000_1111);
|
||||||
|
assert(n6 == 9'b0_1111_1111);
|
||||||
|
assert(n7 == 9'b0_0000_1111);
|
||||||
|
assert(n8 == 9'b1_1111_1111);
|
||||||
|
assert(n9 == 9'b0_0000_1111);
|
||||||
|
end
|
||||||
|
endmodule
|
4
tests/svtypes/static_cast_verilog.ys
Normal file
4
tests/svtypes/static_cast_verilog.ys
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
logger -expect error "Static cast is only supported in SystemVerilog mode" 1
|
||||||
|
read_verilog <<EOT
|
||||||
|
module top; wire [7:0] a = 1'(a); endmodule
|
||||||
|
EOT
|
4
tests/svtypes/static_cast_zero.ys
Normal file
4
tests/svtypes/static_cast_zero.ys
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
logger -expect error "Static cast with zero or negative size" 1
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top; wire [7:0] a = 0'(a); endmodule
|
||||||
|
EOT
|
Loading…
Reference in a new issue