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)
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
|
@ -54,11 +55,15 @@ dep:
|
|||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
%.o: %.cc vpi_config.h
|
||||
$(CXX) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
# Object files for system.vpi
|
||||
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_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 \
|
||||
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
|
||||
* 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,
|
||||
* so we only need a single copy. Some are generic enough they can use
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -21,10 +21,16 @@
|
|||
|
||||
#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;
|
||||
extern struct stringheap_s name_heap;
|
||||
EXTERN struct stringheap_s name_heap;
|
||||
|
||||
struct vcd_names_list_s {
|
||||
struct vcd_names_s *vcd_names_list;
|
||||
|
|
@ -32,21 +38,23 @@ struct vcd_names_list_s {
|
|||
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);
|
||||
|
||||
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 void set_nexus_ident(int nex, const char *id);
|
||||
EXTERN const char*find_nexus_ident(int nex);
|
||||
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. */
|
||||
extern PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name);
|
||||
EXTERN PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name);
|
||||
|
||||
#undef EXTERN
|
||||
|
||||
#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