text: 
  /**
   * @file   src/memluv.c
   * @author Dionysios Diamantopoulos(diamantd@microlab.ntua.gr)
   * @date   December 2013
   *
   * @brief  Memluv functions. Major calls are included in separate files, rest lives here.
   */
  
  #include "memluv.h"
  #include "global.c"
  #include "util.c"
  #include "freelist.c"
  #include "free.c"
  #include "malloc.c"
  #include "types/arraylist.c"
  
  
  void MemluvInit() {
  /* TODO: MemluvInit shall be synthesized as well. However currently the MemLuvCoreArray is 
   * not always properly synthesized by Vivado 2013.4, thus we keep it in unsythesizable region.
   */
  #ifndef __SYNTHESIS__
  #if SIM_MINIMUM_OVERHEAD==0
  	int i;
  	CurMemLuvConf = &MemLuvConf0;
  	char filename[64];
  	/* get the process id */
  	if ((CurMemLuvConf->pid = getpid()) < 0)
  		perror("Unable to get pid.");
  	else {
  		sprintf(filename, "./memluv_run_%d.log", CurMemLuvConf->pid);
  		printf("INFO: Bringing up MemLuv x86-simulation environment with pid %d\n", CurMemLuvConf->pid);
  	}
  #if DEBUG_PRINT_STREAM==1
  	if (NULL == (CurMemLuvConf->dbg_fd = fopen(filename, "w"))) {
  		printf ("ERROR: Could not create run log file %s. Aborting...\n", filename);
  		exit (-1);
  	}
  	else
  		printf ("INFO: Debug messages are printed to %s\n", filename);
  #else
  	CurMemLuvConf->dbg_fd = stdout;
  	printf ("INFO: Runtime messages are printed to stdout\n");
  #endif
  	Dfprintf(1, CurMemLuvConf->dbg_fd, "\nINFO: Linked with MemLuv version %d.%d", MEMLUV_VERSION_MAJOR, MEMLUV_VERSION_MINOR);
  #if SIM_WITH_GLIBC_MALLOC==1
  	Dfprintf(1, CurMemLuvConf->dbg_fd, " (Using glibc malloc)\n");
  #else
  	Dfprintf(1, CurMemLuvConf->dbg_fd, "\n");
  #endif
  	for (i=0; i<NUM_HW_HEAPS; i++) {
  	/* MemLuvCoreArray automated generated by gen_memluv_wrappers.c, included in global.c */
  		MemluvInitCore (MemLuvCoreArray[i]);
  	}
  #endif
  #endif
  }
  
  void MemluvInitCore(MemLuvCore *CurMemLuvCore) {
  #ifndef __SYNTHESIS__
  #if SIM_MINIMUM_OVERHEAD==0
  	uint_t i;
  // 	CurMemLuvCore->base = (var_type_t*)CurMemLuvCore->core;
  	CurMemLuvCore->top = (void*)(CurMemLuvCore->core+MEMLUV_DEPTH-1);
  
  	uint_t length = sizeof(CurMemLuvCore->freelist)/sizeof(FREELIST_UINT_T);
  	for (i=0; i<length; i++) {
  		CurMemLuvCore->freelist[i]=0;
  	}
  	CurMemLuvCore->action_status = 0;
  #if HW_DEBUG_MEMLUV==1
  	CurMemLuvCore->stats.max_address_reached=0;
  	CurMemLuvCore->stats.result=0;
  	CurMemLuvCore->stats.used_percentage=0;
  	CurMemLuvCore->stats.total_bytes_allocated=0;
  	CurMemLuvCore->stats.total_addresses_allocated=0;
  	CurMemLuvCore->stats.total_fragmented_bytes=0;
  	CurMemLuvCore->stats.total_bytes_requested=0;
  	CurMemLuvCore->stats.total_bytes_for_headers=0;
          CurMemLuvCore->stats.total_request_fragmented_bytes=0;
  #endif
  	DumpStatisticsToFile(CurMemLuvCore
  				#if USE_MEMLUV==1 && HW_DEBUG_MEMLUV==1 
  					,0
  					,0
  				#endif
  				);
  	//for (i=10; i<20; i++)
  	//	SetBit( freelist, i );
  #endif
  #endif      
  }
  
  void MemluvEnd() {
  #ifndef __SYNTHESIS__
  #if SIM_MINIMUM_OVERHEAD==0
  	int i;
  #if DEBUG_PRINT_STREAM==1
  	if (0 != fclose(CurMemLuvConf->dbg_fd)) {
  		printf ("ERROR: Could not close run log file. Aborting...\n");
  		exit (-1);
  	}
  	else
  		printf ("INFO: Succesfully closed log file.\n");
  #endif
  	for (i=0; i<NUM_HW_HEAPS; i++) {
  		/* MemLuvCoreArray automated generated by gen_memluv_wrappers.c, included in global.c */
  		MemluvEndCore (MemLuvCoreArray[i]);
  	}
  	printf ("INFO: Closing MemLuv %d.%d sim engine with pid %d\n\n", MEMLUV_VERSION_MAJOR, MEMLUV_VERSION_MINOR, CurMemLuvConf->pid);
  #endif
  #endif      
  }
  
  void MemluvEndCore(MemLuvCore *CurMemLuvCore) {
  #ifndef __SYNTHESIS__
  #if SIM_MINIMUM_OVERHEAD==0
  #if DEBUG_PRINT_STREAM==1
  	printf ("INFO: Trying free up resources of MemLuvCore #%u.\n", CurMemLuvCore->id);
  	/* useless close since the file is opened and closed in every DumpStatisticsToFile() iteration on src/util.c */
  	if (CurMemLuvCore->fd != NULL) {
  		if (0 != fclose(CurMemLuvCore->fd)) {
  			printf ("ERROR: Could not close statistics output file. Aborting...\n");
  			exit (-1);
  		}
  		else
  			printf ("INFO: Succesfully closed statistics output file.\n");
  	}
  #endif
  	printf ("INFO: Succesfully free up resources of MemLuvCore #%u.\n", CurMemLuvCore->id);
  #endif
  #endif   
  }
  
  #if HW_DEBUG_MEMLUV==1
  void MemLuvDebugUpdate(MemLuvCore *CurMemLuvCore, uint_t arg, uint_t value) {
  #ifdef __SYNTHESIS__
  #if MEMLUV_HLS_INLINE == 0
  #pragma AP inline off
  #else
  #pragma AP inline
  #endif
  #endif
  	if (arg == 1)
  		CurMemLuvCore->stats.max_address_reached=value;
  	else if (arg == 2)
  		CurMemLuvCore->stats.result = value;
  	else if (arg == 3)
  		CurMemLuvCore->stats.used_percentage = value;
  	else
  		bprintf("WARNING: Wrong id=%d argument attached on debugger\n", arg);
  }
  #endif
  
  void MemluvInfo(MemLuvCore *CurMemLuvCore, FILE* stream, memluv_struct_handle_t handle) {
  #if SIM_MINIMUM_OVERHEAD==0
  #ifndef __SYNTHESIS__
  	uint_t i=0;
  	while (i < CurMemLuvConf->num_hw_heaps) {
  		/* MemLuvCoreArray automated generated by gen_memluv_wrappers.c, included in global.c */
  		if (handle==THIS)
  			i+=CurMemLuvConf->num_hw_heaps; /* print CurMemLuvCore from argument and exit */
  		else
  			CurMemLuvCore=MemLuvCoreArray[i++]; /* print info for all hw heaps */
  		Dfprintf(1, stream, "\nINFO: ----------- MemLuv internal core info [heap id: %.2d] ----------\n", CurMemLuvCore->id);
  		Dfprintf(1, stream, "INFO: x86 Heap Start Addr: %8p \n", CurMemLuvCore->base);
  		Dfprintf(1, stream, "INFO: x86 Heap End Addr  : %8p [=%8p+0x%x(%u*0x%x(%u))]\n", CurMemLuvCore->top, CurMemLuvCore->base, sizeof(CORE_UINT_T)*((uint_t)(CurMemLuvCore->top - CurMemLuvCore->base + 1)*sizeof(var_type_t)/sizeof(CORE_UINT_T)-1) , sizeof(CORE_UINT_T), (uint_t)(CurMemLuvCore->top - CurMemLuvCore->base + 1)*sizeof(var_type_t)/sizeof(CORE_UINT_T)-1, (uint_t)(CurMemLuvCore->top - CurMemLuvCore->base + 1)*sizeof(var_type_t)/sizeof(CORE_UINT_T)-1);
  		Dfprintf(1, stream, "INFO: Organization       : %u unique addresses x %uB (core type->%uB)\n", CurMemLuvCore->depth, CurMemLuvCore->size/CurMemLuvCore->depth, sizeof(CORE_UINT_T));
  		Dfprintf(1, stream, "INFO: Data bus width     : %u bits\n", 8*CurMemLuvCore->size/CurMemLuvCore->depth);
  		Dfprintf(1, stream, "INFO: Address bus width  : %.0f bits\n", ceil(log2(CurMemLuvCore->depth)));
  		Dfprintf(1, stream, "INFO: Total Size         : %u bytes [Est. brams %dx36Kb - %dx18Kb]\n", CurMemLuvCore->size, (int)ceil(((double)CurMemLuvCore->size*8/36000)), (int)ceil((double)CurMemLuvCore->size*8/18000));
  		Dfprintf(1, stream, "INFO: ------------- MemLuv Freelist Bit Map info -----------------\n");
  		Dfprintf(1, stream, "INFO: Size of free list  : %d bytes (bitmap array = %d bits)\n", CurMemLuvCore->freelist_depth*sizeof(FREELIST_UINT_T), CurMemLuvCore->freelist_total_bits);
  		Dfprintf(1, stream, "INFO: Register width     : %d bits\n", sizeof(FREELIST_UINT_T)*8);
  		Dfprintf(1, stream, "INFO: Total depth        : %d registers\n", CurMemLuvCore->freelist_depth);
  		Dfprintf(1, stream, "INFO: --------------------------------------------------------------\n\n");
  	}
  #else
  	Dfprintf(1, CurMemLuvConf->dbg_fd, "\nINFO: Statistics N/A: Using glibc malloc\n\n");
  #endif
  #endif
  }
  
  void MemluvDumpCore(MemLuvCore *CurMemLuvCore, memluv_struct_handle_t handle) {
  #ifndef __SYNTHESIS__
  #if SIM_MINIMUM_OVERHEAD==0
  	uint_t i,j,k;
  	uint_t unroll=4;
  	for (k = 0; k < CurMemLuvConf->num_hw_heaps; k++) {
  		/* MemLuvCoreArray automated generated by gen_memluv_wrappers.c, included in global.c */
  		if (handle==THIS)
  			k+=CurMemLuvConf->num_hw_heaps; /* print CurMemLuvCore from argument and exit */
  		else
  			CurMemLuvCore=MemLuvCoreArray[k]; /* print info for all hw heaps */
  		uint_t show_depth = (uint_t)((MEMELUV_DUMP_SHOW_PERCENTAGE/100.0)*CurMemLuvCore->depth);
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "DEBUG: ========================================================================= \n");
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "DEBUG: MemLuv core dump [heap id: %.2d] (print unroll %d) (show depth %u%% [%u-%u])\n", CurMemLuvCore->id, unroll, MEMELUV_DUMP_SHOW_PERCENTAGE, 0, show_depth);
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "DEBUG: ========================================================================= \n");
  		for (j=0;j<unroll;j++) 
  			Dfprintf(2, CurMemLuvConf->dbg_fd, "i/n  x86.addr [hw.addr] :  val (hex)\t");
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "\n");
  		for (j=0;j<unroll;j++)
  			Dfprintf(2, CurMemLuvConf->dbg_fd, "--------------------------------------\t");
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "\n");
  		for (i=0;i<show_depth;i+=unroll) {
  			for (j=0;j<unroll;j++) 
  				Dfprintf(2, CurMemLuvConf->dbg_fd, "%4u %8p [%#08x]:%5u (%#05x)\t", i+j, &CurMemLuvCore->core[i+j],  (uint_t)(&CurMemLuvCore->core[i+j]-(CORE_UINT_T*)CurMemLuvCore->base), CurMemLuvCore->core[i+j], CurMemLuvCore->core[i+j]);
  				//printf("%4d %#08lx [%8p]:%5u (%#05x)\t", i+j, ((uint_t)base)+i+j,  &core[i+j], core[i+j], core[i+j]);
  			Dfprintf(2, CurMemLuvConf->dbg_fd, "\n");
  		}
  		//for (j=0;j<100;j++)
  		//	Dprintf(2, debug aling:ALIGN(%d)=%d req_padding(%d)=%d\n", j, ALIGN(j), j, ReqPadding(j));
  	}
  #endif
  #endif
  }
  
  void MemluvDumpFreeList(MemLuvCore *CurMemLuvCore, memluv_struct_handle_t handle) {
  #ifndef __SYNTHESIS__
  #if SIM_MINIMUM_OVERHEAD==0
  	uint_t i,k;
  	for (k = 0; k < CurMemLuvConf->num_hw_heaps; k++) {
  		/* MemLuvCoreArray automated generated by gen_memluv_wrappers.c, included in global.c */
  		if (handle==THIS)
  			k+=CurMemLuvConf->num_hw_heaps; /* print CurMemLuvCore from argument and exit */
  		else
  			CurMemLuvCore=MemLuvCoreArray[k]; /* print info for all hw heaps */
  		uint_t show_depth = (uint_t)((MEMELUV_DUMP_SHOW_PERCENTAGE/100.0)*CurMemLuvCore->freelist_depth);
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "\nINFO: ------- MemLuv Freelist Bit Map info [heap id: %.2d] (show depth %u%% [%u-%u]) -------\n", CurMemLuvCore->id,  MEMELUV_DUMP_SHOW_PERCENTAGE, 0, show_depth);
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "INFO: Size of free list = %d bytes (bitmap array = %d bits)\n", CurMemLuvCore->freelist_depth*sizeof(FREELIST_UINT_T), CurMemLuvCore->freelist_total_bits);
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "INFO: Register width = %d bits\n", sizeof(FREELIST_UINT_T)*8);
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "INFO: Total depth = %d registers\n", CurMemLuvCore->freelist_depth);
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "INFO: -----------------------------------------------------------------------------------\n");
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "reg id     Bitmap Places     Dec       Hex         Bin\n");
  		Dfprintf(2, CurMemLuvConf->dbg_fd, "-----------------------------------------------------------------------------------------\n");
  		for (i=0; i<=show_depth; i++) {
  			Dfprintf(2, CurMemLuvConf->dbg_fd, "reg_%.6d %.6d-%.6d <-> %.10u[%#8x][0b", i, i*sizeof(FREELIST_UINT_T)*8, (i+1)*sizeof(FREELIST_UINT_T)*8, CurMemLuvCore->freelist[i], CurMemLuvCore->freelist[i]);
  			Uint_tToBin(CurMemLuvCore->freelist[i]);
  			Dfprintf(2, CurMemLuvConf->dbg_fd, "]\n");
  		}
  	}
  #endif
  #endif
  }
  
  uint_t ReqPadding(uint_t size) {
  #ifdef __SYNTHESIS__
  #if MEMLUV_HLS_INLINE == 0
  #pragma AP inline off
  #else
  #pragma AP inline
  #endif
  #endif
      uint_t align;
      align = size % ALIGNMENT;
      if(align != 0) {
          size += (ALIGNMENT - align);
      }
      return size;
  }
  
  void QueryLock(
  		#if HW_DEBUG_MEMLUV==1
  			MemLuvCore *CurMemLuvCore
  		#else
  			void
  		#endif
  		) {
  #if HW_DEBUG_MEMLUV==1
  	uint64_t i;
  	for (i=0; i<1000; i++) {
  		if (CurMemLuvCore->stats.lock==0) {
  			CurMemLuvCore->stats.lock=1;
  			i+=1000;
  		}
  		else
  			i--;
  	}
  #endif
  }
  
  void QueryUnLock(
  		#if HW_DEBUG_MEMLUV==1
  			MemLuvCore *CurMemLuvCore
  		#else
  			void
  		#endif
  		) {
  #if HW_DEBUG_MEMLUV==1
  	if (CurMemLuvCore->stats.lock==1)
  		CurMemLuvCore->stats.lock = 0;
  #endif
  }
  
  uint_t MemluvReportReqFragBytes(MemLuvCore *CurMemLuvCore) {
  #if HW_DEBUG_MEMLUV==1
      uint_t i, max_marked_bit_flag=0;
      CurMemLuvCore->stats.total_request_fragmented_bytes = 0;
      
      Dfprintf(3, CurMemLuvConf->dbg_fd, "DEBUG: Checking bit ...");
      for (i=CurMemLuvCore->freelist_total_bits; i>0; i--) {
          Dfprintf(3, CurMemLuvConf->dbg_fd, "%u ", i);
      
          if (MemluvTestBitFreelist(CurMemLuvCore->freelist, i-1) == 1) {
              if (max_marked_bit_flag==0) {
                  max_marked_bit_flag=1;
                  Dfprintf(3, CurMemLuvConf->dbg_fd, "Found max_marked_bit_flag on %u\n", i);
              }
          }
          else {
              if (max_marked_bit_flag==1)
                  CurMemLuvCore->stats.total_request_fragmented_bytes++;
          }
      }
      Dfprintf(2, CurMemLuvConf->dbg_fd, "DEBUG: total_request_fragmented_bytes=%u\n",
               CurMemLuvCore->stats.total_request_fragmented_bytes);
      
      return CurMemLuvCore->stats.total_request_fragmented_bytes;
  #else
      return 0;
  #endif
  }
  
  