#include "data.h"
#include <iostream>

#define	TEXT_BASE		0x00000000
#define	TEXT_SIZE		0x00005000

#define	DATA_CACHED_BASE	0x10000000
#define	DATA_CACHED_SIZE	0x00000100

#define	DATA_UNCACHED_BASE	0x40000000
#define	DATA_UNCACHED_SIZE	0x00000100

#define	STACK_BASE		0x50000000
#define	STACK_SIZE		0x00000200
				
#define TTY_BASE        	0x60000000
#define TTY_SIZE        	0x00000100 

#define SIM2OS_BASE     	0x70000000
#define SIM2OS_SIZE     	0x00000100 

#define RAMLOCK_BASE    	0x80000000
#define RAMLOCK_SIZE    	0x00000100 

using namespace hierarchy_memory::data;
using namespace std;

void test_ko (int val)
{
  cout << "***** Test(" << val << ") KO *****" << endl;
  exit (val);
}

void test_ok ()
{
  cout << "***** Test OK *****" << endl;
  exit (0);
}

static uint32_t num_test = 1;

template <class T>
void test(T exp1, T exp2)
{
  if (exp1 != exp2)
    test_ko (num_test);
  num_test ++;
}

int main ()
{
  cout << "<main> Test de \"Data\"" << endl;
  
  cout << "  * Create a Data" << endl;

  SOCLIB_SEGMENT_TABLE segtable;
  segtable.setMSBNumber    (8);
  segtable.setDefaultTarget(0,0);
  
  //shared data segment


  
  // Add a segment   :name        , address of base    , size               , global index , local index, uncache
  segtable.addSegment("text"      , TEXT_BASE          , TEXT_SIZE          , 0            ,0           , false);
  segtable.addSegment("data"      , DATA_CACHED_BASE   , DATA_CACHED_SIZE   , 0            ,0           , false);
  segtable.addSegment("data_unc"  , DATA_UNCACHED_BASE , DATA_UNCACHED_SIZE , 0            ,0           , true );
  segtable.addSegment("stack"     , STACK_BASE         , STACK_SIZE         , 0            ,0           , false);
  segtable.addSegment("tty"       , TTY_BASE           , TTY_SIZE           , 0            ,0           , true );
  segtable.addSegment("sim2os"    , SIM2OS_BASE        , SIM2OS_SIZE        , 0            ,0           , true );
  segtable.addSegment("ramlock"   , RAMLOCK_BASE       , RAMLOCK_SIZE       , 0            ,0           , true );

  Data my_data = Data(param_t("my_data",16,0,0,&segtable));

  const char * sections_text  []  = {".text",NULL}; 
  const char * sections_data  []  = {".data",".rodata",".sdata",".sbss",".bss", NULL}; 
  const char * sections_stack []  = {".stack",NULL}; 
  const char * filename           = "soft.x";

  test <bool> (my_data.init("text"   , filename, sections_text) ,true);
  test <bool> (my_data.init("stack"  , filename, sections_stack),true);
  test <bool> (my_data.init("data"   , filename, sections_data) ,true);
  
  segtable.print();

  cout << my_data << endl;

  uint32_t size, offset;
  char   * data = new char [100];

  // *************************************************************
  offset = 0;
  size   = 32;
  
  cout << " * Read  of bytes [" << DATA_CACHED_BASE+offset << ":" << DATA_CACHED_BASE+offset+size << "[" << endl;

  test <bool> (my_data.read(DATA_CACHED_BASE+offset,size,data), true);

  for (uint32_t it = 0; it < size; it ++)
    {
      if (it % 4 == 0)
	printf("\n");

      printf("%.2x",(unsigned char)(data[it]));
    }
  printf("\n");

  // *************************************************************
  offset = 8;
  size   = 16;
  char * data_src = new char [100];
  sprintf(data_src,"123456780abcdef0");

  cout << " * Write of bytes [" << DATA_CACHED_BASE+offset << ":" << DATA_CACHED_BASE+offset+size << "[" << endl;

  test <bool> (my_data.write(DATA_CACHED_BASE+offset,size,data_src), true);

  for (uint32_t it = 0; it < size; it ++)
    {
      if (it % 4 == 0)
	printf("\n");

      printf("%.2x",(unsigned char)(data_src[it]));
    }
  printf("\n");

  // *************************************************************
  offset = 0;
  size   = 32;
  cout << " * Read  of bytes [" << DATA_CACHED_BASE+offset << ":" << DATA_CACHED_BASE+offset+size << "[" << endl;

  test <bool> (my_data.read(DATA_CACHED_BASE+offset,size,data), true);

  for (uint32_t it = 0; it < size; it ++)
    {
      if (it % 4 == 0)
	printf("\n");

      printf("%.2x",(unsigned char)(data[it]));
    }
  printf("\n");

  // *************************************************************

  cout << " * Recherche of address" << endl;
  test<bool> (my_data.entity(0x00000034, 2).present,true );
  test<bool> (my_data.entity(0x00005000, 1).present,false);
  test<bool> (my_data.entity(0x00004FFD, 2).present,true );
  test<bool> (my_data.entity(0x00004FFD, 4).present,false);
  test<bool> (my_data.entity(0x10000000, 1).present,true );
  test<bool> (my_data.entity(0x0FFFFFFF,10).present,false);

  cout << " * Typage" << endl;
  cout << my_data.entity(TTY_BASE,TTY_SIZE) << endl;
  my_data.entity(TTY_BASE,TTY_SIZE).segment->define_target (TYPE_TTY,0);
  cout << my_data.entity(TTY_BASE,TTY_SIZE) << endl;

  cout << my_data.entity("ramlock") << endl;
  my_data.entity("ramlock").segment->define_target (TYPE_RAMLOCK,0);
  cout << my_data.entity("ramlock") << endl;

  test_ok ();
}
