% Joshua Mack, Sam Bellestri, Nia Simmonds IREECE 2015
% UltimateTestScript_atanh:
%   Acts as a completely autonomous test script for testing floating-point aTanhX.
%   After establishing the test domain for each case and the arrays specifying the cases that need testing, 
%   The script simply iterates through each combination, generates LUTs, generates a testbench, executes the Vivado simulation,
%   analyzes the results, and proceeds to the next test case. Requires some directories to be manually specified by hand, though, 
%   and it can be a bit tricky working around (1) Matlab's hatred of double quotation marks (") and (2) unix's hatred of spaces. 
%   If you're careful, though, and only replace the path names between the single and double quotes, it should transfer to other machines fine.

function [] = UltimateTestScript_atanh()

    % Define the interval to test over
    yMin = -0.999990;
    yMax = 0.999990;
    yPts = 1000;
    
    % Define the desired configurations to be tested. Note that fracArr corresponds exactly with expArr.
    % So, for example, the cases being tested here are (9 + 6) + 1 = 16 bits, (13 + 6) + 1 = 20 bits, (16 + 7) + 1 = 24 bits, ..., (52 + 11) + 1 = 64 bits,
    % and they all vary from 8, 12, 16, ..., 52 iterations.
    fracArr = [9 13 16 20 23 26 30 34 37 41 44 48 52];
    expArr = [6 6 7 7 8 9 9 9 10 10 11 11 11];
    iterArr = [8 12 16 20 24 28 32 36 40 44 48 52];
    
    % Filename results will be saved to after testing
    aTanhFilename = ['aTanh_PSNR_', num2str(length(fracArr)*length(iterArr)), '_Cases_', num2str(yMin, 2), '_to_', num2str(yMax, 2), '_', datestr(datetime('today')), '.txt'];
    
    %Name of the VHDL testbench file
    tbName = 'FloP_FullCORDIC_Generic_tb.vhd';
    %Path to testbench directory -- generic form is "*PathToVivadoProject*/VHDLProj.srcs/sim_1/new"
    VHDLPath = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/VHDL/FlexibleFloPCORDIC/FlexibleFloPCORDIC.srcs/sim_1/new/"';
    %Path to Matlab directory -- the current working directory for Matlab. This line can probably be replaced by some usage of "pwd"
    MatlabPath = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/Matlab Files/';
    
    % Clear the results directory of any previously generated files
    % It enabled us to be sure that the results we were getting were, in fact, from this test run. Otherwise, for example, a given configuration's simulation may fail
    % (say, 40 bits, 24 iterations), in which case the script hands control from the Vivado simulator back to Matlab, and the only way that the script knows the simulation failed
    % is if it cannot find the resulting simulation file (or if it doesn't have yPts results in it). 
    unix('rm ./FloP_aTanhX_VivadoResults/*');

    myATanhPSNR = zeros(length(fracArr), length(iterArr));
    
    h1 = figure();
    for i = 1:1:length(fracArr)
        for j = 1:1:length(iterArr)
            if iterArr(j) <= fracArr(i)
                % Assign the parameters for this execution
                expWidth = expArr(i); fracWidth = fracArr(i); numIterations = iterArr(j);
                % Print diagnostic information for reference to the poor soul watching this long script execute
                fprintf('\n----------------------\n');
                fprintf('%d bits, %d iterations', expWidth+fracWidth+1, numIterations);
                fprintf('\n----------------------\n'); 

                % Path to simulation results
                % First just establish the basic path -- generic form: "*PathToVivadoProject*/VHDLProj.sim/sim_1/behav/"
                aTanhResultsPath = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/VHDL/FlexibleFloPCORDIC/FlexibleFloPCORDIC.sim/sim_1/behav/';
                % Then concatenate the filename of the simulation results
                aTanhResultsPath = [aTanhResultsPath, num2str(numIterations), 'iterations', num2str(fracWidth+expWidth+1), 'bits_atanh.txt"'];
                
                % Generate LUTs
                [fileName1, fileName2] = generateLUTs(numIterations,expWidth,fracWidth);
                % Generic form: "*PathToVivadoProject*/VHDLProj.srcs/sources_1/new/"
                projectPathStr = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/VHDL/FlexibleFloPCORDIC/FlexibleFloPCORDIC.srcs/sources_1/new/"';
                unix(['mv ', fileName1, ' ', fileName2, ' ', projectPathStr]);
                
                % Generate testbench
                FloP_FullCORDIC_Generic_tb('v', yMin, yMax, yPts, numIterations, expWidth, fracWidth);
                % Copy it to the vivado project
                unix(['cp ./', tbName, ' ', VHDLPath]);

                % Start vivado and call the script to automate the simulation process
                % Requires the companion tcl script to be inside the "TCL_Files" directory located inside Matlab's current working directory.
                unix('C:/Xilinx/Vivado/2015.1/bin/vivado -mode tcl -source "./TCL_Files/coshSinhATanhSim.tcl"');

                % Copy the cosh and sinh results back to matlab directory into their PSNR folders
                unix(['cp ', aTanhResultsPath, ' ', MatlabPath, 'FloP_aTanhX_VivadoResults/"']);
                
                % Call the matlab PSNR script
                myATanhPSNR(i, j) = convertPlotAndPSNR_aTanhX(yMin, yMax, yPts, expWidth, fracWidth, numIterations);

                % Whenever an error occurs in the simulation, as reported by the convertPlotAndPSNR_aTanhX script, repeat the simulation until it works.
                % Failure can occur either when (1) the PSNR script can't find the results or (2) the results script didn't have yPts data points to analyze
                while myATanhPSNR(i, j) == -123456
                    unix('C:/Xilinx/Vivado/2015.1/bin/vivado -mode tcl -source "./TCL_Files/coshSinhATanhSim.tcl"');
                    unix(['cp ', aTanhResultsPath, ' ', MatlabPath, 'FloP_aTanhX_VivadoResults/"']);
                    myATanhPSNR(i, j) = convertPlotAndPSNR_aTanhX(yMin, yMax, yPts, expWidth, fracWidth, numIterations);
                end
            else
                % Keep each sample equal in length regardless of cases run
                myATanhPSNR(i, j:1:length(iterArr)) = myATanhPSNR(i, j-1);
            end
        end
        % Plot the results
        figure(h1);
        myATanhPlots(i) = plot(iterArr, myATanhPSNR(i, :), 'd-'); hold all;
    end
    % Add some legends and a title to make it look nice
    for i = 1:1:length(fracArr)
       legendStrs{i} = [num2str(fracArr(i) + expArr(i) + 1), ' bits'];
    end
    
    legend(myATanhPlots, legendStrs);
    title(['$\tanh^{-1}$[x] PSNR vs Number of Iterations, ', ...
            num2str(yMin), ' $\leq$ y $\leq$ ', num2str(yMax)], 'Interpreter', 'laTex');
    set(gca, 'FontWeight', 'bold');
    set(gca, 'FontSize', 11);
    set(get(gca,'Title'), 'FontSize', 14);

    %And write the results to a file because why not?
    aTanhFile = fopen(['./PSNR_Output/', aTanhFilename], 'w');
    fprintf(aTanhFile, 'yMin = %f, yMax = %f, yPts = %d\n', yMin, yMax, yPts);
    for i = 1:1:length(myATanhPSNR(:,1))
        for j = 1:1:length(myATanhPSNR(1, :))
            fprintf(aTanhFile, 'Exp Width: %d, Frac Width: %d, Num Iterations: %d\n', expArr(i), fracArr(i), iterArr(j));
            fprintf(aTanhFile, '%f\n', myATanhPSNR(i, j));
        end
    end
    fclose(aTanhFile);
    
end