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