% Joshua Mack, Sam Bellestri, Nia Simmonds IREECE 2015
% UltimateTestScript_coshSinh:
%   Acts as a completely autonomous test script for testing floating-point cosh and sinh.
%   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_coshSinh()

    % Define the test domain
    xMin = -12.42644;
    xMax = 12.42644;
    xPts = 1000;
    
    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];
    
    % Define the filenames that results will be written to at the end of the script
    coshFilename = ['coshX_PSNR_', num2str(length(fracArr)*length(iterArr)), '_Cases_', num2str(xMin, 2), '_to_', num2str(xMax, 2), '_', datestr(datetime('today')), '.txt'];
    sinhFilename = ['sinhX_PSNR_', num2str(length(fracArr)*length(iterArr)), '_Cases_', num2str(xMin, 2), '_to_', num2str(xMax, 2), '_', datestr(datetime('today')), '.txt'];
    
    % Name of the VHDL testbench file
    tbName = 'FloP_FullCORDIC_Generic_tb.vhd';
    % Path to testbench directory -- Generic form: "*PathToVivadoProj*/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. 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 xPts results in it). 
    unix('rm ./FloP_coshX_VivadoResults/* ./FloP_sinhX_VivadoResults/*');

    myCoshPSNR = zeros(length(fracArr), length(iterArr));
    mySinhPSNR = 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 out diagnostic information to let the poor soul watching this simulation run know what case it's on
                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: "*PathToVivadoProj*/VHDLProj.sim/sim_1/behav"
                coshResultsPath = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/VHDL/FlexibleFloPCORDIC/FlexibleFloPCORDIC.sim/sim_1/behav/';
                sinhResultsPath = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/VHDL/FlexibleFloPCORDIC/FlexibleFloPCORDIC.sim/sim_1/behav/';
                %Then concatenate the filename of the simulation results
                coshResultsPath = [coshResultsPath, num2str(numIterations), 'iterations', num2str(fracWidth+expWidth+1), 'bits_cosh.txt"'];
                sinhResultsPath = [sinhResultsPath, num2str(numIterations), 'iterations', num2str(fracWidth+expWidth+1), 'bits_sinh.txt"'];
                
                %Generate LUTs
                [fileName1, fileName2] = generateLUTs(numIterations,expWidth,fracWidth);
                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('r', xMin, xMax, xPts, 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 ', coshResultsPath, ' ', MatlabPath, 'FloP_coshX_VivadoResults/"']);
                unix(['cp ', sinhResultsPath, ' ', MatlabPath, 'FloP_sinhX_VivadoResults/"']);
                
                % Call the matlab PSNR script
                [myCoshPSNR(i, j), mySinhPSNR(i, j)] = convertPlotAndPSNR_coshX_sinhX(xMin, xMax, xPts, expWidth, fracWidth, numIterations);

                % Whenever an error occurs in the simulation, repeat the simulation until it works.
                while myCoshPSNR(i, j) == -123456 || mySinhPSNR(i, j) == -123456
                    unix('C:/Xilinx/Vivado/2015.1/bin/vivado -mode tcl -source "./TCL_Files/coshSinhATanhSim.tcl"');
                    unix(['cp ', coshResultsPath, ' ', MatlabPath, 'FloP_coshX_VivadoResults/"']);
                    unix(['cp ', sinhResultsPath, ' ', MatlabPath, 'FloP_sinhX_VivadoResults/"']);
                    [myCoshPSNR(i, j), mySinhPSNR(i, j)] = convertPlotAndPSNR_coshX_sinhX(xMin, xMax, xPts, expWidth, fracWidth, numIterations);
                end
            else
                % Keep each sample equal in length regardless of cases run
                myCoshPSNR(i, j:1:length(iterArr)) = myCoshPSNR(i, j-1);
                mySinhPSNR(i, j:1:length(iterArr)) = mySinhPSNR(i, j-1);
            end
        end
        % Plot the results
        figure(h1);
        subplot(1, 2, 1);
        myCoshPlots(i) = plot(iterArr, myCoshPSNR(i, :), 'd-'); hold all;
        subplot(1, 2, 2);
        mySinhPlots(i) = plot(iterArr, mySinhPSNR(i, :), 'd-'); hold all;
    end
    
    % Add some legends and titles to make it look nice
    for i = 1:1:length(fracArr)
       legendStrs{i} = [num2str(fracArr(i) + expArr(i) + 1), ' bits'];
    end
    
    h2 = subplot(1, 2, 1);
    legend(myCoshPlots, legendStrs);
    title(['$\cosh$[x] PSNR vs Number of Iterations, ', ...
            num2str(xMin), ' $\leq$ x $\leq$ ', num2str(xMax)], 'Interpreter', 'laTex');
    set(h2, 'FontWeight', 'bold');
    set(h2, 'FontSize', 11);
    set(get(h2,'Title'), 'FontSize', 14);
    
    h2 = subplot(1, 2, 2);
    legend(mySinhPlots, legendStrs);
    title(['$\sinh$[x] PSNR vs Number of Iterations, ', ...
            num2str(xMin), ' $\leq$ x $\leq$ ', num2str(xMax)], 'Interpreter', 'laTex');
    set(h2, 'FontWeight', 'bold');
    set(h2, 'FontSize', 11);
    set(get(h2,'Title'), 'FontSize', 14);
        
    %And write the results to a file because why not?
    coshFile = fopen(['./PSNR_Output/', coshFilename], 'w');
    sinhFile = fopen(['./PSNR_Output/', sinhFilename], 'w');
    fprintf(coshFile, 'xMin = %f, xMax = %f, xPts = %d\n', xMin, xMax, xPts);
    fprintf(sinhFile, 'xMin = %f, xMax = %f, xPts = %d\n', xMin, xMax, xPts);
    for i = 1:1:length(myCoshPSNR(:,1))
        for j = 1:1:length(myCoshPSNR(1, :))
            fprintf(coshFile, 'Exp Width: %d, Frac Width: %d, Num Iterations: %d\n', expArr(i), fracArr(i), iterArr(j));
            fprintf(coshFile, '%f\n', myCoshPSNR(i, j));
            
            fprintf(sinhFile, 'Exp Width: %d, Frac Width: %d, Num Iterations: %d\n', expArr(i), fracArr(i), iterArr(j));
            fprintf(sinhFile, '%f\n', mySinhPSNR(i, j));
        end
    end
    fclose(coshFile);
    fclose(sinhFile);
    
end