On Thu, May 1, 2008 at 12:43 AM, Tristan Gingold <[EMAIL PROTECTED]> wrote:
> On Wed, Apr 30, 2008 at 11:22:47AM -0400, Pascal Giard wrote:
>  > Hello list,
>  >  I'm attempting to track a memory leak i'm experiencing with GHDL.
>  >
>  > Context:
>  > - I'm using the VHPI interface in order to get and put signals.
>  > - I'm using POSIX shared memory and semaphores.
>  >
>  > I've fully tested my POSIX shm/sem code in separate client/server
>  > applications. There isn't any memleaks.
>  > However, running the code with GHDL clearly shows memleaks
>  > (non-scientifically shown by `top`).
>  >
>  > Running a long simulation with GHDL doesn't show any memleak.
>  >
>  > I'm requesting help in order to track this memleak issue.
>  > Please see valgrind report in attachment.
>
>  Hum, maybe you are simply discarding the result of vpi_register_cb ?

Hmmm... What would be the good thing to do?
I here attached my vpi shared library for you to check in case it's useful.

-Pascal
-- 
Homepage (http://organact.mine.nu)
Debian GNU/Linux (http://www.debian.org)
LACIME: École de technologie supérieure (http://lacime.etsmtl.ca)
/* tb_vpi.cpp - this file is part of GHDL_CORBA
 *
 * Copyright (C) 2007-2008 Pascal Giard
 *
 * Author: Pascal Giard <[EMAIL PROTECTED]>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This file is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <string.h>
#include <vpi_user.h>

#include "unpipc.h"
#include "common.h"

sem_t *csem;
sem_t *ssem;
vector<unsigned char> sdata; /* server data */
vector<unsigned char> cdata; /* client data */
firPortsIn portsIn;
firPortsOut portsOut;
char *shmread_ptr;
char *shmwrite_ptr;

/* Prototypes */
void beginrun (int);
int readonlysync (struct t_cb_data*);
int endofsim (struct t_cb_data*);
int endofcompile (struct t_cb_data*);
void my_handle_register();
void initfir();
void updateinput();
void updateoutput();

int readonlysync (struct t_cb_data* cbdata)
{
  /* Synch/clk/init variable */
  static bool rising_edge = true;
  static bool init = true;
  static bool firstpass = true;

  // Clock synch, ReadOnlySynch callback is called on each event be it
  // rising_edge or falling_edge. Write/read data only on rising_edge.
  if(!rising_edge) {
    rising_edge = !rising_edge;
    return 0;
  } else {
    if( init ) {
      initfir();
      init = false;
    } else {
      // On first pass the input hasn't been update yet so skip output update.
      if( firstpass ) {
        firstpass = false;
      } else {
        updateoutput();
      }
      updateinput(); 
    }
  }
  rising_edge = !rising_edge;

  return 0;
}

void beginrun (int runtime)
{
  s_vpi_time time_s, tt;
  s_cb_data cbdata;

  tt.type = vpiSimTime;
  vpi_get_time(NULL, &tt);

  cbdata.reason = cbReadOnlySynch;
  time_s.low = runtime + tt.low; // Warning: No effect!
  time_s.high = 0;
  time_s.type = vpiSimTime;

  cbdata.time = &time_s;
  cbdata.obj  = 0;
  cbdata.value = 0;

  cbdata.cb_rtn    = &readonlysync;
  if(vpi_register_cb(&cbdata) == NULL)
    vpi_printf ("cannot register ReadOnlySync call back\n");
}

int endofsim (struct t_cb_data* cbdata)
{
  s_vpi_time cur_time;
  cur_time.type = vpiSimTime;
  vpi_get_time(NULL, &cur_time);

  vpi_printf("VPI: End of simulation at %d ns.\n", cur_time.low);

  return 0;
}

/* FIXME: Not going thru the design breaks the behavior, why?! */
int endofcompile (struct t_cb_data* cbdata)
{
  vpiHandle top_iter;
  vpiHandle module_h;
  vpiHandle net_iter;
  vpiHandle net_h;
  const char *mod_name;
  s_vpi_value val;
  s_vpi_value valset;

  /* get TOP Module handle */
  top_iter = vpi_iterate (vpiModule, NULL);
  module_h = vpi_scan (top_iter);
  
  /* get TOP Module Nets */
  net_iter = vpi_iterate (vpiNet, module_h);
  if (net_iter != NULL)
    {
      while ((net_h = vpi_scan (net_iter)) != NULL)
	{
          val.format = vpiBinStrVal;
          valset.format = vpiBinStrVal;

	  mod_name = vpi_get_str (vpiFullName, net_h);
          vpi_get_value(net_h, &val);
	  printf ("%s starts as %s\n",
                  mod_name, val.value.str);
	}
    }
  else
    {
      printf("No Nets\n");
    }

  beginrun(10);

  return 0;
}

void my_handle_register()
{
  s_cb_data cbend;
  s_cb_data cbstart;

  cbend.reason = cbEndOfCompile;
  cbend.cb_rtn = &endofcompile;
  cbend.user_data = NULL;
  if (vpi_register_cb (&cbend) == NULL)
    vpi_printf ("cannot register EndOfCompile call back\n");

  cbstart.reason = cbEndOfSimulation;
  cbstart.cb_rtn = &endofsim;
  cbstart.user_data = NULL;
  if (vpi_register_cb (&cbstart) == NULL)
    vpi_printf ("VPI: Cannot register EndOfSimulation call back\n");

  // Init semaphore and shared memory
  ssem = sem_open("/ghdlserver", O_RDWR);
  if( ssem == SEM_FAILED ) perror("sem_open");
  csem = sem_open("/ghdlclient", 0);
  if( csem == SEM_FAILED ) perror("sem_open");

  shmread_ptr = shmgetaddr("/ghdlclient", O_RDONLY, PROT_READ);
  shmwrite_ptr = shmgetaddr("/ghdlserver", O_RDWR, PROT_READ|PROT_WRITE);

  // Init ports
  portsIn.dataIn = 0;
  portsIn.select = 0;
  portsIn.ordre = 0;
  portsOut.dataOut = 0;

  cdata = serialize_ports_in(portsIn);
  sdata = serialize_ports_out(portsOut);
}

/* Initialize FIR filter, requires 1 cycle on reset. */
void initfir()
{
  vpiHandle top_iter, module_h, net_iter;
  vpiHandle net_h;
  const char *mod_name;
  s_vpi_value valset;

  /* get TOP Module handle */
  top_iter = vpi_iterate (vpiModule, NULL);
  module_h = vpi_scan (top_iter);

  /* get TOP Module Nets */
  net_iter = vpi_iterate (vpiNet, module_h);
  if (net_iter != NULL)
    {
      while ((net_h = vpi_scan (net_iter)) != NULL)
	{
          /* Signal value formats, only vpiBinStrVal is implemented */
          valset.format = vpiBinStrVal;
          /* Get signal name */
	  mod_name = vpi_get_str (vpiFullName, net_h);

          /* Set next signal value */
          if( !strcmp(mod_name, "tb.reset") ) {
            valset.value.str = (char *)"1";
            vpi_put_value(net_h, &valset, NULL, vpiNoDelay);
          }
	}
    }
  else
    {
      printf("initfir: No Nets\n");
    }
}

/* Update FIR filter inputs using data received via CORBA, available in shm */
void updateinput()
{
  vpiHandle top_iter;
  vpiHandle module_h;
  vpiHandle net_iter;
  vpiHandle net_h;
  const char *mod_name;
  s_vpi_value val;
  s_vpi_value valset;

  /* Temporary dataIn holder */
  char dataInStr[32*4];

  /* FIXME: How come this doesn't work?? */
//   if( sem_wait(csem) == -1 )
//     err_quit("Error: Semaphore client doesn't exists!\n");

  /* Wait for client data */
  while( sem_trywait(csem) == -1 ) usleep(100);

  /* Get data from client */
  shmread(cdata, shmread_ptr);
  unserialize_ports_in(cdata, portsIn);

  /* get TOP Module handle */
  top_iter = vpi_iterate (vpiModule, NULL);
  module_h = vpi_scan (top_iter);

  /* get TOP Module Nets */
  net_iter = vpi_iterate (vpiNet, module_h);
  if (net_iter != NULL)
    {
      while ((net_h = vpi_scan (net_iter)) != NULL)
	{
          /* Signal value formats, only vpiBinStrVal is implemented */
          val.format = vpiBinStrVal;
          valset.format = vpiBinStrVal;

	  mod_name = vpi_get_str (vpiFullName, net_h);

          /* Get signal value */
          vpi_get_value(net_h, &val);

          /* Set next signal value */
          if( !strcmp(mod_name, "tb.reset") ) {
            valset.value.str = (char *)"0";
            vpi_put_value(net_h, &valset, NULL, vpiNoDelay);

          } else if( !strcmp(mod_name, "tb.ce") ) {
            if( !strcmp(val.value.str, "U") ) {
              valset.value.str = (char *)"1";
              vpi_put_value(net_h, &valset, NULL, vpiNoDelay);
            }

          } else if( !strcmp(mod_name, "tb.ordre") ) { // Unused for now
            if( !strcmp(val.value.str, "UUUUUUUU") ) {
              valset.value.str = (char *)"00000000";
              vpi_put_value(net_h, &valset, NULL, vpiNoDelay);
            }

          } else if( !strcmp(mod_name, "tb.data") ) {
            int2bin(portsIn.dataIn, dataInStr,32);
            valset.value.str = dataInStr;
            vpi_put_value(net_h, &valset, NULL, vpiNoDelay);

          } else if( !strcmp(mod_name, "tb.runcfg") ) {
            int2bin(portsIn.select, valset.value.str, 1);
            vpi_put_value(net_h, &valset, NULL, vpiNoDelay);
          }
	}
    }
  else
    {
      printf("No Nets\n");
    }
}

/* Put FIR filter result in shm for CORBA server to pick up. */
void updateoutput()
{
  vpiHandle top_iter;
  vpiHandle module_h;
  vpiHandle net_iter;
  vpiHandle net_h;
  const char *mod_name;
  s_vpi_value val;

  /* get TOP Module handle */
  top_iter = vpi_iterate (vpiModule, NULL);
  module_h = vpi_scan (top_iter);

  /* get TOP Module Nets */
  net_iter = vpi_iterate (vpiNet, module_h);
  if (net_iter != NULL)
    {
      while ((net_h = vpi_scan (net_iter)) != NULL)
	{
          /* Signal value formats, only vpiBinStrVal is implemented */
          val.format = vpiBinStrVal;

	  mod_name = vpi_get_str (vpiFullName, net_h);

          /* Get signal value */
          vpi_get_value(net_h, &val);

          /* Update server data with result */
          if( !strcmp(mod_name, "tb.result") ) {
            portsOut.dataOut = bin2int(val.value.str);
            sdata = serialize_ports_out(portsOut);
            shmwrite(sdata, shmwrite_ptr);
          }
	}
    }
  else
    {
      printf("No Nets\n");
    }

  /* Post semaphore to client */
  Sem_post(ssem);
}

void (*vlog_startup_routines[]) () =
{
  my_handle_register,
  0
};
_______________________________________________
Ghdl-discuss mailing list
[email protected]
https://mail.gna.org/listinfo/ghdl-discuss

Reply via email to