/* ram_image.c by Steve Rhoads 11/7/05 
 * This program take the ram_xilinx.vhd file as input
 * and the code.txt file as input.
 * It then creates ram_image.vhd as output with the
 * initialization vectors set to the contents of code.txt.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUF_SIZE (1024*1024)

unsigned int swap_int (unsigned int data)
{
  unsigned char* b=(unsigned char*)&data;
  unsigned char t;
  t=b[3]; b[3]=b[0]; b[0]=t;
  t=b[2]; b[2]=b[1]; b[1]=t;
  return data;
}



int main(int argc, char *argv[])
{
   FILE *file;
   int i, j, index, size, count;
   char *buf, *ptr, *ptr_list[64*4], text[80];
   unsigned int *code;

   if(argc < 4)
   {
      printf("Usage: ram_image <in.vhd> <file.bin> <out.vhd>\n");
      printf("Usage: ram_image ram_xilinx.vhd <file.bin> ram_image.vhd\n");
      return 0;
   }

   buf = (char*)malloc(BUF_SIZE);
   code = (unsigned int*)malloc(BUF_SIZE);

   //Read ram_xilinx.vhd
   file = fopen(argv[1], "rb");
   if(file == NULL)
   {
      printf("Can't open %s!\n", argv[1]);
      return -1;
   }
   size = fread(buf, 1, BUF_SIZE, file);
   fclose(file);

   //Read binary file 
   file = fopen(argv[2], "r");
   if(file == NULL)
   {
      printf("Can't open %s!\n", argv[2]);
      return -1;
   }
   for(count = 0; count < 16*1024; ++count)
   {
      if(feof(file))
         break;
      fread ( &code[count], 1, sizeof(unsigned int), file);
   }
   fclose(file);

   //Find 'INIT_00 => X"'
   ptr = buf;
   for(i = 0; i < 64*4; ++i)
   {
      sprintf(text, "INIT_%2.2X => X\"", i % 64);
      ptr = strstr(ptr, text);
      if(ptr == NULL)
      {
         printf("ERROR:  Can't find '%s' in file!\n", text);
         return -1;
      }
      ptr_list[i] = ptr + strlen(text);
   }

   //Modify vhdl source code
   //ptr_list[64*4] four banks of 64 bytes: Bank0 D31-D24 Bank1 D23-D16 Bank2 D15-D8 Bank3 D7-D0
   j = 62;
   for(i = 0; i < count; ++i)
   {  
      sprintf(text, "%8.8x", swap_int(code[i]));
      index = i / 32;
      ptr_list[index][j]       = text[0]; // Bank0 D31- D28
      ptr_list[index][j+1]     = text[1]; // Bank0 D27- D24
      ptr_list[index+64][j]    = text[2]; // Bank0 D23- D20
      ptr_list[index+64][j+1]  = text[3]; // Bank0 D19- D16
      ptr_list[index+128][j]   = text[4]; // Bank0 D15- D12
      ptr_list[index+128][j+1] = text[5]; // Bank0 D11- D8
      ptr_list[index+192][j]   = text[6]; // Bank0 D7 - D4
      ptr_list[index+192][j+1] = text[7]; // Bank0 D3 - D0
      j -= 2;
      if(j < 0)
         j = 62;
   }

   //Write ram_image.vhd
   file = fopen(argv[3], "wb");
   if(file == NULL)
   {
      printf("Can't write %s!\n", argv[3]);
      return -1;
   }
   fwrite(buf, 1, size, file);
   fclose(file);
   free(buf);
   free(code);
   return 0;
}