[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