//---------------------------------------------------------------------------
#pragma hdrstop

#include "generate_ver_env.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
//---------------------------------------------------------------------------

#pragma package(smart_init)

#define FILE_COUNT 4
#define TEMP_VER_SOURCES_ADDR "temp_models/"
#define VER_SOURCES_ADDR "models/"
#define VER_FILE_NAMES {"bfm",       \
                        "ref_fft",   \
                        "tb",        \
                        "testcase"};


 int fce_gen_ver_env (int stage_count, int bit_size, FILE *report)
  {
   int file_ind;
   int _error = 0;

   _error = _error + fce_gen_ver_def_pkg_file(stage_count, bit_size, report);
   _error = _error + fce_gen_ver_const_bank(pow(2, stage_count-1), report);
   for (file_ind = 0; file_ind < FILE_COUNT; file_ind ++)
    {
     _error = _error + fce_copy_ver_files(file_ind,report);
    }
    return _error;
  }

 int fce_gen_ver_def_pkg_file(int  stage_count,
                              int  bit_size,
                              FILE *report)
  {
   FILE *def_pkg;
   FILE *def_pkg_template;
   char line [85];
   int __error = 0;


    def_pkg = fopen(VER_SOURCES_ADDR"test_pkg.sv", "w");
    def_pkg_template = fopen (TEMP_VER_SOURCES_ADDR"test_pkg_temp.sv", "r");

    if (def_pkg_template == NULL)
    {
     fprintf(report, "Error during opening test_pkg_temp.sv file!\n");
     __error = __error + 1;
    }
     else if (def_pkg == NULL)
    {
     fprintf(report, "Error during opening test_pkg.sv file!\n");
     __error = __error + 1;
    }
     else
   {
    while (!feof(def_pkg_template))
     {
      fgets(line,sizeof(line) - 1,def_pkg_template);
      if (strstr(line,"/*insert verification parameters*/"))
       {
        fprintf(def_pkg, "  localparam c_DATA_WIDTH  = %d;  // bit size of input/output data\n",bit_size);
        fprintf(def_pkg, "  localparam c_STAGE_COUNT = %d;   // stage count = log2(c_FFT_SIZE);\n", stage_count);

       }
      else
       fprintf(def_pkg, line);
     }

     fprintf(report, "FFT verification parameters package generated.\n");
     fclose(def_pkg);
     fclose(def_pkg_template);
   }
   return __error;
}

 int fce_gen_ver_const_bank (int const_count, FILE *report)
  {
   FILE *const_bank;
   int  const_addr;
   float const_float;
   int __error = 0;

   const_bank = fopen(VER_SOURCES_ADDR"/const_ver_bank.sv", "w");
   if (const_bank == NULL)
    {
     fprintf(report, "Error during opening verification const_bank.sv file!\n");
     __error = __error + 1;
    }
    else
   {
   fprintf(const_bank, "//---------------------------------------------------------------------------\n");
   fprintf(const_bank, "//------------------- Constant bank for verification ------------------------\n");
   fprintf(const_bank, "//---------------------------------------------------------------------------\n\n");

   fprintf(const_bank, "`timescale 1 ns/1 ps \n\n");

   fprintf(const_bank, "package const_bank_for_ver; \n\n");

   fprintf(const_bank, "typedef real  t_CONST_ARRAY [0 : %d]; \n\n",const_count-1);

   fprintf(const_bank, "const t_CONST_ARRAY c_CONST_VER_RE  = { \n");  

   for (const_addr = 0; const_addr < const_count; const_addr++)  
    {
     const_float = cos(3.14159/const_count*const_addr);

     fprintf(const_bank, "             %12f",const_float); 
     if (const_addr < const_count -1)
      {
       fprintf(const_bank, ", ");}
       fprintf(const_bank, "\n");
      }
   fprintf(const_bank, "             }; \n\n\n");

   fprintf(const_bank, "const t_CONST_ARRAY c_CONST_VER_IM = {  \n");

   for (const_addr = 0; const_addr < const_count; const_addr++)
    {
     const_float = -(sin(3.14159/const_count*const_addr));

     fprintf(const_bank, "             %12f",const_float); 
     if (const_addr < const_count-1)
       fprintf(const_bank, ", ");

     fprintf(const_bank, "\n");
    }
     fprintf(const_bank, "             }; \n\n");
  
     fprintf(const_bank, "endpackage : const_bank_for_ver; \n\n");

     fprintf(report, "Verification constant bank generated\n");

     fclose(const_bank);
   }
   return __error;
  }

 int fce_copy_ver_files (int file_ind, FILE *report)
  {
   FILE *file;
   FILE *file_out;
   char temp_file_name[50];
   char hdl_file_name[50];
   char line [85];
   char file_list[FILE_COUNT] [20] = VER_FILE_NAMES
   int __error = 0;

   strcpy(temp_file_name,TEMP_VER_SOURCES_ADDR);
   strcat(temp_file_name,file_list[file_ind]);
   strcat(temp_file_name,".sv"); 

   strcpy(hdl_file_name,VER_SOURCES_ADDR);   
   strcat(hdl_file_name,file_list[file_ind]);
   strcat(hdl_file_name,".sv");

   file = fopen(temp_file_name,"r");
   file_out = fopen(hdl_file_name,"w");

   if (file == NULL || file_out == NULL)
    {
     __error = __error + 1;
     fprintf(report, "Error during copying source file %s into models/ directory.\n \
                      Check if template file and models/ directory exist.\n",
             hdl_file_name);
    }
   else
    {
     fprintf(report, "Source file %s was copied into models/ directory.\n",
             temp_file_name);
     while (!feof(file))
      {
       fgets(line,sizeof(line),file);
       fprintf(file_out, line);     
      }

     fclose(file);
     fclose(file_out);
    }
  return __error;
}
