Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main

This commit is contained in:
Ross Thompson 2022-02-21 12:46:22 -06:00
commit 3ba70b74d6
8 changed files with 494 additions and 889 deletions

View File

@ -3,5 +3,5 @@ all: sqrttestgen testgen
sqrttestgen: sqrttestgen.c
gcc sqrttestgen.c -lm -o sqrttestgen
testgen: testgen.c
gcc testgen.c -lm -o testgen
testgen: exptestgen.c
gcc exptestgen.c -lm -o exptestgen

BIN
pipelined/srt/exptestgen Executable file

Binary file not shown.

121
pipelined/srt/exptestgen.c Normal file
View File

@ -0,0 +1,121 @@
/* testgen.c */
/* Written 2/19/2022 by David Harris
This program creates test vectors for mantissa and exponent components
of an IEEE floating point divider.
Builds upon program that creates test vectors for mantissa component only.
*/
/* #includes */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* Constants */
#define ENTRIES 17
#define RANDOM_VECS 500
// #define BIAS 1023 // Bias is for double precision
/* Prototypes */
void output(FILE *fptr, int e1, double a, int e2, double b, int r_exp, double r_mantissa);
void printhex(FILE *fptr, double x);
double random_input(void);
double random_input_e(void);
/* Main */
void main(void)
{
FILE *fptr;
// e1 & e2 are exponents
// a & b are mantissas
// r_mantissa is result of mantissa divsion
// r_exp is result of exponent division
double a, b, r_mantissa, r_exp;
int e1, e2;
double mantissa[ENTRIES] = {1, 1.5, 1.25, 1.125, 1.0625,
1.75, 1.875, 1.99999,
1.1, 1.2, 1.01, 1.001, 1.0001,
1/1.1, 1/1.5, 1/1.25, 1/1.125};
int exponent[ENTRIES] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
int i, j;
int bias = 1023;
if ((fptr = fopen("testvectors","w")) == NULL) {
fprintf(stderr, "Couldn't write testvectors file\n");
exit(1);
}
for (i=0; i<ENTRIES; i++) {
b = mantissa[i];
e2 = exponent[i] + bias;
for (j=0; j<ENTRIES; j++) {
a = mantissa[j];
e1 = exponent[j] + bias;
r_mantissa = a/b;
r_exp = e1 - e2 + bias;
output(fptr, e1, a, e2, b, r_exp, r_mantissa);
}
}
// for (i = 0; i< RANDOM_VECS; i++) {
// a = random_input();
// b = random_input();
// e1 = random_input_e() + BIAS; // make new random input function for exponents
// e2 = random_input_e() + BIAS;
// r_mantissa = a/b;
// r_exp = e1 - e2 + BIAS;
// output(fptr, e1, a, e2, b, r_exp, r_mantissa);
// }
fclose(fptr);
}
/* Functions */
void output(FILE *fptr, int e1, double a, int e2, double b, int r_exp, double r_mantissa)
{
fprintf(fptr, "%03x", e1);
//printhex(fptr, e1, exp);
printhex(fptr, a);
fprintf(fptr, "_");
fprintf(fptr, "%03x", e2);
//printhex(fptr, e2, exp);
printhex(fptr, b);
fprintf(fptr, "_");
fprintf(fptr, "%03x", r_exp);
//printhex(fptr, r_exp, exp);
printhex(fptr, r_mantissa);
fprintf(fptr, "\n");
}
void printhex(FILE *fptr, double m)
{
int i, val, len;
len = 52;
while (m<1) m *= 2;
while (m>2) m /= 2;
for (i=0; i<len; i+=4) {
m = m - floor(m);
m = m * 16;
val = (int)(m)%16;
fprintf(fptr, "%x", val);
}
}
double random_input(void)
{
return 1.0 + rand()/32767.0;
}
double random_input_e(void)
{
return rand() % 300 + 1;
}

View File

