Rework vcd id-mapping for scalability
Huge designs have huge sets of unique nexus ids. Use more efficient algorithms to map them and detect aliases.
This commit is contained in:
parent
3cef85b06b
commit
53ec59a97f
|
|
@ -33,6 +33,7 @@ includedir = $(prefix)/include
|
||||||
vpidir = $(libdir)/ivl$(suffix)
|
vpidir = $(libdir)/ivl$(suffix)
|
||||||
|
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
|
CXX = @CXX@
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
|
@ -54,11 +55,15 @@ dep:
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||||
mv $*.d dep
|
mv $*.d dep
|
||||||
|
|
||||||
|
%.o: %.cc vpi_config.h
|
||||||
|
$(CXX) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||||
|
mv $*.d dep
|
||||||
|
|
||||||
# Object files for system.vpi
|
# Object files for system.vpi
|
||||||
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
|
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
|
||||||
sys_finish.o sys_icarus.o sys_plusargs.o sys_random.o sys_random_mti.o \
|
sys_finish.o sys_icarus.o sys_plusargs.o sys_random.o sys_random_mti.o \
|
||||||
sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o \
|
sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o \
|
||||||
sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o \
|
sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o vcd_priv2.o \
|
||||||
mt19937int.o sys_priv.o sdf_lexor.o sdf_parse.o stringheap.o \
|
mt19937int.o sys_priv.o sdf_lexor.o sdf_parse.o stringheap.o \
|
||||||
vams_simparam.o
|
vams_simparam.o
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003-2009 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2003-2010 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
|
||||||
|
|
@ -135,89 +135,6 @@ void vcd_names_sort(struct vcd_names_list_s*tab)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
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 smaller 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 = 0;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nexus_ident_delete()
|
|
||||||
{
|
|
||||||
unsigned idx;
|
|
||||||
|
|
||||||
if (vcd_ids == 0) return;
|
|
||||||
|
|
||||||
for (idx = 0 ; idx < 256; idx++) {
|
|
||||||
struct vcd_id_s *cur, *tmp;
|
|
||||||
for (cur = vcd_ids[idx]; cur; cur = tmp) {
|
|
||||||
tmp = cur->next;
|
|
||||||
free(cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(vcd_ids);
|
|
||||||
vcd_ids = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since the compiletf routines are all the same they are located here,
|
* Since the compiletf routines are all the same they are located here,
|
||||||
* so we only need a single copy. Some are generic enough they can use
|
* so we only need a single copy. Some are generic enough they can use
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __vcd_priv_H
|
#ifndef __vcd_priv_H
|
||||||
#define __vcd_priv_H
|
#define __vcd_priv_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003-2009 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2003-2010 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
|
||||||
|
|
@ -21,10 +21,16 @@
|
||||||
|
|
||||||
#include "vpi_user.h"
|
#include "vpi_user.h"
|
||||||
|
|
||||||
extern int is_escaped_id(const char *name);
|
#ifdef __cplusplus
|
||||||
|
# define EXTERN extern "C"
|
||||||
|
#else
|
||||||
|
# define EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN int is_escaped_id(const char *name);
|
||||||
|
|
||||||
struct vcd_names_s;
|
struct vcd_names_s;
|
||||||
extern struct stringheap_s name_heap;
|
EXTERN struct stringheap_s name_heap;
|
||||||
|
|
||||||
struct vcd_names_list_s {
|
struct vcd_names_list_s {
|
||||||
struct vcd_names_s *vcd_names_list;
|
struct vcd_names_s *vcd_names_list;
|
||||||
|
|
@ -32,21 +38,23 @@ struct vcd_names_list_s {
|
||||||
int listed_names, sorted_names;
|
int listed_names, sorted_names;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void vcd_names_add(struct vcd_names_list_s*tab, const char *name);
|
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,
|
EXTERN const char *vcd_names_search(struct vcd_names_list_s*tab,
|
||||||
const char *key);
|
const char *key);
|
||||||
|
|
||||||
extern void vcd_names_sort(struct vcd_names_list_s*tab);
|
EXTERN void vcd_names_sort(struct vcd_names_list_s*tab);
|
||||||
|
|
||||||
extern void vcd_names_delete();
|
EXTERN void vcd_names_delete();
|
||||||
|
|
||||||
extern const char*find_nexus_ident(int nex);
|
EXTERN const char*find_nexus_ident(int nex);
|
||||||
extern void set_nexus_ident(int nex, const char *id);
|
EXTERN void set_nexus_ident(int nex, const char *id);
|
||||||
|
|
||||||
extern void nexus_ident_delete();
|
EXTERN void nexus_ident_delete();
|
||||||
|
|
||||||
/* The compiletf routines are common for the VCD, LXT and LXT2 dumpers. */
|
/* The compiletf routines are common for the VCD, LXT and LXT2 dumpers. */
|
||||||
extern PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name);
|
EXTERN PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name);
|
||||||
|
|
||||||
|
#undef EXTERN
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "vcd_priv.h"
|
||||||
|
# include <map>
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 smaller VCD files.
|
||||||
|
|
||||||
|
The _vpiNexusId is a private (int) property of IVL simulators.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static std::map<int,const char*> nexus_ident_map;
|
||||||
|
|
||||||
|
extern "C" const char*find_nexus_ident(int nex)
|
||||||
|
{
|
||||||
|
std::map<int,const char*>::const_iterator cur = nexus_ident_map.find(nex);
|
||||||
|
if (cur == nexus_ident_map.end())
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return cur->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void set_nexus_ident(int nex, const char*id)
|
||||||
|
{
|
||||||
|
nexus_ident_map[nex] = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void nexus_ident_delete()
|
||||||
|
{
|
||||||
|
nexus_ident_map.clear();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue