Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in Verilator signed/unsigned handling in power operator #730

Closed
veripoolbot opened this issue Apr 3, 2014 · 8 comments
Closed

Bug in Verilator signed/unsigned handling in power operator #730

veripoolbot opened this issue Apr 3, 2014 · 8 comments
Assignees
Labels
area: wrong runtime result Issue involves an incorrect runtine result from Verilated model resolution: fixed Closed; fixed

Comments

@veripoolbot
Copy link
Contributor


Author Name: Clifford Wolf (@cliffordwolf)
Original Redmine Issue: 730 from https://www.veripool.org
Original Date: 2014-04-03
Original Assignee: Wilson Snyder (@wsnyder)


The following module should return 0 for both outputs:

module issue016(y0, y1);
  output [3:0] y0;
  output [3:0] y1;
  assign y0  = -4'd1 ** -4'sd2;
  assign y1  = -4'd1 ** -4'sd3;
endmodule

But Verilator 3.856 sets y0 = 4'b0001 and y1 = 4'b1111.

Analysis: The 1st operand of the power operator is (unsigned) 4'b1111 in both cases. The 2nd operand of the power operator is self determined and its sign is not influenced by the rest of the expressions (see table 5-22 and sec. 5.5.1 of IEEE Std 1364-2005). According to table 5-6 of IEEE Std 1364-2005 this should return zero.

Crosscheck: Vivado 2013.4, XST 14.7, Isim 14.7 and Modelsim 10.1d implement this correctly.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2014-04-04T03:34:51Z


Well this is fun. Verilator isn't treating it as signed, for example do this

   $display("%b", ((-4'd1 ** -4'sd2)));
   $display("%b", ((-4'd1 ** -4'd2)));
   $display("%b", ((4'b1111 ** 4'b1110)));

You'll get the same answer from Verilator in each case ('b0001)

Basically this is an arithmetic overflow case, as 15**14 is crazy large.

// 15**14 = 155568095557812224 = 'h228b05bd21b8000

VCS and the simulators you tried give the ending correctly as 'b0000. NC-Verilog agrees with Verilator and gives 'b0001. My guess is most of the other simulators are using floating point math then taking LSBs. The standard isn't really clear on how much precision is required of the power operator, as expecting it to work with infinite size isn't reasonable, but I can get get more than 4 :)

Stay tuned, will fix in the next few days.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2014-04-04T03:48:00Z


Please post the results of this on your other simulators. It may be interesting.

module t;
initial begin
$display("wide %x", 64'h8765432187654321 ** 1);
$display("wide %x", 64'h8765432187654321 ** 2);
$display("wide %x", 64'h8765432187654321 ** 3);
$display("wide %x", 72'h876543218765432112 ** 1);
$display("wide %x", 72'h876543218765432112 ** 2);
$display("wide %x", 72'h876543218765432112 ** 3);
end
endmodule

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Clifford Wolf (@cliffordwolf)
Original Date: 2014-04-04T11:50:55Z


Wilson Snyder wrote:

My guess is most of the other simulators are using floating point math then taking LSBs.

I hope not. the correct way to do this is by using a power-modulus algorithm: http://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method.

See for example RTLIL::const_pow() from Yosys (near line 500):
https://github.com/cliffordwolf/yosys/blob/master/kernel/calc.cc

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Clifford Wolf (@cliffordwolf)
Original Date: 2014-04-04T12:00:04Z


Wilson Snyder wrote:

Please post the results of this on your other simulators. It may be interesting.

This is with modelsim:

1. wide 8765432187654321
1. wide f6e4895cd7a44a41
1. wide 29034dc25e419561
1. wide 876543218765432112
1. wide eec6cd8eae87b1a544
1. wide 9736d70c51859762c8

I get the same result with icarus verilog and Xilinx XSIM and if I synthesize an equivalent test module with yosys I also get the same result.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2014-04-05T20:07:15Z


Your test plus others I created turned up bugs in every simulator I tested, you are lucky you found any that worked. For example Icarus sets the output incorrectly and has a for() loop multiplying for every value of the LHS! You should file a bug on them too. Also NC does a negation case wrong, and VCS has a precision issue, I will bug them as I presume you don't have licenses for them since you didn't point out the discrepancies.

Anyhow I fixed several issues including one similar to your original hypothesis. Thanks for the references, though Verilator already uses the power-modulus algorithm. If you are interested it can be written even more efficiently by using shifts and writing it in a way to allow the compiler to do loop unrolling; see include/verilated.h for an example.

Pushed to git towards 3.857.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Clifford Wolf (@cliffordwolf)
Original Date: 2014-04-06T00:36:01Z


Wilson Snyder wrote:

For example Icarus sets the output incorrectly and has a for() loop multiplying for every value of the LHS! You should file a bug on them too.

I already did a while back, along with a couple of others:

https://github.com/steveicarus/iverilog/issues/created_by/cliffordwolf?page=1&state=closed

This is part of my VlogHammer project:

http://www.clifford.at/yosys/vloghammer.html

I added Verilator support the other day and just reported the first two bugs I've found. I'll run it again with the git head of Verilator soon. So brace yourself more bug reports in the near future.. ;)

Also NC does a negation case wrong, and VCS has a precision issue, I will bug them as I presume you don't have licenses for them since you didn't point out the discrepancies.

Please do that.

Anyhow I fixed several issues including one similar to your original hypothesis. Thanks for the references, though Verilator already uses the power-modulus algorithm. If you are interested it can be written even more efficiently by using shifts and writing it in a way to allow the compiler to do loop unrolling; see include/verilated.h for an example.

I'll have a look at it.

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2014-04-06T00:50:48Z


Neat. BTW you might want to look at test_verilated/vgen.v, which makes random verilog programs to test expression evaluation. It doesn't make any width violations though :)

@veripoolbot
Copy link
Contributor Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2014-05-11T21:08:23Z


In 3.860.

@veripoolbot veripoolbot added area: wrong runtime result Issue involves an incorrect runtine result from Verilated model resolution: fixed Closed; fixed labels Dec 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: wrong runtime result Issue involves an incorrect runtine result from Verilated model resolution: fixed Closed; fixed
Projects
None yet
Development

No branches or pull requests

2 participants