testbench now compiles with basic infrastructure to do int64rem test on drsu

This commit is contained in:
Kevin Kim 2023-07-08 20:42:16 -07:00
parent 23bb96f857
commit 9343c2296e
4 changed files with 572 additions and 237 deletions

View File

@ -56,7 +56,8 @@ module testbenchfp;
logic WriteIntVal; // value of the current WriteInt
logic [P.FLEN-1:0] X, Y, Z; // inputs read from TestFloat
logic [P.FLEN-1:0] XPostBox; // inputs read from TestFloat
logic [P.XLEN-1:0] SrcA; // integer input
logic [P.XLEN-1:0] SrcA, SrcB; // integer input
logic W64; // is W64 instruction
logic [P.FLEN-1:0] Ans; // correct answer from TestFloat
logic [P.FLEN-1:0] Res; // result from other units
logic [4:0] AnsFlg; // correct flags read from testfloat
@ -84,6 +85,7 @@ module testbenchfp;
logic [P.DIVb:0] Quot;
logic CvtResSubnormUfE;
logic DivStart;
logic IDivStart;
logic FDivBusyE;
logic OldFDivBusyE;
logic reset = 1'b0;
@ -118,11 +120,13 @@ module testbenchfp;
logic [P.NE+1:0] QeM;
logic [P.DIVb:0] QmM;
logic [P.XLEN-1:0] FIntDivResultM;
logic IntDivE;
logic ResMatch; // Check if result match
logic FlagMatch; // Check if IEEE flags match
logic CheckNow; // Final check
logic FMAop; // Is this a FMA operation?
flop #(3) funct3reg(.clk, .d(Funct3E), .q(Funct3M));
///////////////////////////////////////////////////////////////////////////////////////////////
// ||||||||| |||||||| ||||||| ||||||||| ||||||| |||||||| |||
@ -660,12 +664,12 @@ module testbenchfp;
end
end
if (TEST === "divremsqrttest") begin // if unified div sqrt is being tested
Tests = {Tests, f128sqrt};
Tests = {Tests, f64sqrt};
OpCtrl = {OpCtrl, `SQRT_OPCTRL};
WriteInt = {WriteInt, 1'b0};
for(int i = 0; i<5; i++) begin
Unit = {Unit, `DIVUNIT};
Fmt = {Fmt, 2'b11};
Fmt = {Fmt, 2'b01};
end
end
if (TEST === "customdiv") begin // if unified div sqrt is being tested
@ -682,7 +686,15 @@ module testbenchfp;
Unit = {Unit, `DIVUNIT};
Fmt = {Fmt, 2'b10};
end
if (TEST === "intdiv") begin // if unified div sqrt is being tested
Tests = {Tests, intdiv};
OpCtrl = {OpCtrl, `INTREM_OPCTRL};
WriteInt = {WriteInt, 1'b0};
Unit = {Unit, `INTDIVUNIT};
Fmt = {Fmt, 2'b10};
end
end
// check if nothing is being tested
if (Tests.size() == 0) begin
$display("TEST %s not supported in this configuration", TEST);
@ -732,10 +744,10 @@ module testbenchfp;
// extract the inputs (X, Y, Z, SrcA) and the output (Ans, AnsFlg) from the current test vector
readvectors #(P) readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]),
.VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA,
.VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA, .SrcB,
.Xs, .Ys, .Zs, .Unit(UnitVal),
.Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal),
.Xm, .Ym, .Zm, .DivStart,
.Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal), .Funct3E,
.Xm, .Ym, .Zm, .DivStart, .IDivStart, .IntDivE,
.XNaN, .YNaN, .ZNaN,
.XSNaN, .YSNaN, .ZSNaN,
.XSubnorm, .ZSubnorm,
@ -799,7 +811,7 @@ module testbenchfp;
.Funct3E(Funct3E), .IntDivE(1'b0), .FIntDivResultM(FIntDivResultM),
.FDivDoneE(FDivDoneE), .IFDivStartE(IFDivStartE));
end
if (TEST === "divremsqrt" | TEST === "divremsqrttest" | TEST === "customdiv") begin: divremsqrt
if (TEST === "divremsqrt" | TEST === "divremsqrttest" | TEST === "customdiv" | TEST === "intdiv") begin: divremsqrt
drsu #(P) drsu(.clk, .reset, .XsE(Xs), .YsE(Ys), .FmtE(ModFmt), .XmE(Xm), .YmE(Ym),
.XeE(Xe), .YeE(Ye), .SqrtE(OpCtrlVal[0]), .SqrtM(OpCtrlVal[0]),
.XInfE(XInf), .YInfE(YInf), .XZeroE(XZero), .YZeroE(YZero),
@ -808,10 +820,10 @@ module testbenchfp;
.OpCtrl(OpCtrlVal),
.XSNaNE(XSNaN), .YSNaNE(YSNaN),
.Frm(FrmVal),
.FDivStartE(DivStart), .IDivStartE(1'b0), .W64E(1'b0),
.FDivStartE(DivStart), .IDivStartE(IDivStart), .W64E(1'b0),
.StallM(1'b0), .FDivBusyE,
.FlushE(1'b0), .ForwardedSrcAE('0), .ForwardedSrcBE('0), .Funct3M(Funct3M),
.Funct3E(Funct3E), .IntDivE(1'b0),
.FlushE(1'b0), .ForwardedSrcAE(SrcA), .ForwardedSrcBE(SrcB), .Funct3M(Funct3M),
.Funct3E(Funct3E), .IntDivE(IntDivE),
.FDivDoneE(FDivDoneE), .IFDivStartE(IFDivStartE), .FResM(FpRes), .FIntDivResultM(IntRes), .FlgM(Flg));
end
else begin: postprocess
@ -912,6 +924,7 @@ module testbenchfp;
`CMPUNIT: Res = CmpRes;
`CVTINTUNIT: if (WriteIntVal) Res = IntRes; else Res = FpRes;
`CVTFPUNIT: Res = FpRes;
`INTDIVUNIT: Res = IntRes;
endcase
// select the flag to check
@ -921,6 +934,7 @@ module testbenchfp;
`CMPUNIT: ResFlg = CmpFlg;
`CVTINTUNIT: ResFlg = Flg;
`CVTFPUNIT: ResFlg = Flg;
`INTDIVUNIT: ResFlg = Flg;
endcase
end
@ -1030,7 +1044,7 @@ module testbenchfp;
// wait till the division result is done or one extra cylcle for early termination (to simulate the EM pipline stage)
assign ResMatch = ((Res === Ans) | NaNGood | (NaNGood === 1'bx));
assign FlagMatch = ((ResFlg === AnsFlg) | (AnsFlg === 5'bx));
assign divsqrtop = (OpCtrlVal == `SQRT_OPCTRL) | (OpCtrlVal == `DIV_OPCTRL);
assign divsqrtop = (OpCtrlVal == `SQRT_OPCTRL) | (OpCtrlVal == `DIV_OPCTRL) | (OpCtrlVal == `INTREM_OPCTRL);
assign FMAop = (OpCtrlVal == `FMAUNIT);
assign DivDone = OldFDivBusyE & ~FDivBusyE;
@ -1044,7 +1058,7 @@ module testbenchfp;
errors += 1;
$display("\nError in %s", Tests[TestNum]);
$display("TestNum %d OpCtrl %d", TestNum, OpCtrl[TestNum]);
$display("inputs: %h %h %h\nSrcA: %h\n Res: %h %h\n Expected: %h %h", X, Y, Z, SrcA, Res, ResFlg, Ans, AnsFlg);
$display("inputs: %h %h %h\nSrcA: %h\n SrcB: %h\n Res: %h %h\n Expected: %h %h", X, Y, Z, SrcA, SrcB, Res, ResFlg, Ans, AnsFlg);
end
// TestFloat sets the result to all 1's when there is an invalid result, however in
@ -1100,6 +1114,7 @@ module readvectors (
input logic [2:0] OpCtrl,
output logic [P.FLEN-1:0] Ans,
output logic [P.XLEN-1:0] SrcA,
output logic [P.XLEN-1:0] SrcB,
output logic [4:0] AnsFlg,
output logic Xs, Ys, Zs, // sign bits of XYZ
output logic [P.NE-1:0] Xe, Ye, Ze, // exponents of XYZ (converted to largest supported precision)
@ -1111,6 +1126,9 @@ module readvectors (
output logic XInf, YInf, ZInf, // is XYZ infinity
output logic XExpMax,
output logic DivStart,
output logic IDivStart,
output logic IntDivE,
output logic [2:0] Funct3E,
output logic [P.FLEN-1:0] X, Y, Z, XPostBox
);
@ -1265,6 +1283,21 @@ module readvectors (
DivStart = 1'b0;
end
endcase
`INTDIVUNIT: begin
#20;
X = {P.FLEN{1'bx}};
SrcA = TestVector[2*(P.Q_LEN)+P.D_LEN-1:2*(P.Q_LEN)];
SrcB = TestVector[(P.Q_LEN)+P.D_LEN-1:P.Q_LEN];
Ans = TestVector[P.D_LEN-1:0];
if (~clk) #5;
IDivStart = 1'b1;
IntDivE = 1'b1;
Funct3E = 3'b110;
#10 // one clk cycle
IDivStart = 1'b0;
IntDivE = 1'b0;
end
`CMPUNIT:
case (Fmt)
2'b11: begin // quad

View File

@ -42,6 +42,10 @@
`define FROM_I_OPCTRL 3'b101
`define FROM_UL_OPCTRL 3'b110
`define FROM_L_OPCTRL 3'b111
`define INTREMU_OPCTRL 3'b000
`define INTREM_OPCTRL 3'b110
`define INTDIV_OPCTRL 3'b010
`define INTDIVU_OPCTRL 3'b011
`define RNE 3'b000
`define RZ 3'b001
`define RU 3'b011
@ -53,6 +57,7 @@
`define CVTFPUNIT 4
`define CMPUNIT 3
`define DIVREMSQRTUNIT 5
`define INTDIVUNIT 6
string f16rv32cvtint[] = '{
"ui32_to_f16_rne.tv",
@ -589,5 +594,8 @@ string customdivcorrect[] = '{
"f16_custom.tv"
};
string intdiv[] = '{
"f16_kevin.tv"
};

View File

@ -272,22 +272,22 @@ def create_vectors(my_config):
src_file2.close()
config_list = [
Config(32, "M", "div", "div-", 0),
Config(32, "M", "div", "div-", 4),
Config(32, "F", "fdiv", "fdiv", 1),
Config(32, "F", "fsqrt", "fsqrt", 2),
Config(32, "M", "rem", "rem-", 3),
Config(32, "M", "divu", "divu-", 4),
Config(32, "M", "remu", "remu-", 5),
Config(64, "M", "div", "div-", 0),
Config(32, "M", "rem", "rem-", 6),
Config(32, "M", "divu", "divu-", 5),
Config(32, "M", "remu", "remu-", 7),
Config(64, "M", "div", "div-", 4),
Config(64, "F", "fdiv", "fdiv", 1),
Config(64, "F", "fsqrt", "fsqrt", 2),
Config(64, "M", "rem", "rem-", 3),
Config(64, "M", "divu", "divu-", 4),
Config(64, "M", "remu", "remu-", 5),
Config(64, "M", "divw", "divw-", 6),
Config(64, "M", "divuw", "divuw-", 7),
Config(64, "M", "remw", "remw-", 8),
Config(64, "M", "remuw", "remuw-", 9)
Config(64, "M", "rem", "rem-", 6),
Config(64, "M", "divu", "divu-", 5),
Config(64, "M", "remu", "remu-", 7),
Config(64, "M", "divw", "divw-", 4),
Config(64, "M", "divuw", "divuw-", 5),
Config(64, "M", "remw", "remw-", 6),
Config(64, "M", "remuw", "remuw-", 7)
]
for c in config_list:

View File

@ -0,0 +1,294 @@
#! /usr/bin/python3
# author: Alessandro Maiuolo, Kevin Kim
# contact: amaiuolo@g.hmc.edu, kekim@hmc.edu
# date created: 3-29-2023
# extract all arch test vectors
import os
wally = os.popen('echo $WALLY').read().strip()
def ext_bits(my_string):
target_len = 32 # we want 128 bits, div by 4 bc hex notation
zeroes_to_add = target_len - len(my_string)
return zeroes_to_add*"0" + my_string
def twos_comp(b, x):
if b == 32:
return hex(0x100000000 - int(x,16))[2:]
elif b == 64:
return hex(0x10000000000000000 - int(x,16))[2:]
else:
return "UNEXPECTED_BITSIZE"
def unpack_rf(packed):
bin_u = bin(int(packed, 16))[2:].zfill(8) # translate to binary
flags = hex(int(bin_u[3:],2))[2:].zfill(2)
rounding_mode = hex(int(bin_u[:3],2))[2:]
return flags, rounding_mode
# rounding mode dictionary
round_dict = {
"rne":"0",
"rnm":"4",
"ru":"3",
"rz":"1",
"rd":"2",
"dyn":"7"
}
# fcsr dictionary
fcsr_dict = {
"0":"rne",
"128":"rnm",
"96":"ru",
"32":"rz",
"64":"rd",
"224":"dyn"
}
print("creating arch test vectors")
class Config:
def __init__(self, bits, letter, op, filt, op_code):
self.bits = bits
self.letter = letter
self.op = op
self.filt = filt
self.op_code = op_code
def create_vectors(my_config):
suite_folder_num = my_config.bits
if my_config.bits == 64 and my_config.letter == "F": suite_folder_num = 32
source_dir1 = "{}/addins/riscv-arch-test/riscv-test-suite/rv{}i_m/{}/src/".format(wally, suite_folder_num, my_config.letter)
source_dir2 = "{}/tests/riscof/work/riscv-arch-test/rv{}i_m/{}/src/".format(wally, my_config.bits, my_config.letter)
dest_dir = "{}/tests/fp/combined_IF_vectors/IF_vectors/".format(wally)
all_vectors1 = os.listdir(source_dir1)
filt_vectors1 = [v for v in all_vectors1 if my_config.filt in v]
# print(filt_vectors1)
filt_vectors2 = [v + "/ref/Reference-sail_c_simulator.signature" for v in all_vectors1 if my_config.filt in v]
# iterate through all vectors
for i in range(len(filt_vectors1)):
vector1 = filt_vectors1[i]
vector2 = filt_vectors2[i]
operation = my_config.op_code
rounding_mode = "X"
flags = "XX"
# use name to create our new tv
dest_file = open("{}cvw_{}_{}.tv".format(dest_dir, my_config.bits, vector1[:-2]), 'w')
# open vectors
src_file1 = open(source_dir1 + vector1,'r')
src_file2 = open(source_dir2 + vector2,'r')
# for each test in the vector
reading = True
src_file2.readline() #skip first bc junk
# print(my_config.bits, my_config.letter)
if my_config.letter == "F" and my_config.bits == 64:
reading = True
# print("trigger 64F")
#skip first 2 lines bc junk
src_file2.readline()
while reading:
# get answer and flags from Ref...signature
# answers are before deadbeef (first line of 4)
# flags are after deadbeef (third line of 4)
answer = src_file2.readline().strip()
deadbeef = src_file2.readline().strip()
# print(answer)
if not (answer == "e7d4b281" and deadbeef == "6f5ca309"): # if there is still stuff to read
# get flags
packed = src_file2.readline().strip()[6:]
flags, rounding_mode = unpack_rf(packed)
# skip 00000000 buffer
src_file2.readline()
# parse through .S file
detected = False
done = False
op1val = "0"
op2val = "0"
while not (detected or done):
# print("det1")
line = src_file1.readline()
# print(line)
if "op1val" in line:
# print("det2")
# parse line
op1val = line.split("op1val")[1].split("x")[1].split(";")[0]
if my_config.op != "fsqrt": # sqrt doesn't have two input vals
op2val = line.split("op2val")[1].split("x")[1].strip()
if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there
else:
op2val = 32*"X"
# go to next test in vector
detected = True
elif "RVTEST_CODE_END" in line:
done = True
# put it all together
if not done:
translation = "{}_{}_{}".format(ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()))
dest_file.write(translation + "\n")
else:
# print("read false")
reading = False
elif my_config.letter == "M" and my_config.bits == 64:
reading = True
#skip first 2 lines bc junk
src_file2.readline()
while reading:
# print("trigger 64M")
# get answer from Ref...signature
# answers span two lines and are reversed
answer2 = src_file2.readline().strip()
answer1 = src_file2.readline().strip()
answer = answer1 + answer2
#print(answer1,answer2)
if not (answer2 == "e7d4b281" and answer1 == "6f5ca309"): # if there is still stuff to read
# parse through .S file
detected = False
done = False
op1val = "0"
op2val = "0"
while not (detected or done):
# print("det1")
line = src_file1.readline()
# print(line)
if "op1val" in line:
# print("det2")
# parse line
op1val = line.split("op1val")[1].split("x")[1].split(";")[0]
if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling
op1val = twos_comp(my_config.bits, op1val)
if my_config.op != "fsqrt": # sqrt doesn't have two input vals, unnec here but keeping for later
op2val = line.split("op2val")[1].split("x")[1].strip()
if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there
if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling
op2val = twos_comp(my_config.bits, op2val)
# go to next test in vector
detected = True
elif "RVTEST_CODE_END" in line:
done = True
# ints don't have flags
flags = "XX"
# put it all together
if not done:
translation = "{}_{}_{}".format(ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()))
dest_file.write(translation + "\n")
else:
# print("read false")
reading = False
elif my_config.letter == "M" and my_config.bits == 32:
reading = True
while reading:
# print("trigger 64M")
# get answer from Ref...signature
# answers span two lines and are reversed
answer = src_file2.readline().strip()
print(f"Answer: {answer}")
#print(answer1,answer2)
if not (answer == "6f5ca309"): # if there is still stuff to read
# parse through .S file
detected = False
done = False
op1val = "0"
op2val = "0"
while not (detected or done):
# print("det1")
line = src_file1.readline()
# print(line)
if "op1val" in line:
# print("det2")
# parse line
op1val = line.split("op1val")[1].split("x")[1].split(";")[0]
if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling
op1val = twos_comp(my_config.bits, op1val)
if my_config.op != "fsqrt": # sqrt doesn't have two input vals, unnec here but keeping for later
op2val = line.split("op2val")[1].split("x")[1].strip()
if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there
if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling
op2val = twos_comp(my_config.bits, op2val)
# go to next test in vector
detected = True
elif "RVTEST_CODE_END" in line:
done = True
# ints don't have flags
flags = "XX"
# put it all together
if not done:
translation = "{}_{}_{}".format(ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()))
dest_file.write(translation + "\n")
else:
# print("read false")
reading = False
else:
while reading:
# get answer and flags from Ref...signature
answer = src_file2.readline()
print(answer)
packed = src_file2.readline()[6:]
print("Packed: ", packed)
if len(packed.strip())>0: # if there is still stuff to read
# print("packed")
# parse through .S file
detected = False
done = False
op1val = "0"
op2val = "0"
while not (detected or done):
# print("det1")
line = src_file1.readline()
# print(line)
if "op1val" in line:
# print("det2")
# parse line
op1val = line.split("op1val")[1].split("x")[1].split(";")[0]
if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling
op1val = twos_comp(my_config.bits, op1val)
if my_config.op != "fsqrt": # sqrt doesn't have two input vals
op2val = line.split("op2val")[1].split("x")[1].strip()
if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there
if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling
op2val = twos_comp(my_config.bits, op2val)
# go to next test in vector
detected = True
elif "RVTEST_CODE_END" in line:
done = True
# rounding mode for float
if not done and (my_config.op == "fsqrt" or my_config.op == "fdiv"):
flags, rounding_mode = unpack_rf(packed)
# put it all together
if not done:
translation = "{}_{}_{}".format(ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()))
dest_file.write(translation + "\n")
else:
# print("read false")
reading = False
# print("out")
dest_file.close()
src_file1.close()
src_file2.close()
config_list = [
Config(32, "M", "div", "div-", 4),
Config(32, "F", "fdiv", "fdiv", 1),
Config(32, "F", "fsqrt", "fsqrt", 2),
Config(32, "M", "rem", "rem-", 6),
Config(32, "M", "divu", "divu-", 5),
Config(32, "M", "remu", "remu-", 7),
Config(64, "M", "div", "div-", 4),
Config(64, "F", "fdiv", "fdiv", 1),
Config(64, "F", "fsqrt", "fsqrt", 2),
Config(64, "M", "rem", "rem-", 6),
Config(64, "M", "divu", "divu-", 5),
Config(64, "M", "remu", "remu-", 7),
Config(64, "M", "divw", "divw-", 4),
Config(64, "M", "divuw", "divuw-", 5),
Config(64, "M", "remw", "remw-", 6),
Config(64, "M", "remuw", "remuw-", 7)
]
for c in config_list:
create_vectors(c)