% Joshua Mack, Sam Bellestri, Nia Simmonds IREECE 2015
% Fixed_NaturalLogX_Generic_tb:
%   Takes in a given test domain (varies from lower to upper with "lines" many test cases) along with the corresponding integer and fractional widths of the fixed-point format and number of iterations
%   And then generates a VHDL testbench for simulating a specific configuration of NaturalLogX. The resulting file is saved to the current Matlab working directory
%   As "Fixed_NaturalLogX_Generic_tb.vhd".

function [] = Fixed_NaturalLogX_Generic_tb(lower,upper,lines,iterations,intWidth,fracWidth)

    % Declare some variables
    numBits = intWidth+fracWidth;
    iterWidth = floor(log2(iterations))+1;
    q = quantizer('fixed', [numBits fracWidth]);

    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;

    % Begin writing testbench. Easiest way to understand is to run the script and look at the output.
    file = fopen('Fixed_NaturalLogX_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 Fixed_NaturalLogX_Generic_tb is\nend Fixed_NaturalLogX_Generic_tb;\n\n');
    fprintf(file,['architecture Behavioral of Fixed_NaturalLogX_Generic_tb is\n', ...
        'component Fixed_NaturalLogX is\n', ...
        '\tGeneric ( filename1, filename2 : string; intWidth, fracWidth, iterWidth, M, N : integer );\n',...
        '\tPort ( input : in std_logic_vector(intWidth+fracWidth-1 downto 0); ',...
            '\t\tclk, start : in STD_LOGIC;\n',...
            '\t\toutput : out STD_LOGIC_VECTOR (intWidth+fracWidth-1 downto 0);\n',...
            '\t\tdone : out STD_LOGIC );\n']);
    fprintf(file,['end component;\n\n', ...
    'constant file1 : string := "%d_%dBitExpandedLUT_Fixed.txt";\n', ...
    'constant file2 : string := "%d_%dBitLUT_Fixed.txt";\n', ...
    'constant intWidth : integer := %d;\n',...
    'constant fracWidth : integer := %d;\n',...
    'constant dataWidth : integer := %d;\n', ...
    'constant iterWidth : integer := %d;\n', ...
    'constant M : integer := %d;\n', ...
    'constant N : integer := %d;\n\n', ...
        'signal clk_tb, start_tb, done_tb : std_logic;\n', ...
        'signal input_tb, output_tb : std_logic_vector (dataWidth-1 downto 0);\n\n', ...
        'begin\n',...
            '\tmyCORDIC : Fixed_NaturalLogX\n\t\tGeneric Map(fileName1 => file1, fileName2 => file2,\n', ...
                    '\t\t\tintWidth => intWidth, fracWidth => fracWidth, iterWidth => iterWidth, M => M, N => N)\n', ...
            '\t\tPort Map(input_tb, clk_tb, start_tb, output_tb, done_tb);\n\n', ...
            'clock : process begin\n',...
                '\tclk_tb <= ''0''; wait for 1 ns;\n',...
                '\tclk_tb <= ''1''; wait for 1 ns;\n',...
           'end process;\n\n',...
            'testProc : process\n',... 
             '\tFILE test_out_data1: TEXT open WRITE_MODE is "%diterations%dfracBits%dintBits_NaturalLogX_fixed.txt";\n',...
             '\tvariable L1 : LINE;\n\n',...
         'begin\n\n',...
    '--------------------------Begin Tests-----------------------------\n\n\n'],intWidth,fracWidth,intWidth,fracWidth,intWidth,fracWidth,numBits,iterWidth,5,iterations,iterations,fracWidth,intWidth);
    
    % Begin writing test cases to file
    x = linspace(lower,upper,lines);
    i = 1;
    while i <= lines
        %Perform conversion and record in file
        fprintf(file,'\t--input <= "%s";\n', num2str(x(i)));
        fprintf(file,'\tinput_tb <= "%s";\n', num2bin(q,x(i)));
        fprintf(file,'\tstart_tb <= ''1''; wait for 2 ns; start_tb <= ''0''; wait until done_tb = ''1''; wait for 20 ns;\n');
        fprintf(file,'\twrite(L1,output_tb);\n');
        fprintf(file,'\twriteline(test_out_data1,L1);\n\n');
        i = i + 1;
    end
    fprintf(file,['stop(0);\n',...
        'end process;\n',...
        'end Behavioral;\n']);

    fclose(file); 
return;