More fixes in ast expression sign/width handling

This commit is contained in:
Clifford Wolf 2013-07-09 23:41:28 +02:00
parent 618b2ac994
commit 5dab327b30
2 changed files with 22 additions and 21 deletions

View File

@ -530,7 +530,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint)
break; break;
case AST_TO_UNSIGNED: case AST_TO_UNSIGNED:
children.at(0)->detectSignWidthWorker(width_hint, sign_hint); children.at(0)->detectSignWidthWorker(width_hint, dummy_sign_hint);
sign_hint = false; sign_hint = false;
break; break;
@ -593,8 +593,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint)
case AST_LOGIC_AND: case AST_LOGIC_AND:
case AST_LOGIC_OR: case AST_LOGIC_OR:
case AST_LOGIC_NOT: case AST_LOGIC_NOT:
for (auto child : children) width_hint = std::max(width_hint, 1);
child->detectSignWidthWorker(width_hint, sign_hint); sign_hint = false;
break; break;
case AST_TERNARY: case AST_TERNARY:
@ -835,7 +835,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// just pass thru the signal. the parent will evaluated the is_signed property and inperpret the SigSpec accordingly // just pass thru the signal. the parent will evaluated the is_signed property and inperpret the SigSpec accordingly
case AST_TO_SIGNED: case AST_TO_SIGNED:
case AST_TO_UNSIGNED: { case AST_TO_UNSIGNED: {
RTLIL::SigSpec sig = children[0]->genRTLIL(width_hint, sign_hint); RTLIL::SigSpec sig = children[0]->genRTLIL();
is_signed = type == AST_TO_SIGNED; is_signed = type == AST_TO_SIGNED;
return sig; return sig;
} }
@ -889,6 +889,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (0) { case AST_BIT_XOR: type_name = "$xor"; } if (0) { case AST_BIT_XOR: type_name = "$xor"; }
if (0) { case AST_BIT_XNOR: type_name = "$xnor"; } if (0) { case AST_BIT_XNOR: type_name = "$xnor"; }
{ {
if (width_hint < 0)
detectSignWidth(width_hint, sign_hint);
RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint); RTLIL::SigSpec left = children[0]->genRTLIL(width_hint, sign_hint);
RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint); RTLIL::SigSpec right = children[1]->genRTLIL(width_hint, sign_hint);
int width = std::max(left.width, right.width); int width = std::max(left.width, right.width);
@ -965,12 +967,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (width > width_hint && width_hint > 0) if (width > width_hint && width_hint > 0)
width = width_hint; width = width_hint;
if (width < width_hint) { if (width < width_hint) {
if (type == AST_ADD || type == AST_SUB) { if (type == AST_ADD || type == AST_SUB)
width++; width++;
if (width < width_hint && children[0]->is_signed != children[1]->is_signed) if (type == AST_SUB && (!children[0]->is_signed || !children[1]->is_signed))
width++;
}
if (type == AST_SUB && !children[0]->is_signed && !children[1]->is_signed)
width = width_hint; width = width_hint;
if (type == AST_MUL) if (type == AST_MUL)
width = std::min(left.width + right.width, width_hint); width = std::min(left.width + right.width, width_hint);

View File

@ -27,19 +27,21 @@ module test04(a, y);
assign y = ~(a - 1'b0); assign y = ~(a - 1'b0);
endmodule endmodule
module test05(a, y); // .. this test triggers a bug in xilinx isim.
input a; // module test05(a, y);
output y; // input a;
assign y = 12345 >> {a, 32'd0}; // output y;
endmodule // assign y = 12345 >> {a, 32'd0};
// endmodule
module test06(a, b, c, y); // .. this test triggers a bug in icarus verilog.
input signed [3:0] a; // module test06(a, b, c, y);
input signed [1:0] b; // input signed [3:0] a;
input signed [1:0] c; // input signed [1:0] b;
output [5:0] y; // input signed [1:0] c;
assign y = (a >> b) >>> c; // output [5:0] y;
endmodule // assign y = (a >> b) >>> c;
// endmodule
module test07(a, b, y); module test07(a, b, y);
input signed [1:0] a; input signed [1:0] a;