% Joshua Mack, Sam Bellestri, Nia Simmonds IREECE 2015
% convertPlotAndPSNR_xToTheY_Plotter_Fixed:
%   Takes in the test domain used in a given testbench file along with the corresponding integer and fractional widths of the format and number of iterations
%   And then looks for a corresponding results textfile of the form "(numIters)iterations(intWidth+fracWidth)bits_xToTheY_Fixed.txt"
%   inside a "FixedPt_xToTheY_VivadoResults" directory within your current Matlab operating directory.
%   If it doesn't find the file, it displays an error message, and if the file doesn't have the number of points as specified by xPoints * yPoints (i.e. 50 xPoints and 30 yPoints => 1500 test points)
%   Then it also returns an error and exits. 

function myPSNR = convertPlotAndPSNR_xToTheY_Plotter_Fixed(xLower, xUpper, yLower, yUpper, xPoints, yPoints, intWidth, fracWidth, numIters)
    
    % Define a few variables.
    dataWidth = intWidth+fracWidth;
    q = quantizer('fixed', [dataWidth fracWidth]);
    xRange = linspace(xLower, xUpper, xPoints); 
    yRange = linspace(yLower, yUpper, yPoints);
    fileName = [num2str(numIters), 'iterations', num2str(dataWidth), 'bits_xToTheY_Fixed.txt'];
    
    % Attempt to open the results file.
    file1 = fopen(['./FixedPt_xToTheY_VivadoResults/', fileName], 'r');
    if file1 == -1
        % Display an error if the file not found.
        fprintf('----------------------------------------------------\n');
        display(['xToTheY results not found for ', num2str(intWidth+fracWidth), ' bits, ', num2str(numIters), ' iterations.']);
        fprintf('----------------------------------------------------\n');
        % This value is used as an indication value for the corresponding "UltimateTestScript_xToTheY_Fixed_Plotter.m" file
        % That an error occured inside this script and that it should rerun the simulation for this given test case.
        myPSNR = -123456;
        return;
    end

    % Otherwise, the results file was found. Scan the results into a cell array of strings
    s1 = textscan(file1,'%s');
    fclose(file1);
    
    % Extract the results strings.
    myPowStrs = s1{1};

    % Check that the length of the results file is as long as it should be.
    if length(myPowStrs) ~= xPoints*yPoints
        % Otherwise, display an error and exit with the given error code.
        fprintf('----------------------------------------------------\n');
        display(['The Vivado simulator did not finish for ', num2str(intWidth+fracWidth), ' bits, ', num2str(numIters), ' iterations.']);
        fprintf('----------------------------------------------------\n');
        myPSNR = -123456;
        return;
    end
    
    % If we're at this point, the file existed, and all the values were successfully extracted.
    % Allocate some memory.
    myXToTheYs = zeros(yPoints, xPoints);
    valNum = 1;
    for i = 1:1:xPoints
        for j = 1:1:yPoints
            % (j, i) because 'surf' plotting wants things in the order surf(yVals, xVals, zVals) 
            % So switch x and y to make it right.
            % Assign each x^y value with the corresponding string's numerical value.
            myXToTheYs(j, i) = bin2num(q, cell2mat(myPowStrs(valNum)));
            valNum = valNum + 1;
        end
    end
    
    % Used for displaying X^Y 3D surface plots for the certain given parameter setups. Completed testing our whole range and plotting specific parameterizations at the same time.
    if (dataWidth == 24 && numIters == 8 || dataWidth == 28 && numIters == 8 || dataWidth == 36 && numIters == 16 || dataWidth == 40 && numIters == 20 || dataWidth == 44 && numIters == 24)
        figure();
        % display(size(xRange)); display(size(yRange)); display(size(myXToTheYs));
        surf(xRange, yRange, myXToTheYs);
        xlabel('X Values');
        ylabel('Y Values');
        zlabel('{X}^{Y} Values');
        title(['{X}^{Y} Plot, ', num2str(intWidth+fracWidth), ' bits, ', num2str(xLower), '\leq x \leq', num2str(xUpper), ', ', num2str(yLower), '\leq y \leq', num2str(yUpper)]);
    end

    % Allocate memory for the reference Matlab values.
    matlabPows = zeros(yPoints, xPoints);
    for i = 1:1:xPoints
        % Depending on testing setup, may want to uncomment this line. Causes yRange to vary along the entire permitted range for a given x-value when M = 5.
        % yRange = linspace(-12.42644/log(xRange(i)), 12.42644/log(xRange(i)), yPoints);
        for j = 1:1:yPoints
            matlabPows(j, i) = xRange(i)^yRange(j);
        end
    end
    
    % Assign the maximum value as the maximum finite value of the minimum fixed-point format needed to represent the maximum x^y value in the given test domain.
    % For example, if the largest x^y value produced in a given test interval is ~250000, then it requires 18 integer bits to represent.
    maxVal = 2^(18) - 2^(-fracWidth);
    myPSNR = psnr(myXToTheYs, matlabPows, maxVal);
    display(myPSNR);
    return;
    
end