[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [fpu] fdiv problem
on 8/28/00 17:25, Jamil Khatib at jamilkhatib75@yahoo.com wrote:
...
>> The test pattern generator generates proper floating
>> point
>> numbers and results. It appears that you don't
>> understand how
>> to integrate it into a test bench and how to write a
>> test
>> bench.
>
> yes I do not know how to use it in the testbench
> forgive me I am very new to verilog.
It is irrelevant what tool you use, VHDL or verilog,
it appears to me that you do not understand the basics.
>
> You need to learn to look at floating point
>> numbers in
>> their native IEEE representation and understand what
>> it all
>> means.
>
> what is the reason for that?
Because that is the standard. That is what every IEEE
compliant fpu uses.
> Finally when I ran the program in verbose mode and
> after following the code I found that you are
> generating the exceptions and the results
>
> You only provide the result from library and ignore
> the native result
If you would have read my previous emails, I would not
have to waste my time and explain it to you again.
The reason I am ignoring the host results are:
1) I do not know how to set the rounding mode in C
2) I do not know how to catch exceptions in C
3) The author claims that SoftFloat is 100% IEEE
compliant. At this point I believe it.
> The code seems to generate the same test vectors again
> and again for the same parameteres, why???
Read the help screen. When you use -p option, it will
use pre defined values from a table. If you want random
code you should omit -p, then it will generate semi-random
code. I do not change the seed, so the random code will
always be based on the same seed. That's something that
should be an option in the program. I will add it later.
> Do you depend on the test bench to decide if the
> result of the core is correct or on the software?
The test bench. It has to compare the result from the core
against what was provided by the program. In some cases,
when I'm not sure who is correct, I do the math with a
pencil and paper, and reread the IEEE standard. So far the
program was always correct.
> I hope so, but still I have to do rounding that you
> said you are working on, I do not want to have
> different results
Beyond rounding, you need to make sure that INF, and NAN
operators are handled properly. You also must generate
all exceptions, they are generated differently for each
block.
> Anyhow I give you always the status of my work but no
> one give his work status, is not it a cooperative
> work?
I'm in constant communication with Dmajan, at this point
I feel it is more important to ensure that he can use the
fpu.
> Can you please be kind and resend the test bench
> interface again?
Attached is my entire test bench.
>>> Jamil Khatib
>>
>> rudi
rudi
test_top.v
/////////////////////////////////////////////////////////////////////
//// ////
//// FPU ////
//// Floating Point Unit (Single precision) ////
//// ////
//// TEST BENCH ////
//// ////
//// Author: Rudolf Usselmann ////
//// russelmann@hotmail.com ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Rudolf Usselmann ////
//// russelmann@hotmail.com ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT ////
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND ////
//// FITNESS FOR A PARTICULAR PURPOSE. ////
//// ////
/////////////////////////////////////////////////////////////////////
`timescale 1ns / 10ps
module test;
reg clk;
reg [31:0] opa;
reg [31:0] opb;
wire [31:0] sum;
wire inf, snan, qnan;
reg [31:0] exp, exp1, exp2, exp3, exp4;
reg [31:0] opa1, opa2, opa3, opa4;
reg [31:0] opb1, opb2, opb3, opb4;
reg [2:0] fpu_op1, fpu_op2, fpu_op3, fpu_op4;
reg start, s1, s2, s3, s4;
reg [107:0] tmem[0:200000];
reg [107:0] tmp;
reg [3:0] oper;
reg [7:0] exc, exc1, exc2, exc3, exc4;
integer i;
wire ine;
reg match;
wire overflow, underflow;
wire zero;
reg exc_err;
reg m0, m1, m2;
reg [1:0] rnd_mode;
reg [3:0] test_rmode;
reg [2:0] fpu_op;
reg fp_add;
reg fp_mul;
event error_event;
integer error, vcount;
always #50 clk = ~clk;
initial
begin
$display ("\n\nFloating Point Unit Version 1.4\n\n");
clk = 0;
start = 0;
s1 = 0;
s2 = 0;
s3 = 0;
s4 = 0;
error = 0;
vcount = 0;
fp_add=0;
fp_mul=1;
test_rmode = 4'b1111;
@(posedge clk);
if(fp_add)
begin
$display("\n\nTesting FP Add/Sub Unit\n");
if(test_rmode[0])
begin
rnd_mode = 0;
$display("\n+++++ ROUNDING MODE: Nearest Even\n\n");
if(1)
begin
$display("\nRunning Pat 0 Add Test ...\n");
$readmemh ("test_vectors/rtne/fasu_pat0a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 0 Sub Test ...\n");
$readmemh ("test_vectors/rtne/fasu_pat0b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Add Test ...\n");
$readmemh ("test_vectors/rtne/fasu_pat1a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Sub Test ...\n");
$readmemh ("test_vectors/rtne/fasu_pat1b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Add Test ...\n");
$readmemh ("test_vectors/rtne/fasu_pat2a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Sub Test ...\n");
$readmemh ("test_vectors/rtne/fasu_pat2b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Add Test ...\n");
$readmemh ("test_vectors/rtne/fasu_lga.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Sub Test ...\n");
$readmemh ("test_vectors/rtne/fasu_lgb.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Add Test ...\n");
$readmemh ("test_vectors/rtne/fasu_sma.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Sub Test ...\n");
$readmemh ("test_vectors/rtne/fasu_smb.hex", tmem);
run_test;
end
end
if(test_rmode[1])
begin
rnd_mode = 1;
$display("\n\n+++++ ROUNDING MODE: Towards Zero\n\n");
if(1)
begin
$display("\nRunning Pat 0 Add Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_pat0a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 0 Sub Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_pat0b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Add Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_pat1a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Sub Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_pat1b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Add Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_pat2a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Sub Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_pat2b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Add Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_lga.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Sub Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_lgb.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Add Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_sma.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Sub Test ...\n");
$readmemh ("test_vectors/rtzero/fasu_smb.hex", tmem);
run_test;
end
end
if(test_rmode[2])
begin
rnd_mode = 2;
$display("\n\n+++++ ROUNDING MODE: Towards INF+ (UP)\n\n");
if(1)
begin
$display("\nRunning Pat 0 Add Test ...\n");
$readmemh ("test_vectors/rup/fasu_pat0a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 0 Sub Test ...\n");
$readmemh ("test_vectors/rup/fasu_pat0b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Add Test ...\n");
$readmemh ("test_vectors/rup/fasu_pat1a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Sub Test ...\n");
$readmemh ("test_vectors/rup/fasu_pat1b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Add Test ...\n");
$readmemh ("test_vectors/rup/fasu_pat2a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Sub Test ...\n");
$readmemh ("test_vectors/rup/fasu_pat2b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Add Test ...\n");
$readmemh ("test_vectors/rup/fasu_lga.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Sub Test ...\n");
$readmemh ("test_vectors/rup/fasu_lgb.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Add Test ...\n");
$readmemh ("test_vectors/rup/fasu_sma.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Sub Test ...\n");
$readmemh ("test_vectors/rup/fasu_smb.hex", tmem);
run_test;
end
end
if(test_rmode[3])
begin
rnd_mode = 3;
$display("\n\n+++++ ROUNDING MODE: Towards INF- (DOWN)\n\n");
if(1)
begin
$display("\nRunning Pat 0 Add Test ...\n");
$readmemh ("test_vectors/rdown/fasu_pat0a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 0 Sub Test ...\n");
$readmemh ("test_vectors/rdown/fasu_pat0b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Add Test ...\n");
$readmemh ("test_vectors/rdown/fasu_pat1a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Sub Test ...\n");
$readmemh ("test_vectors/rdown/fasu_pat1b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Add Test ...\n");
$readmemh ("test_vectors/rdown/fasu_pat2a.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Sub Test ...\n");
$readmemh ("test_vectors/rdown/fasu_pat2b.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Add Test ...\n");
$readmemh ("test_vectors/rdown/fasu_lga.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Sub Test ...\n");
$readmemh ("test_vectors/rdown/fasu_lgb.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Add Test ...\n");
$readmemh ("test_vectors/rdown/fasu_sma.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Sub Test ...\n");
$readmemh ("test_vectors/rdown/fasu_smb.hex", tmem);
run_test;
end
end
end
if(fp_mul)
begin
$display("\n\nTesting FP MUL Unit\n");
if(test_rmode[0])
begin
rnd_mode = 0;
$display("\n+++++ ROUNDING MODE: Nearest Even\n\n");
if(1)
begin
$display("\nRunning Pat 0 Test ...\n");
$readmemh ("test_vectors/rtne/fmul_pat0.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 1 Test ...\n");
$readmemh ("test_vectors/rtne/fmul_pat1.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Pat 2 Test ...\n");
$readmemh ("test_vectors/rtne/fmul_pat2.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Lg. Num Test ...\n");
$readmemh ("test_vectors/rtne/fmul_lg.hex", tmem);
run_test;
end
if(1)
begin
$display("\nRunning Random Sm. Num Test ...\n");
$readmemh ("test_vectors/rtne/fmul_sm.hex", tmem);
run_test;
end
end
end
repeat (4) @(posedge clk);
$display("\n\n");
$display("\n\nAll test Done !\n\n");
$display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
$finish;
end
task run_test;
begin
oper = 1;
i=0;
while( |oper == 1'b1 )
begin
@(posedge clk);
#1;
start = 1;
tmp = tmem[i];
exc = tmp[107:100];
oper = tmp[99:96];
// oper fpu operation
// 1 add
// 2 sub
// 4 mul
// 8 div
if(oper==1) fpu_op=3'b000; // Add
else
if(oper==2) fpu_op=3'b001; // Sub
else
if(oper==4) fpu_op=3'b010; // Mul
else
if(oper==8) fpu_op=3'b011; // Div
else fpu_op=3'bx;
//if(oper==1) add=1;
//else
//if(oper==2) add=0;
//else add=1'bx;
//if(oper==4) $write("*");
//else
//if(oper==2) $write("-");
opa = tmp[95:64];
opb = tmp[63:32];
exp = tmp[31:00];
i= i+1;
end
start = 0;
for(i=0;i<200000;i=i+1)
tmem[i] = 108'hxxxxxxxxxxxxxxxxx;
end
endtask
always @(posedge clk)
begin
s1 <= #1 start;
s2 <= #1 s1;
s3 <= #1 s2;
s4 <= #1 s3;
exp1 <= #1 exp;
exp2 <= #1 exp1;
exp3 <= #1 exp2;
exp4 <= #1 exp3;
opa1 <= #1 opa;
opa2 <= #1 opa1;
opa3 <= #1 opa2;
opa4 <= #1 opa3;
opb1 <= #1 opb;
opb2 <= #1 opb1;
opb3 <= #1 opb2;
opb4 <= #1 opb3;
fpu_op1 <= #1 fpu_op;
fpu_op2 <= #1 fpu_op1;
fpu_op3 <= #1 fpu_op2;
fpu_op4 <= #1 fpu_op3;
exc1 <= #1 exc;
exc2 <= #1 exc1;
exc3 <= #1 exc2;
exc4 <= #1 exc3;
#3;
// Floating Point Exceptions ( exc4 )
// -------------------------
// float_flag_invalid = 1,
// float_flag_divbyzero = 4,
// float_flag_overflow = 8,
// float_flag_underflow = 16,
// float_flag_inexact = 32
/*
$display("Expected Exception: %h\n",exc4);
if(ine) $display("Got INE Exception ...\n");
if(overflow) $display("Got overflow Exception ...\n");
if(underflow) $display("Got underflow Exception ...\n");
if(inf) $display("Got INF Exception ...\n");
if(nan) $display("Got NAN Exception ...\n");
*/
exc_err=0;
if(ine !== exc4[5])
begin
exc_err=1;
$display("\nERROR: INE Exception: Expected: %h, Got %h\n",exc4[5],ine);
end
if(overflow !== exc4[3])
begin
exc_err=1;
$display("\nERROR: Overflow Exception Expected: %h, Got %h\n",exc4[3],overflow);
end
if(underflow !== exc4[4])
begin
exc_err=1;
$display("\nERROR: Underflow Exception Expected: %h, Got %h\n",exc4[4],underflow);
end
if(zero !== !(|sum[30:0]))
begin
exc_err=1;
$display("\nERROR: Zero Detection Failed. ZERO: %h, Sum: %h\n", zero, sum);
end
if(inf !== ( (sum[30:23] == 8'hff) & ((|sum[22:0]) == 1'b0) ) )
begin
exc_err=1;
$display("\nERROR: INF Detection Failed. INF: %h, Sum: %h\n", inf, sum);
end
if(qnan !== ( &sum[30:23] & |sum[22:0] ) )
begin
exc_err=1;
$display("\nERROR: QNAN Detection Failed. QNAN: %h, Sum: %h\n", qnan, sum);
end
if(snan !== ( ( &opa4[30:23] & !opa4[22] & |opa4[21:0]) | ( &opb4[30:23] & !opb4[22] & |opb4[21:0]) ) )
begin
exc_err=1;
$display("\nERROR: SNAN Detection Failed. SNAN: %h, OpA: %h, OpB: %h\n", snan, opa4, opb4);
end
m0 = ( (|sum) !== 1'b1) & ( (|sum) !== 1'b0); // result unknown (ERROR)
m1 = (exp4 === sum); // results are equal
// NAN *** Ignore Fraction Detail ***
m2 = (sum[31] == exp4[31]) &
(sum[30:23] == 8'hff) & (exp4[30:23] == 8'hff) &
(sum[22] == exp4[22]) &
( (|sum[22:0]) == 1'b1) & ((|exp4[22:0]) == 1'b1);
match = m1 | m2;
if( ( exc_err | !match | m0) & s4 )
begin
-> error_event;
#0.6;
$display("\n%t: ERROR: output mismatch. Expected %h, Got %h (%h)", $time, exp4, sum, {opa4, opb4, exp4} );
$write("opa:\t"); disp_fp(opa4);
case(fpu_op4)
0: $display("\t+");
1: $display("\t-");
2: $display("\t*");
3: $display("\t/");
default: $display("\t Unknown Operation ");
endcase
$write("opb:\t"); disp_fp(opb4);
$write("EXP:\t"); disp_fp(exp4);
$write("GOT:\t"); disp_fp(sum);
$display("\n");
error = error + 1;
end
if(s4) vcount = vcount + 1;
if(error > 20)
begin
@(posedge clk);
$display("\n\nFound to many errors, aborting ...\n\n");
$display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
$finish;
end
end
fasu u0(clk, rnd_mode, fpu_op, opa, opb, sum, inf, snan, qnan, ine, overflow, underflow, zero);
task disp_fp;
input [31:0] fp;
reg [63:0] x;
reg [7:0] exp;
begin
exp = fp[30:23];
if(exp==8'h7f) $write("(%h %h ( 00 ) %h) ",fp[31], exp, fp[22:0]);
else
if(exp>8'h7f) $write("(%h %h (+%d ) %h) ",fp[31], exp, exp-8'h7f, fp[22:0]);
else $write("(%h %h (-%d ) %h) ",fp[31], exp, 8'h7f-exp, fp[22:0]);
x[51:0] = {fp[22:0], 29'h0};
x[63] = fp[31];
x[62] = fp[30];
x[61:59] = {fp[29], fp[29], fp[29]};
x[58:52] = fp[29:23];
$display("\t%f",$bitstoreal(x));
end
endtask
endmodule