% Joshua Mack, Sam Bellestri, Nia Simmonds IREECE 2015
% UltimateTestScript_xToTheY_Fixed:
%   Acts as a completely autonomous test script for testing fixed-point x^y.
%   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.

% NOTE: The main difference between the xToTheY testscript and the xToTheY_Plotter test script is that
% the main one strictly tests along the entire permitted y-interval for each corresponding x-value and thus allows for more comprehensive results
% while the "Plotter" version tests along a scrictly rectangular domain to allow for easy "surf" plotting of the corresponding x^y results.

function [] = UltimateTestScript_xToTheY_Fixed_Plotter

    % Normal mode is the mode described above. This file does not have any other mode, 
    % but the other fixed-point xToTheY test script does.
    fprintf('Running in normal mode...\n\n');

    %Disable underflow/overflow quantization error warnings. They're annoying, and we know they're going to happen.
    warning('off', 'fixed:fi:overflow');
    warning('off', 'fixed:fi:underflow');

    % Define the desired test domain along with resolution of points.
    xMin = exp(-12.42644/2); xMax = exp(12.42644/2); xPts = 30;
    yMin = -2.0; yMax = 2.0; yPts = 50;
    
    % Define the desired configurations to be tested. Note that fracArr corresponds exactly with intArr.
    % So, for example, the cases being tested here are 8 + 16 = 24, 8 + 20 = 28, 12 + 20 = 32, ..., 32 + 44 = 76 bits,
    % and they all vary from 8, 12, 16, ..., 40 iterations.
    fracArr = [8 8 12 16 20 24 28 32 32 32 32 32 32 32];
    intArr = [16 20 20 20 20 20 20 20 24 28 32 36 40 44];
    iterArr = [8 12 16 20 24 28 32 36 40];
    
    % Filename that results will be saved to after testing
    fileName = ['xToTheY_Fixed_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 = 'Fixed_xToTheY_Generic_tb.vhd';
    % Path to testbench directory -- generic form is "*PathToVHDLProject*/VHDL_Proj.srcs/sim_1/new"
    VHDLPath = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/VHDL/Fixed_xToTheY/Fixed_xToTheY.srcs/sim_1/new/"';
    % Path to Matlab directory -- the current working directory for Matlab. Can most likely be replaced with "pwd" of some sort, but that hasn't been tested.
    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 xPoints*yPoints results in it)
    unix ('rm ./FixedPt_xToTheY_VivadoResults/*');

    myPSNR = 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 iteration
                intWidth = intArr(i); fracWidth = fracArr(i); numIterations = iterArr(j);
                % Print diagnostic information to the console for the poor soul who's watching this script execute. If the timestamp is significantly longer ago than most others,
                % then the Vivado simulator most likely got stuck somewhere. Simply kill its process to hand control back over to Matlab.
                fprintf('\n--------------------------------------\n');
                fprintf('%d bits, %d iterations, %s', intWidth+fracWidth, numIterations, datestr(now, 'HH:MM:SS PM'));
                fprintf('\n--------------------------------------\n'); 

                % Path to simulation results
                % First just establish the basic path
                % Generic form: "*PathToVivadoProject*/VHDL_Proj.sim/sim_1/behav" 
                simuResultsPath = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/VHDL/Fixed_xToTheY/Fixed_xToTheY.sim/sim_1/behav/';
                %Then concatenate the filename of the simulation results
                simuResultsPath = [simuResultsPath, num2str(numIterations), 'iterations', num2str(fracWidth+intWidth), 'bits_xToTheY_Fixed.txt"'];

                % Generate testbench
                Fixed_xToTheY_Generic_tb_Plotter(xMin, xMax, yMin, yMax, xPts, yPts, intWidth, fracWidth, numIterations);
                % Copy it to the vivado project
                unix(['cp ./', tbName, ' ', VHDLPath]);

                % Generate LUTs
                [fileName1, fileName2] = generateFixedLUTs(numIterations,intWidth,fracWidth);
                % Generic form: "*PathToVivadoProject*/VHDL_Proj.srcs/sources_1/imports"
                projectPathStr = '"C:/Data/College Stuff/IREECE 2015/Cylinder Pressure Estimation/VHDL/Fixed_xToTheY/Fixed_xToTheY.srcs/sources_1/imports/"';
                unix(['mv ', fileName1, ' ', fileName2, ' ', projectPathStr]);

                % 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/xToTheYSim_Fixed.tcl');

                % Copy the results back to matlab directory into PSNR folder
                unix(['cp ', simuResultsPath, ' ', MatlabPath, '/FixedPt_xToTheY_VivadoResults/"']);

                % Call the matlab PSNR analysis script
                myPSNR(i, j) = convertPlotAndPSNR_xToTheY_Plotter_Fixed(xMin, xMax, yMin, yMax, xPts, yPts, intWidth, fracWidth, numIterations);

                % Whenever Vivado fails, keep repeating the simuation 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 xPoints*yPoints data points to analyze
                while myPSNR(i, j) == -123456
                    unix('C:/Xilinx/Vivado/2015.1/bin/vivado -mode tcl -source ./TCL_Files/xToTheYSim_Fixed.tcl');
                    unix(['cp ', simuResultsPath, ' ', MatlabPath, '/FixedPt_xToTheY_VivadoResults/"']);
                    myPSNR(i, j) = convertPlotAndPSNR_xToTheY_Plotter_Fixed(xMin, xMax, yMin, yMax, xPts, yPts, intWidth, fracWidth, numIterations);
                end
            else
                %Keep each sample equal in length regardless of cases run
                myPSNR(i, j:1:length(iterArr)) = myPSNR(i, j-1);
            end
        end
        %Plot the results
        figure(h1);
        myPlots(i) = plot(iterArr, myPSNR(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) + intArr(i)), ' bits'];
    end
    legend(myPlots, legendStrs);
    title(['${X}^{Y}$ FixedPt PSNR vs Number of Iterations, ', ...
            num2str(xMin), ' $\leq$ x $\leq$ ', num2str(xMax)], 'Interpreter', 'laTex');
    
    % In this specific test script, we didn't need to write the results to a file. But the option is here.
    %And write the results to a file because why not?
    % myFile = fopen(['./PSNR_Output/', fileName], 'w');
    % fprintf(myFile, 'xMin = %f, xMax = %f, xPts = %d, yPts = %d\n', xMin, xMax, xPts, yPts);
    % for i = 1:1:length(myPSNR(:, 1))
    %     for j = 1:1:length(myPSNR(1, :))
    %         fprintf(myFile, 'Int Width: %d, Frac Width: %d, Num Iterations: %d\n', intArr(i), fracArr(i), iterArr(j));
    %         fprintf(myFile, '%f\n', myPSNR(i, j));
    %     end
    % end
    % fclose(myFile);
    
end