Support dump of vpiRealVar objects.

This commit is contained in:
steve 2003-02-11 05:21:33 +00:00
parent 2713694338
commit 83ee6fc818
5 changed files with 325 additions and 283 deletions

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.32 2003/01/10 03:06:32 steve Exp $" #ident "$Id: Makefile.in,v 1.33 2003/02/11 05:21:33 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -57,7 +57,7 @@ all: system.vpi
O = sys_table.o sys_deposit.o sys_display.o sys_finish.o sys_plusargs.o \ O = sys_table.o sys_deposit.o sys_display.o sys_finish.o sys_plusargs.o \
sys_random.o sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o \ sys_random.o sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o \
sys_lxt.o lxt_write.o \ sys_lxt.o lxt_write.o vcd_priv.o \
mt19937int.o mt19937int.o
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi

View File

@ -17,12 +17,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: sys_lxt.c,v 1.13 2002/12/21 00:55:58 steve Exp $" #ident "$Id: sys_lxt.c,v 1.14 2003/02/11 05:21:33 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
# include "sys_priv.h" # include "sys_priv.h"
# include "lxt_write.h" # include "lxt_write.h"
# include "vcd_priv.h"
/* /*
* This file contains the implementations of the VCD related * This file contains the implementations of the VCD related
@ -148,9 +149,18 @@ static void show_this_item(struct vcd_info*info)
{ {
s_vpi_value value; s_vpi_value value;
value.format = vpiBinStrVal; if (vpi_get(vpiType,info->item) == vpiRealVar) {
vpi_get_value(info->item, &value); value.format = vpiRealVal;
lt_emit_value_bit_string(dump_file, info->sym, 0 /* array row */, value.value.str); vpi_get_value(info->item, &value);
lt_emit_value_double(dump_file, info->sym, 0, value.value.real);
} else {
value.format = vpiBinStrVal;
vpi_get_value(info->item, &value);
lt_emit_value_bit_string(dump_file, info->sym,
0 /* array row */,
value.value.str);
}
} }
@ -164,73 +174,7 @@ static void show_this_item_x(struct vcd_info*info)
* managed qsorted list of scope names for duplicates bsearching * managed qsorted list of scope names for duplicates bsearching
*/ */
struct vcd_names_s { struct vcd_names_list_s lxt_tab;
const char *name;
struct vcd_names_s *next;
};
static struct vcd_names_s *vcd_names_list;
static const char **vcd_names_sorted;
static int listed_names, sorted_names;
inline static void vcd_names_add(const char *name)
{
struct vcd_names_s *nl = (struct vcd_names_s *)
malloc(sizeof(struct vcd_names_s));
assert(nl);
nl->name = strdup(name);
nl->next = vcd_names_list;
vcd_names_list = nl;
listed_names ++;
}
static int vcd_names_compare(const void *s1, const void *s2)
{
const char *v1 = *(const char **) s1;
const char *v2 = *(const char **) s2;
return strcmp(v1, v2);
}
static const char *vcd_names_search(const char *key)
{
const char **v = (const char **)
bsearch(&key,
vcd_names_sorted, sorted_names,
sizeof(const char *), vcd_names_compare );
return(v ? *v : NULL);
}
static void vcd_names_sort(void)
{
if (listed_names) {
struct vcd_names_s *r;
const char **l;
sorted_names += listed_names;
vcd_names_sorted = (const char **)
realloc(vcd_names_sorted,
sorted_names*(sizeof(const char *)));
assert(vcd_names_sorted);
l = vcd_names_sorted + sorted_names - listed_names;
listed_names = 0;
r = vcd_names_list;
vcd_names_list = 0x0;
while (r) {
struct vcd_names_s *rr = r;
r = rr->next;
*(l++) = rr->name;
free(rr);
}
qsort(vcd_names_sorted, sorted_names,
sizeof(const char **), vcd_names_compare);
}
}
static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */ static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
@ -474,71 +418,6 @@ static int sys_dumpfile_calltf(char*name)
return 0; return 0;
} }
/*
Nexus Id cache
In structural models, many signals refer to the same nexus.
Some structural models also have very many signals. This cache
saves nexus_id - vcd_id pairs, and reuses the vcd_id when a signal
refers to a nexus that is already dumped.
The new signal will be listed as a $var, but no callback
will be installed. This saves considerable CPU time and leads
to smalle VCD files.
The _vpiNexusId is a private (int) property of IVL simulators.
*/
struct vcd_id_s
{
const char *id;
struct vcd_id_s *next;
int nex;
};
static inline unsigned ihash(int nex)
{
unsigned a = nex;
a ^= a>>16;
a ^= a>>8;
return a & 0xff;
}
static struct vcd_id_s **vcd_ids;
inline static const char *find_nexus_ident(int nex)
{
struct vcd_id_s *bucket;
if (!vcd_ids) {
vcd_ids = (struct vcd_id_s **)
calloc(256, sizeof(struct vcd_id_s*));
assert(vcd_ids);
}
bucket = vcd_ids[ihash(nex)];
while (bucket) {
if (nex == bucket->nex)
return bucket->id;
bucket = bucket->next;
}
return 0;
}
inline static void set_nexus_ident(int nex, const char *id)
{
struct vcd_id_s *bucket;
assert(vcd_ids);
bucket = (struct vcd_id_s *) malloc(sizeof(struct vcd_id_s));
bucket->next = vcd_ids[ihash(nex)];
bucket->id = id;
bucket->nex = nex;
vcd_ids[ihash(nex)] = bucket;
}
static void scan_item(unsigned depth, vpiHandle item, int skip) static void scan_item(unsigned depth, vpiHandle item, int skip)
{ {
struct t_cb_data cb; struct t_cb_data cb;
@ -623,7 +502,35 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
} }
break; break;
case vpiRealVar:
if (skip)
break;
name = vpi_get_str(vpiName, item);
ident = create_full_name(name);
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
info->item = item;
info->sym = lt_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiSize, item)-1, 0, LT_SYM_F_DOUBLE);
cb.time = &info->time;
cb.user_data = (char*)info;
cb.value = NULL;
cb.obj = item;
cb.reason = cbValueChange;
cb.cb_rtn = variable_cb;
info->next = vcd_list;
vcd_list = info;
info->cb = vpi_register_cb(&cb);
break;
case vpiModule: type = "module"; if(0){ case vpiModule: type = "module"; if(0){
case vpiNamedBegin: type = "begin"; }if(0){ case vpiNamedBegin: type = "begin"; }if(0){
case vpiTask: type = "task"; }if(0){ case vpiTask: type = "task"; }if(0){
@ -642,11 +549,10 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
" scanning scope %s, %u levels\n", " scanning scope %s, %u levels\n",
fullname, depth); fullname, depth);
nskip = sorted_names && fullname nskip = 0 != vcd_names_search(&lxt_tab, fullname);
&& vcd_names_search(fullname);
if (!nskip) if (!nskip)
vcd_names_add(fullname); vcd_names_add(&lxt_tab, fullname);
else else
vpi_mcd_printf(6, vpi_mcd_printf(6,
"LXT warning:" "LXT warning:"
@ -762,7 +668,7 @@ static int sys_dumpvars_calltf(char*name)
int dep = draw_scope(item); int dep = draw_scope(item);
vcd_names_sort(); vcd_names_sort(&lxt_tab);
scan_item(depth, item, 0); scan_item(depth, item, 0);
while (dep--) { while (dep--) {
@ -820,6 +726,9 @@ void sys_lxt_register()
/* /*
* $Log: sys_lxt.c,v $ * $Log: sys_lxt.c,v $
* Revision 1.14 2003/02/11 05:21:33 steve
* Support dump of vpiRealVar objects.
*
* Revision 1.13 2002/12/21 00:55:58 steve * Revision 1.13 2002/12/21 00:55:58 steve
* The $time system task returns the integer time * The $time system task returns the integer time
* scaled to the local units. Change the internal * scaled to the local units. Change the internal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: sys_vcd.c,v 1.40 2002/12/21 00:55:58 steve Exp $" #ident "$Id: sys_vcd.c,v 1.41 2003/02/11 05:21:33 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -37,6 +37,8 @@
#ifdef HAVE_MALLOC_H #ifdef HAVE_MALLOC_H
# include <malloc.h> # include <malloc.h>
#endif #endif
# include "vcd_priv.h"
static FILE*dump_file = 0; static FILE*dump_file = 0;
@ -104,7 +106,12 @@ static void show_this_item(struct vcd_info*info)
{ {
s_vpi_value value; s_vpi_value value;
if (vpi_get(vpiSize, info->item) == 1) { if (vpi_get(vpiType, info->item) == vpiRealVar) {
value.format = vpiRealVal;
vpi_get_value(info->item, &value);
fprintf(dump_file, "r%.16g %s\n", value.value.real, info->ident);
} else if (vpi_get(vpiSize, info->item) == 1) {
value.format = vpiBinStrVal; value.format = vpiBinStrVal;
vpi_get_value(info->item, &value); vpi_get_value(info->item, &value);
fprintf(dump_file, "%s%s\n", value.value.str, info->ident); fprintf(dump_file, "%s%s\n", value.value.str, info->ident);
@ -132,73 +139,7 @@ static void show_this_item_x(struct vcd_info*info)
* managed qsorted list of scope names for duplicates bsearching * managed qsorted list of scope names for duplicates bsearching
*/ */
struct vcd_names_s { struct vcd_names_list_s vcd_tab = { 0 };
const char *name;
struct vcd_names_s *next;
};
static struct vcd_names_s *vcd_names_list;
static const char **vcd_names_sorted;
static int listed_names, sorted_names;
inline static void vcd_names_add(const char *name)
{
struct vcd_names_s *nl = (struct vcd_names_s *)
malloc(sizeof(struct vcd_names_s));
assert(nl);
nl->name = strdup(name);
nl->next = vcd_names_list;
vcd_names_list = nl;
listed_names ++;
}
static int vcd_names_compare(const void *s1, const void *s2)
{
const char *v1 = *(const char **) s1;
const char *v2 = *(const char **) s2;
return strcmp(v1, v2);
}
static const char *vcd_names_search(const char *key)
{
const char **v = (const char **)
bsearch(&key,
vcd_names_sorted, sorted_names,
sizeof(const char *), vcd_names_compare );
return(v ? *v : NULL);
}
void vcd_names_sort(void)
{
if (listed_names) {
struct vcd_names_s *r;
const char **l;
sorted_names += listed_names;
vcd_names_sorted = (const char **)
realloc(vcd_names_sorted,
sorted_names*(sizeof(const char *)));
assert(vcd_names_sorted);
l = vcd_names_sorted + sorted_names - listed_names;
listed_names = 0;
r = vcd_names_list;
vcd_names_list = 0x0;
while (r) {
struct vcd_names_s *rr = r;
r = rr->next;
*(l++) = rr->name;
free(rr);
}
qsort(vcd_names_sorted, sorted_names,
sizeof(const char **), vcd_names_compare);
}
}
static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */ static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
@ -465,71 +406,6 @@ static int sys_dumpfile_calltf(char*name)
return 0; return 0;
} }
/*
Nexus Id cache
In structural models, many signals refer to the same nexus.
Some structural models also have very many signals. This cache
saves nexus_id - vcd_id pairs, and reuses the vcd_id when a signal
refers to a nexus that is already dumped.
The new signal will be listed as a $var, but no callback
will be installed. This saves considerable CPU time and leads
to smalle VCD files.
The _vpiNexusId is a private (int) property of IVL simulators.
*/
struct vcd_id_s
{
const char *id;
struct vcd_id_s *next;
int nex;
};
static inline unsigned ihash(int nex)
{
unsigned a = nex;
a ^= a>>16;
a ^= a>>8;
return a & 0xff;
}
static struct vcd_id_s **vcd_ids;
inline static const char *find_nexus_ident(int nex)
{
struct vcd_id_s *bucket;
if (!vcd_ids) {
vcd_ids = (struct vcd_id_s **)
calloc(256, sizeof(struct vcd_id_s*));
assert(vcd_ids);
}
bucket = vcd_ids[ihash(nex)];
while (bucket) {
if (nex == bucket->nex)
return bucket->id;
bucket = bucket->next;
}
return 0;
}
inline static void set_nexus_ident(int nex, const char *id)
{
struct vcd_id_s *bucket;
assert(vcd_ids);
bucket = (struct vcd_id_s *) malloc(sizeof(struct vcd_id_s));
bucket->next = vcd_ids[ihash(nex)];
bucket->id = id;
bucket->nex = nex;
vcd_ids[ihash(nex)] = bucket;
}
static void scan_item(unsigned depth, vpiHandle item, int skip) static void scan_item(unsigned depth, vpiHandle item, int skip)
{ {
struct t_cb_data cb; struct t_cb_data cb;
@ -614,7 +490,39 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
type, vpi_get(vpiSize, item), ident, type, vpi_get(vpiSize, item), ident,
name); name);
break; break;
case vpiRealVar:
if (skip)
break;
/* Declare the variable in the VCD file. */
name = vpi_get_str(vpiName, item);
ident = strdup(vcdid);
gen_new_vcd_id();
fprintf(dump_file, "$var real 1 %s %s $end\n",
ident, name);
/* Add a callback for the variable. */
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
info->item = item;
info->ident = ident;
cb.time = &info->time;
cb.user_data = (char*)info;
cb.value = NULL;
cb.obj = item;
cb.reason = cbValueChange;
cb.cb_rtn = variable_cb;
info->next = vcd_list;
vcd_list = info;
info->cb = vpi_register_cb(&cb);
break;
case vpiModule: type = "module"; if(0){ case vpiModule: type = "module"; if(0){
case vpiNamedBegin: type = "begin"; }if(0){ case vpiNamedBegin: type = "begin"; }if(0){
case vpiTask: type = "task"; }if(0){ case vpiTask: type = "task"; }if(0){
@ -633,11 +541,10 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
" scanning scope %s, %u levels\n", " scanning scope %s, %u levels\n",
fullname, depth); fullname, depth);
nskip = sorted_names && fullname nskip = 0 != vcd_names_search(&vcd_tab, fullname);
&& vcd_names_search(fullname);
if (!nskip) if (!nskip)
vcd_names_add(fullname); vcd_names_add(&vcd_tab, fullname);
else else
vpi_mcd_printf(6, vpi_mcd_printf(6,
"VCD warning:" "VCD warning:"
@ -794,7 +701,7 @@ static int sys_dumpvars_calltf(char*name)
int dep = draw_scope(item); int dep = draw_scope(item);
vcd_names_sort(); vcd_names_sort(&vcd_tab);
scan_item(depth, item, 0); scan_item(depth, item, 0);
while (dep--) { while (dep--) {
@ -852,6 +759,9 @@ void sys_vcd_register()
/* /*
* $Log: sys_vcd.c,v $ * $Log: sys_vcd.c,v $
* Revision 1.41 2003/02/11 05:21:33 steve
* Support dump of vpiRealVar objects.
*
* Revision 1.40 2002/12/21 00:55:58 steve * Revision 1.40 2002/12/21 00:55:58 steve
* The $time system task returns the integer time * The $time system task returns the integer time
* scaled to the local units. Change the internal * scaled to the local units. Change the internal

173
vpi/vcd_priv.c Normal file
View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vcd_priv.c,v 1.1 2003/02/11 05:21:33 steve Exp $"
#endif
# include "vcd_priv.h"
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
struct vcd_names_s {
const char *name;
struct vcd_names_s *next;
};
void vcd_names_add(struct vcd_names_list_s*tab, const char *name)
{
struct vcd_names_s *nl = (struct vcd_names_s *)
malloc(sizeof(struct vcd_names_s));
assert(nl);
nl->name = strdup(name);
nl->next = tab->vcd_names_list;
tab->vcd_names_list = nl;
tab->listed_names ++;
}
static int vcd_names_compare(const void *s1, const void *s2)
{
const char *v1 = *(const char **) s1;
const char *v2 = *(const char **) s2;
return strcmp(v1, v2);
}
const char *vcd_names_search(struct vcd_names_list_s*tab, const char *key)
{
const char **v;
if (tab->vcd_names_sorted == 0)
return 0;
v = (const char **) bsearch(&key,
tab->vcd_names_sorted, tab->sorted_names,
sizeof(const char *), vcd_names_compare );
return(v ? *v : NULL);
}
void vcd_names_sort(struct vcd_names_list_s*tab)
{
if (tab->listed_names) {
struct vcd_names_s *r;
const char **l;
tab->sorted_names += tab->listed_names;
tab->vcd_names_sorted = (const char **)
realloc(tab->vcd_names_sorted,
tab->sorted_names*(sizeof(const char *)));
assert(tab->vcd_names_sorted);
l = tab->vcd_names_sorted + tab->sorted_names - tab->listed_names;
tab->listed_names = 0;
r = tab->vcd_names_list;
tab->vcd_names_list = 0x0;
while (r) {
struct vcd_names_s *rr = r;
r = rr->next;
*(l++) = rr->name;
free(rr);
}
qsort(tab->vcd_names_sorted, tab->sorted_names,
sizeof(const char **), vcd_names_compare);
}
}
/*
Nexus Id cache
In structural models, many signals refer to the same nexus.
Some structural models also have very many signals. This cache
saves nexus_id - vcd_id pairs, and reuses the vcd_id when a signal
refers to a nexus that is already dumped.
The new signal will be listed as a $var, but no callback
will be installed. This saves considerable CPU time and leads
to smalle VCD files.
The _vpiNexusId is a private (int) property of IVL simulators.
*/
struct vcd_id_s
{
const char *id;
struct vcd_id_s *next;
int nex;
};
static inline unsigned ihash(int nex)
{
unsigned a = nex;
a ^= a>>16;
a ^= a>>8;
return a & 0xff;
}
static struct vcd_id_s **vcd_ids;
const char *find_nexus_ident(int nex)
{
struct vcd_id_s *bucket;
if (!vcd_ids) {
vcd_ids = (struct vcd_id_s **)
calloc(256, sizeof(struct vcd_id_s*));
assert(vcd_ids);
}
bucket = vcd_ids[ihash(nex)];
while (bucket) {
if (nex == bucket->nex)
return bucket->id;
bucket = bucket->next;
}
return 0;
}
void set_nexus_ident(int nex, const char *id)
{
struct vcd_id_s *bucket;
assert(vcd_ids);
bucket = (struct vcd_id_s *) malloc(sizeof(struct vcd_id_s));
bucket->next = vcd_ids[ihash(nex)];
bucket->id = id;
bucket->nex = nex;
vcd_ids[ihash(nex)] = bucket;
}
/*
* $Log: vcd_priv.c,v $
* Revision 1.1 2003/02/11 05:21:33 steve
* Support dump of vpiRealVar objects.
*
*/

50
vpi/vcd_priv.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef __vcd_priv_H
#define __vcd_priv_H
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vcd_priv.h,v 1.1 2003/02/11 05:21:33 steve Exp $"
#endif
struct vcd_names_s;
struct vcd_names_list_s {
struct vcd_names_s *vcd_names_list;
const char **vcd_names_sorted;
int listed_names, sorted_names;
};
extern void vcd_names_add(struct vcd_names_list_s*tab, const char *name);
extern const char *vcd_names_search(struct vcd_names_list_s*tab,
const char *key);
extern void vcd_names_sort(struct vcd_names_list_s*tab);
extern const char*find_nexus_ident(int nex);
extern void set_nexus_ident(int nex, const char *id);
/*
* $Log: vcd_priv.h,v $
* Revision 1.1 2003/02/11 05:21:33 steve
* Support dump of vpiRealVar objects.
*
*/
#endif