@ -1 +1,2 @@
verilator --lint-only --top-module srt srt.sv -I../config/rv64gc -I../config/shared ../src/generic/*.sv ../src/generic/flop/*.sv
verilator --lint-only --top-module testbench testbench.sv -I../config/rv64gc -I../config/shared ../src/generic/*.sv ../src/generic/flop/*.sv ../src/fpu/unpacking.sv

View File

@ -37,6 +37,8 @@ module srt #(parameter Nf=52) (
input logic Flush, // *** multiple pipe stages
// Floating Point Inputs
// later add exponents, signs, special cases
input logic [10:0] SrcXExpE, SrcYExpE, // exponents, for double precision exponents are 11 bits
// end of floating point inputs
input logic [Nf-1:0] SrcXFrac, SrcYFrac,
input logic [`XLEN-1:0] SrcA, SrcB,
input logic [1:0] Fmt, // Floats: 00 = 16 bit, 01 = 32 bit, 10 = 64 bit, 11 = 128 bit
@ -45,6 +47,7 @@ module srt #(parameter Nf=52) (
input logic Int, // Choose integer inputss
input logic Sqrt, // perform square root, not divide
output logic [Nf-1:0] Quot, Rem, // *** later handle integers
output logic [10:0] Exp, // output exponent is hardcoded for 11 bits for double precision
output logic [3:0] Flags
);
@ -78,6 +81,9 @@ module srt #(parameter Nf=52) (
// Partial Product Generation
csa csa(WS, WC, Dsel, qp, WSA, WCA);
// Exponent division
exp exp(SrcXExpE, SrcYExpE, Exp);
srtpostproc postproc(rp, rm, Quot);
endmodule
@ -247,6 +253,14 @@ module csa #(parameter N=56) (
(in2[54:0] & in3[54:0]), cin};
endmodule
//////////////
// exponent //
//////////////
module exp(input [10:0] e1, e2,
output [10:0] e); // for double precision, exponent is 11 bits
assign e = (e1 - e2) + 11'd1023; // bias is hardcoded
endmodule
//////////////
// finaladd //
//////////////

View File

@ -14,49 +14,6 @@
`include "wally-config.vh"
// will also be used for integer division so keep in mind when naming modules/signals
/////////////////
// srt_divide //
////////////////
module srt_divide(input logic clk,
input logic req,
input logic sqrt, // 1 to compute sqrt(a), 0 to compute a/b
input logic [63:0] a, b, // input numbers
output logic [54:0] rp, rm,
output logic [10:0] expE);
// output logic from Unpackers
logic XSgnE, YSgnE, ZSgnE;
logic [10:0] XExpE, YExpE, ZExpE; // exponent
logic [52:0] XManE, YManE, ZManE;
logic XNormE;
logic XNaNE, YNaNE, ZNaNE;
logic XSNaNE, YSNaNE, ZSNaNE;
logic XDenormE, YDenormE, ZDenormE; // denormals
logic XZeroE, YZeroE, ZZeroE;
logic [10:0] BiasE; // currrently hardcoded, will probs be removed
logic XInfE, YInfE, ZInfE;
logic XExpMaxE; // says exponent is all ones, can ignore
// have Unpackers
// have mantissa divider
// exponent divider
// hopefully having the .* here works for unpacker --- nope it doesn't
unpack unpacking(a, b, 0, 1'b1, 0, XSgnE, YSgnE, ZSgnE, XExpE, YExpE, ZExpE, XManE, YManE, ZManE, XNormE,XNaNE, YNaNE, ZNaNE,XSNaNE, YSNaNE, ZSNaNE,XDenormE, YDenormE, ZDenormE,XZeroE, YZeroE, ZZeroE,BiasE,XInfE, YInfE, ZInfE,XExpMaxE);
srt srt(clk, req, XManE[51:0], YManE[51:0], rp, rm);
exp exp(XexpE, YExpE, expE);
endmodule
// exponent module
// first iteration
module exp(input [10:0] e1, e2,
output [10:0] e); // for a 64 bit number, exponent section is 11 bits
assign e = (e1 - e2) + 11'd1023; // bias is hardcoded
endmodule
/////////
// srt //
/////////
@ -84,12 +41,12 @@ module srt(input logic clk,
// When start is asserted, the inputs are loaded into the divider.
// Otherwise, the divisor is retained and the partial remainder
// is fed back for the next iteration.
mux2_special psmux({psa[54:0], 1'b0}, {4'b0001, a}, req, psn);
flop_special psflop(clk, psn, ps);
mux2_special pcmux({pca[54:0], 1'b0}, 56'b0, req, pcn);
flop_special pcflop(clk, pcn, pc);
mux2_special dmux(d, {4'b0001, b}, req, dn);
flop_special dflop(clk, dn, d);
mux2 psmux({psa[54:0], 1'b0}, {4'b0001, a}, req, psn);
flop psflop(clk, psn, ps);
mux2 pcmux({pca[54:0], 1'b0}, 56'b0, req, pcn);
flop pcflop(clk, pcn, pc);
mux2 dmux(d, {4'b0001, b}, req, dn);
flop dflop(clk, dn, d);
// Quotient Selection logic
// Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
@ -99,7 +56,7 @@ module srt(input logic clk,
// Divisor Selection logic
inv dinv(d, d_b);
mux3_special divisorsel(d_b, 56'b0, d, qp, qz, qm, dsel);
mux3 divisorsel(d_b, 56'b0, d, qp, qz, qm, dsel);
// Partial Product Generation
csa csa(ps, pc, dsel, qp, psa, pca);
@ -108,7 +65,7 @@ endmodule
//////////
// mux2 //
//////////
module mux2_special(input logic [55:0] in0, in1,
module mux2(input logic [55:0] in0, in1,
input logic sel,
output logic [55:0] out);
@ -118,7 +75,7 @@ endmodule
//////////
// flop //
//////////
module flop_special(clk, in, out);
module flop(clk, in, out);
input clk;
input [55:0] in;
output [55:0] out;
@ -204,9 +161,9 @@ module inv(input logic [55:0] in,
endmodule
//////////
// mux3_special //
// mux3 //
//////////
module mux3_special(in0, in1, in2, sel0, sel1, sel2, out);
module mux3(in0, in1, in2, sel0, sel1, sel2, out);
input [55:0] in0;
input [55:0] in1;
input [55:0] in2;
@ -316,24 +273,6 @@ module testbench;
logic [51:0] b;
logic [51:0] r;
logic [54:0] rp, rm; // positive quotient digits
//input logic [63:0] X, Y, Z, - numbers
//input logic FmtE, ---- format, 1 is for double precision, 0 is single
//input logic [2:0] FOpCtrlE, ---- controling operations for FPU, 1 is sqrt, 0 is divide
// all variables are commented in fpu.sv
// output logic from Unpackers
logic XSgnE, YSgnE, ZSgnE;
logic [10:0] XExpE, YExpE, ZExpE; // exponent
logic [52:0] XManE, YManE, ZManE;
logic XNormE;
logic XNaNE, YNaNE, ZNaNE;
logic XSNaNE, YSNaNE, ZSNaNE;
logic XDenormE, YDenormE, ZDenormE; // denormals
logic XZeroE, YZeroE, ZZeroE;
logic [10:0] BiasE; // currrently hardcoded, will probs be removed
logic XInfE, YInfE, ZInfE;
logic XExpMaxE; // says exponent is all ones, can ignore
// Test parameters
parameter MEM_SIZE = 40000;
@ -350,15 +289,8 @@ module testbench;
logic [51:0] correctr, nextr;
integer testnum, errors;
// Unpackers
unpacking unpack(.X({12'b100010000010,a}), .Y({12'b100010000001,b}), .Z(0), .FmtE(1'b1), .FOpCtrlE(0), .*);
// Divider
srt srt(.clk(clk), .req(req), .sqrt(1'b0), .a(XManE[51:0]), .b(YManE[51:0]), .rp(rp),.rm(rm));
//srt srt(.clk(clk), .req(req), .sqrt(1'b0), .a(a), .b(b), .rp(rp),.rm(rm));
// Divider + unpacker
srt srt(clk, req, a, b, rp, rm);
// Final adder converts quotient digits to 2's complement & normalizes
finaladd finaladd(rp, rm, r);

View File

@ -40,33 +40,66 @@ module testbench;
logic clk;
logic req;
logic done;
logic [51:0] a;
logic [51:0] b;
logic [51:0] r;
logic [63:0] a;
logic [63:0] b;
logic [63:0] result;
logic [51:0] r;
logic [54:0] rp, rm; // positive quotient digits
logic [10:0] e; // output exponent
// input logic for Unpacker
// input logic [63:0] X, Y, Z, - numbers
// input logic FmtE, ---- format, 1 is for double precision, 0 is single
// input logic [2:0] FOpCtrlE, ---- controling operations for FPU, 1 is sqrt, 0 is divide
// all variables are commented in fpu.sv
// output logic from Unpacker
logic XSgnE, YSgnE, ZSgnE;
logic [10:0] XExpE, YExpE, ZExpE; // exponent
logic [52:0] XManE, YManE, ZManE;
logic XNormE;
logic XNaNE, YNaNE, ZNaNE;
logic XSNaNE, YSNaNE, ZSNaNE;
logic XDenormE, YDenormE, ZDenormE; // denormals
logic XZeroE, YZeroE, ZZeroE;
logic [10:0] BiasE; // currrently hardcoded, will probs be removed
logic XInfE, YInfE, ZInfE;
logic XExpMaxE; // says exponent is all ones, can ignore
// Test parameters
parameter MEM_SIZE = 40000;
parameter MEM_WIDTH = 52+52+52;
parameter MEM_SIZE = 60000;
parameter MEM_WIDTH = 64+64+64;
`define memr 51:0
`define memb 103:52
`define mema 155:104
`define memr 63:0
`define memb 127:64
`define mema 191:128
// Test logicisters
logic [MEM_WIDTH-1:0] Tests [0:MEM_SIZE]; // Space for input file
logic [MEM_WIDTH-1:0] Vec; // Verilog doesn't allow direct access to a
// bit field of an array
logic [51:0] correctr, nextr, diffn, diffp;
logic [63:0] correctr, nextr, diffn, diffp;
integer testnum, errors;
// Unpacker
// Note: BiasE will probably get taken out eventually
unpacking unpack(.X({1'b1,a[62:0]}), .Y({1'b1,b[62:0]}), .Z(64'b0), .FmtE(1'b1), .FOpCtrlE(3'b0),
.XSgnE(XSgnE), .YSgnE(YSgnE), .ZSgnE(ZSgnE), .XExpE(XExpE), .YExpE(YExpE), .ZExpE(ZExpE),
.XManE(XManE), .YManE(YManE), .ZManE(ZManE), .XNormE(XNormE), .XNaNE(XNaNE), .YNaNE(YNaNE), .ZNaNE(ZNaNE),
.XSNaNE(XSNaNE), .YSNaNE(YSNaNE), .ZSNaNE(ZSNaNE), .XDenormE(XDenormE), .YDenormE(YDenormE), .ZDenormE(ZDenormE),
.XZeroE(XZeroE), .YZeroE(YZeroE), .ZZeroE(ZZeroE), .BiasE(BiasE),
.XInfE(XInfE), .YInfE(YInfE), .ZInfE(ZInfE), .XExpMaxE(XExpMaxE));
// Divider
srt #(52) srt(.clk, .Start(req),
.Stall(1'b0), .Flush(1'b0),
.SrcXFrac(a), .SrcYFrac(b),
.SrcXExpE(XExpE), .SrcYExpE(YExpE),
.SrcXFrac(XManE[51:0]), .SrcYFrac(YManE[51:0]),
.SrcA('0), .SrcB('0), .Fmt(2'b00),
.W64(1'b0), .Signed(1'b0), .Int(1'b0), .Sqrt(1'b0),
.Quot(r), .Rem(), .Flags());
.Quot(r), .Rem(), .Exp(e), .Flags());
assign result = {1'b0, e, r};
// Counter
counter counter(clk, req, done);
@ -100,16 +133,18 @@ module testbench;
if (done)
begin
req <= #5 1;
diffp = correctr - r;
diffn = r - correctr;
diffp = correctr - result;
diffn = result - correctr;
if (($signed(diffn) > 1) | ($signed(diffp) > 1)) // check if accurate to 1 ulp
begin
errors = errors+1;
$display("result was %h, should be %h %h %h\n", r, correctr, diffn, diffp);
$display("a = %h b = %h result = %h",a,b,correctr);
$display("result was %h, should be %h %h %h\n", result, correctr, diffn, diffp);
$display("at fail");
$display("failed\n");
$stop;
end
if (a === 52'hxxxxxxxxxxxxx)
if (a === 64'hxxxxxxxxxxxxxxxx)
begin
$display("%d Tests completed successfully", testnum);
$stop;
@ -119,12 +154,14 @@ module testbench;
begin
req <= #5 0;
correctr = nextr;
$display("pre increment");
testnum = testnum+1;
Vec = Tests[testnum];
$display("a = %h b = %h",a,b);
a = Vec[`mema];
a = Vec[`mema];
b = Vec[`memb];
Vec = Tests[testnum];
$display("a = %h b = %h result = %h",a,b,nextr);
nextr = Vec[`memr];
$display("after increment");
end
end

File diff suppressed because it is too large Load Diff