% alex35.m
% 
% 2025/03/04  Written
% 2025/03/12  Image size expanded from 31x31 (4 outputs) to 35x35 (9 outputs)

clear;

%--- Set these
% Set LoadData=1 to load the data file written by the verilog simulation. 
% It should include:
%   aa    image data                 as specified
%   f     filter data                as specified
%   outv  output from verilog HW     integer
LoadData      = 3;      % 0=load from vdata.m, 1=small ints, 2,3=random
DimColor      = 1;      % 1=grayscale
DimImage      = 35;     % 35 x 35 x DimColor
DimFilter     = 11;     % 11 x 11 x DimColor
StrideConv    = 4;
Pool_s        = 2;
Pool_z        = 3;

%--- Calculate a few things
DimConvolutionOut = (DimImage-DimFilter)/StrideConv + 1;

%--- Load verilog data or generate random image data and filters 
if (LoadData == 0)              % load data from file vdata.m
  vdata.m       

elseif (LoadData == 1)          % only for testing this matlab script
  for k1=1:DimImage
    for k2=1:DimImage
      for k3=1:DimColor
        aa(k1,k2,k3) = k1+k2+k3-3;
      end
    end
  end
  for k1=1:DimFilter
    for k2=1:DimFilter
      for k3=1:DimColor
        f(k1,k2,k3) = k1+k2+k3-DimFilter-2;
      end
    end
  end

elseif (LoadData == 2)          % only for testing this matlab script
  RandomNumberGenSeed = 123; %281;
  rng(RandomNumberGenSeed)
  aa = round(8* rand(DimImage, DimImage, DimColor) - 0.501);
  f  = round(8* rand(DimFilter,DimFilter,DimColor) - 4);

elseif (LoadData == 3)          % only for testing this matlab script
  RandomNumberGenSeed = 1234; %281;
  rng(RandomNumberGenSeed)
  aa = round(256* rand(DimImage, DimImage, DimColor) - 0.501);
  f  = round(256* rand(DimFilter,DimFilter,DimColor) - 128);

else
  fprintf('Error\n\n');  return;
end

%--- Print some comments
fprintf('=== To see the contents of a variable, type its name, then <Enter>\n');
fprintf('  aa           // input pixel data\n');
fprintf('  f            // filter data\n');
fprintf('  aawindow     // current 11x11 pixel data \n');
fprintf('  product      // current 11x11 pixel data * filter\n');
fprintf('  out          // convolution output\n');
fprintf('  out_relu     // convolution output after ReLU\n');
fprintf('  out_max_pool // convolution output after ReLU and pooling\n\n');

%--- Perform filtering
fprintf('=== (1,1) is the upper left pixel of the image\n');
fprintf('=== (x,y) coordinates are for the upper left pixel of the subimage being filtered\n');
for xoffset = 1:StrideConv:(DimImage-DimFilter)+1
  for yoffset = 1:StrideConv:(DimImage-DimFilter)+1
    aawindow = aa(xoffset:xoffset+10, yoffset:yoffset+10, :);
    product  = f  .* aawindow;
    xindex   = (xoffset-1)/StrideConv;
    yindex   = (yoffset-1)/StrideConv;
    out(xindex+1, yindex+1) = sum(sum(sum(product)));
    fprintf('  out(%2i,%2i) = %7i\n', xoffset, yoffset, out(xindex+1, yindex+1));
  end
end

%--- out
fprintf('\n=== out (convolution) is a %i x %i matrix\n', DimConvolutionOut, ...
  DimConvolutionOut);
out

%--- ReLU
out_relu = max(out, zeros(DimConvolutionOut,DimConvolutionOut));

out_relu

%--- max pool
Pool_step = Pool_z - Pool_s;
size_out = size(out_relu);
xmax = floor((size_out(1) - Pool_step) / Pool_s);
ymax = floor((size_out(2) - Pool_step) / Pool_s);
for ycount = 1:ymax
  for xcount = 1:xmax
    xlo = xcount*Pool_s -1;
    xhi = xlo + Pool_z -1;
    ylo = ycount*Pool_s -1;
    yhi = ylo + Pool_z -1;
    out_max_pool(xcount,ycount) = max(max(out_relu(xlo:xhi, ylo:yhi)));
  end
end

out_max_pool

