Support dump of vpiRealVar objects.
This commit is contained in:
parent
2713694338
commit
83ee6fc818
|
|
@ -18,7 +18,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -57,7 +57,7 @@ all: system.vpi
|
|||
|
||||
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_lxt.o lxt_write.o \
|
||||
sys_lxt.o lxt_write.o vcd_priv.o \
|
||||
mt19937int.o
|
||||
|
||||
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
|
||||
|
|
|
|||
189
vpi/sys_lxt.c
189
vpi/sys_lxt.c
|
|
@ -17,12 +17,13 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
# include "sys_priv.h"
|
||||
# include "lxt_write.h"
|
||||
# include "vcd_priv.h"
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(info->item, &value);
|
||||
lt_emit_value_bit_string(dump_file, info->sym, 0 /* array row */, value.value.str);
|
||||
if (vpi_get(vpiType,info->item) == vpiRealVar) {
|
||||
value.format = vpiRealVal;
|
||||
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
|
||||
*/
|
||||
|
||||
struct vcd_names_s {
|
||||
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);
|
||||
}
|
||||
}
|
||||
struct vcd_names_list_s lxt_tab;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
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)
|
||||
{
|
||||
struct t_cb_data cb;
|
||||
|
|
@ -624,6 +503,34 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
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 vpiNamedBegin: type = "begin"; }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",
|
||||
fullname, depth);
|
||||
|
||||
nskip = sorted_names && fullname
|
||||
&& vcd_names_search(fullname);
|
||||
nskip = 0 != vcd_names_search(&lxt_tab, fullname);
|
||||
|
||||
if (!nskip)
|
||||
vcd_names_add(fullname);
|
||||
vcd_names_add(&lxt_tab, fullname);
|
||||
else
|
||||
vpi_mcd_printf(6,
|
||||
"LXT warning:"
|
||||
|
|
@ -762,7 +668,7 @@ static int sys_dumpvars_calltf(char*name)
|
|||
|
||||
int dep = draw_scope(item);
|
||||
|
||||
vcd_names_sort();
|
||||
vcd_names_sort(&lxt_tab);
|
||||
scan_item(depth, item, 0);
|
||||
|
||||
while (dep--) {
|
||||
|
|
@ -820,6 +726,9 @@ void sys_lxt_register()
|
|||
|
||||
/*
|
||||
* $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
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
|
|
|
|||
188
vpi/sys_vcd.c
188
vpi/sys_vcd.c
|
|
@ -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
|
||||
* 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
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -37,6 +37,8 @@
|
|||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include "vcd_priv.h"
|
||||
|
||||
|
||||
static FILE*dump_file = 0;
|
||||
|
||||
|
|
@ -104,7 +106,12 @@ static void show_this_item(struct vcd_info*info)
|
|||
{
|
||||
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;
|
||||
vpi_get_value(info->item, &value);
|
||||
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
|
||||
*/
|
||||
|
||||
struct vcd_names_s {
|
||||
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);
|
||||
}
|
||||
}
|
||||
struct vcd_names_list_s vcd_tab = { 0 };
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
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)
|
||||
{
|
||||
struct t_cb_data cb;
|
||||
|
|
@ -615,6 +491,38 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
name);
|
||||
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 vpiNamedBegin: type = "begin"; }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",
|
||||
fullname, depth);
|
||||
|
||||
nskip = sorted_names && fullname
|
||||
&& vcd_names_search(fullname);
|
||||
nskip = 0 != vcd_names_search(&vcd_tab, fullname);
|
||||
|
||||
if (!nskip)
|
||||
vcd_names_add(fullname);
|
||||
vcd_names_add(&vcd_tab, fullname);
|
||||
else
|
||||
vpi_mcd_printf(6,
|
||||
"VCD warning:"
|
||||
|
|
@ -794,7 +701,7 @@ static int sys_dumpvars_calltf(char*name)
|
|||
|
||||
int dep = draw_scope(item);
|
||||
|
||||
vcd_names_sort();
|
||||
vcd_names_sort(&vcd_tab);
|
||||
scan_item(depth, item, 0);
|
||||
|
||||
while (dep--) {
|
||||
|
|
@ -852,6 +759,9 @@ void sys_vcd_register()
|
|||
|
||||
/*
|
||||
* $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
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue