From 5c6c8deba391d2dedd32f1115938b0bb3d69254c Mon Sep 17 00:00:00 2001 From: Alexander Klimov Date: Thu, 15 Sep 2011 00:33:12 +0300 Subject: [PATCH] Fix long division. On a 64-bit machine the following module shows incorrect division results: `define X {4'b 1000, `N'b 0} `define Y {1'b 1, `N'b 0} module b; reg [`N:0] y = `Y; reg [3:0] z1, z2; initial begin z1 = `X / `Y; z2 = `X / y; $display("%3d %b %b", `N, z1, z2); end endmodule // b $ for N in {60..65}; do /usr/bin/iverilog -DN=$N -oa b.v && /usr/bin/vvp a; done 60 1000 1000 61 1000 1000 62 1000 0111 63 1000 0101 64 1000 1000 65 1000 1000 The first chunk of the patch (result -> tmp_result) fixes this: $ for N in {60..65}; do iverilog -DN=$N -oa b.v && vvp a; done 60 1000 1000 61 1000 1000 62 1000 1000 63 1000 1000 64 1000 1000 65 1000 1000 The second chunk fixes `define X 264'h 800000000000000000000000000000000000000000000000000000000000000000 `define Y 192'h c6df998d06b97b0db1f056638484d609c0895e8112153524 module c; reg [191:0] y = `Y; reg [72:0] z1, z2; initial begin z1 = `X / `Y; z2 = `X / y; $display("%x %x %b", z1, z2, z1 == z2); end endmodule // c $ /usr/bin/iverilog -oa c.v && /usr/bin/vvp a 0a4c4a2c1dacd76220c 0809033397ca3427927 0 $ iverilog -oa c.v && vvp a 0a4c4a2c1dacd76220c 0a4c4a2c1dacd76220c 1 (cherry picked from commit 766bf45dcfa1536b8d46d0a798612e375a4eb10e) --- vvp/vthread.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 333032639..df37225b7 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1956,7 +1956,7 @@ static unsigned long divide2words(unsigned long a, unsigned long b, remain += 1; if (remain >= b) { remain -= b; - result += 1; + tmp_result += 1; } // Now 0x1_0...0 = b*tmp_result + remain @@ -1972,7 +1972,9 @@ static unsigned long divide2words(unsigned long a, unsigned long b, // The new iteration starts with high*remain + a. remain = multiply_with_carry(high, remain, high); - a = add_with_carry(a, remain, high); + a += remain; + if(a < remain) + high += 1; // Now result*b + {high,a} == the input {high,a}. It is // possible that the new high >= 1. If so, it will