%Sam Bellestri, Joshua Mack, Nia Simmonds
%IREECE 2015
%Creates a VHDL test bench file for use with the expanded floating point
%CORDIC architecture
%Generates test cases in a range [lower,upper] 
%Lines specifies the number of test cases
%Also specify number of iterations and customizable expWidth/fracWidth

%IEEE Standard Exp Widths and Frac Widths
%Half Preicision - 16 total bits, 5 exponent, 10 fractional
%Single Precision - 32 total bits, 8 exponent, 23 fractional
%Double Precision - 64 total bits, 11 exponent, 52 fractional

%General formula 
%Exponent width = round(4*log2(totalBits))-13
%Fractional width = total bits - exponent bits - 1 (sign)

function [] = FloP_FullCORDIC_Generic_tb(mode,lower,upper,lines,iterations,expWidth,fracWidth)
  if mode == 'r'
    numBits = expWidth+fracWidth+1;
    iterWidth = floor(log2(fracWidth))+1;
    q = quantizer('float',[numBits expWidth]);

    negIter = -5:1:0; posIter = 1:1:iterations;
    scalingFactor = prod(sqrt(1-(1-2.^(negIter-2)).^2)) * prod(sqrt(1-(2.^(-posIter)).^2)) *  0.998044956480943;

    file = fopen('FloP_FullCORDIC_Generic_tb.vhd', 'wt');
    fprintf(file,'library IEEE;\n');
    fprintf(file,'use IEEE.STD_LOGIC_1164.ALL;\n');
    fprintf(file,'use std.textio.all;\n');
    fprintf(file,'use ieee.std_logic_textio.all;\n');
    fprintf(file,'library std;\n');
    fprintf(file,'use std.env.all;\n');
    fprintf(file,'use ieee.std_logic_1164.all;\n');
    fprintf(file,'use ieee.numeric_std.all;\n\n');
    fprintf(file,'entity FloP_FullCORDIC_Generic_tb is\nend FloP_FullCORDIC_Generic_tb;\n\n');
    fprintf(file,['architecture Behavioral of FloP_FullCORDIC_Generic_tb is\n', ...
        '\tcomponent FloP_FullCORDIC_Generic is\n', ...
        '\tGeneric ( fileName1 : string := "%dBitExpandedLUT.txt"; fileName2 : string := "%dBitLUT.txt"; \n\t\texpWidth : integer := %d; fracWidth : integer := %d; iterWidth : integer := %d );\n',...
        '\tPort ( clk, start, mode : in STD_LOGIC;\n',...
            '\t\tN, M : in STD_LOGIC_VECTOR (iterWidth-1 downto 0);\n',...
            '\t\tx0,y0,z0 : in STD_LOGIC_VECTOR (expWidth+fracWidth downto 0);\n',...
            '\t\txOut,yOut,zOut : out STD_LOGIC_VECTOR (expWidth+fracWidth downto 0);\n',...
            '\t\tdone : out STD_LOGIC );\n'],numBits,numBits,expWidth,fracWidth,iterWidth);
    fprintf(file,['\tend component;\n\n', ...
    '\tconstant fileName1 : string := "%dBitExpandedLUT.txt";\n', ...
    '\tconstant fileName2 : string := "%dBitLUT.txt";\n', ...
    '\tconstant expWidth : integer := %d;\n', ...
    '\tconstant fracWidth : integer := %d;\n', ...
    '\tconstant iterWidth : integer := %d;\n', ...
        '\tsignal clk_tb, start_tb, mode_tb, done : std_logic;\n', ...
        '\tsignal x0, y0, z0, xn, yn, zn : std_logic_vector (expWidth+fracWidth downto 0);\n', ...
        '\tsignal N, M : std_logic_vector (iterWidth-1 downto 0);\n\n', ...
        '\tbegin\n\n',...
            '\tmyCORDIC : FloP_FullCORDIC_Generic Generic Map(fileName1 => fileName1, fileName2 => fileName2,\n', ...
                    '\t\texpWidth => expWidth, fracWidth => fracWidth, iterWidth => iterWidth)\n', ...
            '\t\tPort Map(clk_tb, start_tb, mode_tb, N, M, x0, y0, z0, xn, yn, zn, done);\n\n', ...
            '\tclock : process begin\n',...
                '\t\tclk_tb <= ''0''; wait for 1 ns;\n',...
                '\t\tclk_tb <= ''1''; wait for 1 ns;\n',...
           '\tend process;\n\n',...
            '\ttestProc : process\n',... 
             '\t\tFILE test_out_data1: TEXT open WRITE_MODE is "%diterations%dbits_cosh.txt";\n',...
             '\t\tFILE test_out_data2: TEXT open WRITE_MODE is "%diterations%dbits_sinh.txt";\n',...
             '\t\tvariable L1              : LINE;\n',...
             '\t\tvariable L2              : LINE;\n\n',...
         '\tbegin\n\n',...
    '--------------------------Rotation Mode Tests-----------------------------\n\n',...
        '\t\t-- Using N = "%d"\n',...
        '\t\tN <= "%s"; M <= "%s"; mode_tb <= ''0'';\n',...
        '\t\t-- The main pieces that need to be in place to get nonscaled, separated values of Cosh and Sinh.\n',...
        '\t\tx0 <= "%s";\n',...
        '\t\t-- y0 := 0\n',...
        '\t\ty0 <= "%s";\n\n\n'],numBits,numBits,expWidth,fracWidth,iterWidth,iterations,numBits,iterations,numBits,iterations,dec2bin(iterations,iterWidth),dec2bin(5, iterWidth), num2bin(q,1/scalingFactor),dec2bin(0,numBits));
    x = linspace(lower,upper,lines);
    i = 1;
    while i <= lines
        %Perform conversion and record in file
        fprintf(file,'\t\t--z0 := %f\n', x(i));
        fprintf(file,'\t\tz0 <= "%s";\n', num2bin(q,x(i)));
        fprintf(file,'\t\tstart_tb <= ''1''; wait for 2 ns; start_tb <= ''0''; wait for 250 ns;\n');
        fprintf(file,'\t\twrite(L1,xn);\n');
        fprintf(file,'\t\twriteline(test_out_data1,L1);\n');
        fprintf(file,'\t\twrite(L2,yn);\n');
        fprintf(file,'\t\twriteline(test_out_data2,L2);\n\n');
        i = i + 1;
    end
    fprintf(file,['\tstop(0);\n',...
        '\tend process;\n',...
        'end Behavioral;\n']);
    
  fclose(file);
  end 
  if mode == 'v'
    numBits = expWidth+fracWidth+1;
    iterWidth = floor(log2(fracWidth))+1;
    q = quantizer('float',[numBits expWidth]);

    file = fopen('FloP_FullCORDIC_Generic_tb.vhd', 'wt');
    fprintf(file,'library IEEE;\n');
    fprintf(file,'use IEEE.STD_LOGIC_1164.ALL;\n');
    fprintf(file,'use std.textio.all;\n');
    fprintf(file,'use ieee.std_logic_textio.all;\n');
    fprintf(file,'library std;\n');
    fprintf(file,'use std.env.all;\n');
    fprintf(file,'use ieee.std_logic_1164.all;\n');
    fprintf(file,'use ieee.numeric_std.all;\n\n');
    fprintf(file,'entity FloP_FullCORDIC_Generic_tb is\nend FloP_FullCORDIC_Generic_tb;\n\n');
    fprintf(file,['architecture Behavioral of FloP_FullCORDIC_Generic_tb is\n', ...
        '\tcomponent FloP_FullCORDIC_Generic is\n', ...
        '\tGeneric ( fileName1 : string := "%dBitExpandedLUT.txt"; fileName2 : string := "%dBitLUT.txt"; \n\t\texpWidth : integer := %d; fracWidth : integer := %d; iterWidth : integer := %d );\n',...
        '\tPort ( clk, start, mode : in STD_LOGIC;\n',...
            '\t\tN, M : in STD_LOGIC_VECTOR (iterWidth-1 downto 0);\n',...
            '\t\tx0,y0,z0 : in STD_LOGIC_VECTOR (expWidth+fracWidth downto 0);\n',...
            '\t\txOut,yOut,zOut : out STD_LOGIC_VECTOR (expWidth+fracWidth downto 0);\n',...
            '\t\tdone : out STD_LOGIC );\n'],numBits,numBits,expWidth,fracWidth,iterWidth);
    fprintf(file,['\tend component;\n\n', ...
    '\tconstant fileName1 : string := "%dBitExpandedLUT.txt";\n', ...
    '\tconstant fileName2 : string := "%dBitLUT.txt";\n', ...
    '\tconstant expWidth : integer := %d;\n', ...
    '\tconstant fracWidth : integer := %d;\n', ...
    '\tconstant iterWidth : integer := %d;\n', ...
        '\tsignal clk_tb, start_tb, mode_tb, done : std_logic;\n', ...
        '\tsignal x0, y0, z0, xn, yn, zn : std_logic_vector (expWidth+fracWidth downto 0);\n', ...
        '\tsignal N, M : std_logic_vector (iterWidth-1 downto 0);\n\n', ...
        '\tbegin\n\n',...
            '\tmyCORDIC : FloP_FullCORDIC_Generic Generic Map(fileName1 => fileName1, fileName2 => fileName2,\n', ...
                    '\t\texpWidth => expWidth, fracWidth => fracWidth, iterWidth => iterWidth)\n', ...
            '\t\tPort Map(clk_tb, start_tb, mode_tb, N, M, x0, y0, z0, xn, yn, zn, done);\n\n', ...
            '\tclock : process begin\n',...
                '\t\tclk_tb <= ''0''; wait for 1 ns;\n',...
                '\t\tclk_tb <= ''1''; wait for 1 ns;\n',...
           '\tend process;\n\n',...
            '\ttestProc : process\n',... 
             '\t\tFILE test_out_data1: TEXT open WRITE_MODE is "%diterations%dbits_atanh.txt";\n',...
             '\t\tvariable L1              : LINE;\n\n',...
         '\tbegin\n\n',...
    '--------------------------Vectoring Mode Tests-----------------------------\n\n',...
        '\t\t-- Using N = "%d"\n',...
        '\t\tN <= "%s"; M <= "%s"; mode_tb <= ''1'';\n',...
        '\t\t-- The main pieces that need to be in place to get standalone aTanh.\n',...
        '\t\tx0 <= "%s";\n',...
        '\t\t-- z0 := 0\n',...
        '\t\tz0 <= "%s";\n\n\n'],numBits,numBits,expWidth,fracWidth,iterWidth,iterations,numBits,iterations,dec2bin(iterations,iterWidth),dec2bin(5, iterWidth),num2bin(q,1),num2bin(q, 0));
    y = linspace(lower,upper,lines);
    i = 1;
    while i <= lines
        %Perform conversion and record in file
        fprintf(file,'\t\t--y0 := %f\n', y(i));
        fprintf(file,'\t\ty0 <= "%s";\n', num2bin(q,y(i)));
        fprintf(file,'\t\tstart_tb <= ''1''; wait for 4 ns; start_tb <= ''0''; wait for 250 ns;\n');
        fprintf(file,'\t\twrite(L1,zn);\n');
        fprintf(file,'\t\twriteline(test_out_data1,L1);\n\n');
        i = i + 1;
    end
    fprintf(file,['\tstop(0);\n',...
        '\tend process;\n',...
        'end Behavioral;\n']);
    
  fclose(file);
  end 