Merge branch 'master' into vvp-net-out-rework

Conflicts:
	vvp/array.cc
This commit is contained in:
Stephen Williams 2009-06-19 22:31:47 -07:00
commit b5271137cf
28 changed files with 410 additions and 205 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2009 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
@ -25,6 +25,11 @@
# include <string.h>
# include <assert.h>
#ifdef CHECK_WITH_VALGRIND
static char **string_pool = NULL;
static unsigned string_pool_count = 0;
#endif
StringHeap::StringHeap()
{
cell_base_ = 0;
@ -46,6 +51,12 @@ const char* StringHeap::add(const char*text)
unsigned rem = HEAPCELL - cell_ptr_;
if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL);
#ifdef CHECK_WITH_VALGRIND
string_pool_count += 1;
string_pool = (char **) realloc(string_pool,
string_pool_count*sizeof(char **));
string_pool[string_pool_count-1] = cell_base_;
#endif
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
@ -80,6 +91,22 @@ StringHeapLex::~StringHeapLex()
{
}
void StringHeapLex::cleanup()
{
#ifdef CHECK_WITH_VALGRIND
for (unsigned idx = 0 ; idx < string_pool_count ; idx += 1) {
free(string_pool[idx]);
}
free(string_pool);
string_pool = NULL;
string_pool_count = 0;
for (unsigned idx = 0 ; idx < HASH_SIZE ; idx += 1) {
hash_table_[idx] = 0;
}
#endif
}
unsigned StringHeapLex::add_hit_count() const
{
return hit_count_;
@ -175,4 +202,3 @@ bool operator < (perm_string a, perm_string b)
return false;
}

View File

@ -1,7 +1,7 @@
#ifndef __StringHeap_H
#define __StringHeap_H
/*
* Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2009 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
@ -104,6 +104,7 @@ class StringHeapLex : private StringHeap {
unsigned add_count() const;
unsigned add_hit_count() const;
void cleanup();
private:
enum { HASH_SIZE = 4096 };

View File

@ -202,5 +202,6 @@ struct sfunc_return_type {
extern const struct sfunc_return_type* lookup_sys_func(const char*name);
extern int load_sys_func_table(const char*path);
extern void cleanup_sys_func_table();
#endif

View File

@ -1,7 +1,7 @@
#ifndef __config_H /* -*- c++ -*- */
#define __config_H
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 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
@ -50,4 +50,10 @@
# include <inttypes.h>
#endif
/*
* Define this if you want to compile vvp with memory freeing and
* special valgrind hooks for the memory pools.
*/
# undef CHECK_WITH_VALGRIND
#endif /* __config_H */

View File

@ -3786,14 +3786,12 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
/* Do not elaborate specify delay paths if this feature is
turned off. */
if (!gn_specify_blocks_flag)
return;
if (!gn_specify_blocks_flag) return;
ivl_assert(*this, conditional || (condition==0));
ndelays = delays.size();
if (ndelays > 12)
ndelays = 12;
if (ndelays > 12) ndelays = 12;
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
@ -4453,6 +4451,7 @@ Design* elaborate(list<perm_string>roots)
NetScope *scope = root_elems[i]->scope;
rc &= rmod->elaborate(des, scope);
delete root_elems[i];
}
if (rc == false) {

View File

@ -1374,3 +1374,17 @@ void reset_lexor()
/* Announce the first file name. */
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
}
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_lexor()
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif
# endif
}

37
main.cc
View File

@ -77,7 +77,7 @@ extern "C" const char*optarg;
/* Count errors detected in flag processing. */
unsigned flag_errors = 0;
const char*basedir = ".";
const char*basedir = strdup(".");
/*
* These are the language support control flags. These support which
@ -280,7 +280,7 @@ static void parm_to_flagmap(const string&flag)
unsigned off = flag.find('=');
if (off > flag.size()) {
key = flag;
value = "";
value = strdup("");
} else {
key = flag.substr(0, off);
@ -399,6 +399,7 @@ static void read_iconfig_file(const char*ipath)
}
if (strcmp(buf, "basedir") == 0) {
free((char *)basedir);
basedir = strdup(cp);
} else if (strcmp(buf, "debug") == 0) {
@ -472,6 +473,7 @@ static void read_iconfig_file(const char*ipath)
flags["VPI_MODULE_LIST"] = vpi_module_list;
} else if (strcmp(buf, "out") == 0) {
free((char *)flags["-o"]);
flags["-o"] = strdup(cp);
} else if (strcmp(buf, "sys_func") == 0) {
@ -529,6 +531,7 @@ static void read_iconfig_file(const char*ipath)
}
}
fclose(ifile);
}
extern Design* elaborate(list <perm_string> root);
@ -555,6 +558,30 @@ inline static void times(struct tms *) { }
inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; }
#endif // ! defined(HAVE_TIMES)
static void EOC_cleanup(void)
{
cleanup_sys_func_table();
for (list<const char*>::iterator suf = library_suff.begin() ;
suf != library_suff.end() ; suf ++ ) {
free((char *)*suf);
}
library_suff.clear();
free((char *) basedir);
free(ivlpp_string);
free(depfile_name);
for (map<string, const char*>::iterator flg = flags.begin() ;
flg != flags.end() ; flg ++ ) {
free((char *)flg->second);
}
flags.clear();
lex_strings.cleanup();
filename_strings.cleanup();
}
int main(int argc, char*argv[])
{
bool help_flag = false;
@ -567,11 +594,11 @@ int main(int argc, char*argv[])
struct tms cycles[5];
library_suff.push_back(".v");
library_suff.push_back(strdup(".v"));
vpi_module_list = strdup("system");
flags["VPI_MODULE_LIST"] = vpi_module_list;
flags["-o"] = "a.out";
flags["-o"] = strdup("a.out");
min_typ_max_flag = TYP;
min_typ_max_warn = 10;
@ -933,6 +960,8 @@ int main(int argc, char*argv[])
<< endl;
}
delete des;
EOC_cleanup();
return 0;
errors_summary:

View File

@ -114,6 +114,11 @@ NexusSet* NetESelect::nex_input(bool rem_out)
}
result->add(*tmp);
delete tmp;
/* See the comment for NetESignal below. */
if (base_) {
cerr << get_fileline() << ": warning: @* is sensitive to all "
"bits in '" << *expr_ << "'." << endl;
}
return result;
}
@ -133,7 +138,23 @@ NexusSet* NetESFunc::nex_input(bool rem_out)
NexusSet* NetESignal::nex_input(bool rem_out)
{
/*
* This is not what I would expect for the various selects (bit,
* part, index, array). This code adds all the bits/array words
* instead of building the appropriate select and then using it
* as the trigger. Other simulators also add everything.
*/
NexusSet*result = new NexusSet;
/* If we have an array index add it to the sensitivity list. */
if (word_) {
NexusSet*tmp;
tmp = word_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
cerr << get_fileline() << ": warning: @* is sensitive to all "
<< net_->array_count() << " words in array '"
<< name() << "'." << endl;
}
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
result->add(net_->pin(idx).nexus());

49
parse.y
View File

@ -719,6 +719,7 @@ delay_value_simple
description
: module
| udp_primitive
| config_declaration
| nature_declaration
| discipline_declaration
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
@ -783,6 +784,54 @@ nature_item
{ delete[] $3; }
;
config_declaration
: K_config IDENTIFIER ';'
K_design lib_cell_identifiers ';'
list_of_config_rule_statements
K_endconfig
{ cerr << @1 << ": sorry: config declarations are not supported and "
"will be skipped." << endl;
delete[] $2;
}
;
lib_cell_identifiers
: /* The BNF implies this can be blank, but I'm not sure exactly what
* this means. */
| lib_cell_identifiers lib_cell_id
;
list_of_config_rule_statements
: /* config rules are optional. */
| list_of_config_rule_statements config_rule_statement
;
config_rule_statement
: K_default K_liblist list_of_libraries ';'
| K_instance hierarchy_identifier K_liblist list_of_libraries ';'
{ delete $2; }
| K_instance hierarchy_identifier K_use lib_cell_id opt_config ';'
{ delete $2; }
| K_cell lib_cell_id K_liblist list_of_libraries ';'
| K_cell lib_cell_id K_use lib_cell_id opt_config ';'
;
opt_config
: /* The use clause takse an optional :config. */
| ':' K_config
lib_cell_id
: IDENTIFIER
{ delete[] $1; }
| IDENTIFIER '.' IDENTIFIER
{ delete[] $1; delete[] $3; }
;
list_of_libraries
: /* A NULL library means use the parents cell library. */
| list_of_libraries IDENTIFIER
{ delete[] $2; }
drive_strength
: '(' dr_strength0 ',' dr_strength1 ')'
{ $$.str0 = $2.str0;

View File

@ -60,6 +60,8 @@ extern void VLerror(const YYLTYPE&loc, const char*msg);
#define yywarn VLwarn
extern void VLwarn(const YYLTYPE&loc, const char*msg);
extern void destroy_lexor();
extern ostream& operator << (ostream&, const YYLTYPE&loc);
extern unsigned error_count, warn_count;

View File

@ -2170,6 +2170,7 @@ int pform_parse(const char*path, FILE*file)
error_count += 1;
}
destroy_lexor();
return error_count;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2009 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
@ -46,6 +46,16 @@ struct sfunc_return_type_cell : sfunc_return_type {
static struct sfunc_return_type_cell*sfunc_stack = 0;
void cleanup_sys_func_table()
{
struct sfunc_return_type_cell *next, *cur = sfunc_stack;
while (cur) {
next = cur->next;
delete cur;
cur = next;
}
}
const struct sfunc_return_type* lookup_sys_func(const char*name)
{
/* First, try to find then name in the function stack. */
@ -186,7 +196,7 @@ int load_sys_func_table(const char*path)
fprintf(stderr, "%s:%s: Unknown type: %s\n",
path, name, stype);
}
fclose(fd);
return 0;
}

View File

@ -19,9 +19,6 @@
# include "vvp_priv.h"
# include <assert.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h>
# include <string.h>

View File

@ -505,6 +505,16 @@ static char* draw_island_port(ivl_island_t island,
/* Omit LPMPART_BI device pin-data(0) drivers. */
# define OMIT_PART_BI_DATA 0x0001
static ivl_nexus_ptr_t *drivers = 0x0;
static unsigned adrivers = 0;
void EOC_cleanup_drivers()
{
free(drivers);
drivers = NULL;
adrivers = 0;
}
char* draw_net_input_x(ivl_nexus_t nex,
ivl_nexus_ptr_t omit_ptr, int omit_flags,
struct vvp_nexus_data*nex_data)
@ -515,8 +525,6 @@ char* draw_net_input_x(ivl_nexus_t nex,
unsigned idx;
int level;
unsigned ndrivers = 0;
static ivl_nexus_ptr_t *drivers = 0x0;
static unsigned adrivers = 0;
const char*resolv_type;

View File

@ -22,9 +22,6 @@
*/
# include "vvp_priv.h"
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h>
# include <math.h>
# include <assert.h>
@ -55,9 +52,6 @@ static int draw_binary_real(ivl_expr_t expr)
{
int l, r = -1;
/* If the opcode is a vector only opcode then the sub expression
* must not be a real expression, so use vector evaluation and
* then convert that result to a real value. */
switch (ivl_expr_opcode(expr)) {
case 'E':
case 'N':
@ -70,22 +64,8 @@ static int draw_binary_real(ivl_expr_t expr)
case 'A':
case 'O':
case 'X':
{
struct vector_info vi;
int res;
const char*sign_flag;
vi = draw_eval_expr(expr, STUFF_OK_XZ);
res = allocate_word();
sign_flag = ivl_expr_signed(expr)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, vi.base, vi.wid);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
clr_vector(vi);
return res;
}
/* These should be caught in draw_eval_real(). */
assert(0);
}
l = draw_eval_real(ivl_expr_oper1(expr));
@ -120,16 +100,20 @@ static int draw_binary_real(ivl_expr_t expr)
int lab_out = local_count++;
int lab_r = local_count++;
/* If r is NaN, the go out and accept l as result. */
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out);
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
lab_out);
/* If l is NaN, the go out and accept r as result. */
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r);
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
lab_r);
/* If l <= r then go out. */
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out);
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
lab_out);
/* At this point we know we want r as the result. */
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r);
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count,
lab_r, l, r);
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
break;
}
@ -138,16 +122,20 @@ static int draw_binary_real(ivl_expr_t expr)
int lab_out = local_count++;
int lab_r = local_count++;
/* If r is NaN, the go out and accept l as result. */
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out);
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
lab_out);
/* If l is NaN, the go out and accept r as result. */
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r);
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
lab_r);
/* if l >= r then go out. */
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out);
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
lab_out);
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r);
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count,
lab_r, l, r);
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
break;
}
@ -508,8 +496,10 @@ static int draw_unary_real(ivl_expr_t expr)
return sub;
}
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub);
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub);
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n",
ivl_expr_opcode(expr), sub);
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n",
ivl_expr_opcode(expr), sub);
return 0;
}
@ -517,6 +507,27 @@ int draw_eval_real(ivl_expr_t expr)
{
int res = 0;
/* If this expression/sub-expression is not real then we need
* to evaluate it as a bit value and then convert the bit based
* result to a real value. This is required to get integer
* division to work correctly. */
if (ivl_expr_value(expr) != IVL_VT_REAL) {
struct vector_info vi;
int res;
const char*sign_flag;
vi = draw_eval_expr(expr, STUFF_OK_XZ);
res = allocate_word();
sign_flag = ivl_expr_signed(expr)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", sign_flag, res,
vi.base, vi.wid);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
clr_vector(vi);
return res;
}
switch (ivl_expr_type(expr)) {
case IVL_EX_BINARY:

View File

@ -140,6 +140,7 @@ int target_design(ivl_design_t des)
}
fclose(vvp_out);
EOC_cleanup_drivers();
return rc + vvp_errors;
}

View File

@ -1,7 +1,7 @@
#ifndef __vvp_priv_H
#define __vvp_priv_H
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 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
@ -141,6 +141,7 @@ struct vvp_nexus_data {
* cache it.
*/
extern const char* draw_net_input(ivl_nexus_t nex);
void EOC_cleanup_drivers();
/*
* See draw_net_input.c for details on draw_net_input_x. (It would be

View File

@ -665,25 +665,12 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
ivl_drive_t str0, str1;
int level;
int ninp = ivl_logic_pins(lptr) - 1;
typedef const char*const_charp;
const_charp*input_strings = calloc(ninp, sizeof(const_charp));
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
if (nex == 0) {
/* Only UDPs can have unconnected inputs. */
assert(ivl_logic_type(lptr) == IVL_LO_UDP);
input_strings[pdx] = 0;
} else {
input_strings[pdx] = draw_net_input(nex);
}
}
int ninp;
const char **input_strings;
switch (ivl_logic_type(lptr)) {
case IVL_LO_UDP:
free(input_strings);
draw_udp_in_scope(lptr);
return;
@ -706,7 +693,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
/* Skip pullup and pulldown objects. Things that have
pull objects as inputs will instead generate the
appropriate C<?> symbol. */
free(input_strings);
return;
case IVL_LO_AND:
@ -1862,12 +1848,14 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
fprintf(vvp_out, ">;\n");
break;
case IVL_EX_REALNUM:
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%#g\n",
par, ivl_parameter_basename(par),
ivl_file_table_index(ivl_parameter_file(par)),
ivl_parameter_lineno(par),
draw_Cr_to_string(ivl_expr_dvalue(pex)),
ivl_expr_dvalue(pex));
{ char *res = draw_Cr_to_string(ivl_expr_dvalue(pex));
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; "
"value=%#g\n", par, ivl_parameter_basename(par),
ivl_file_table_index(ivl_parameter_file(par)),
ivl_parameter_lineno(par), res,
ivl_expr_dvalue(pex));
free(res);
}
break;
default:
fprintf(vvp_out, "; parameter type %d unsupported\n",

View File

@ -263,7 +263,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
s_vpi_value value;
char *result, *fmtb;
unsigned int size;
unsigned int ini_size = 256; /* The initial size of the buffer. */
unsigned int ini_size = 512; /* The initial size of the buffer. */
/* Make sure the width fits in the initial buffer. */
if (width+1 > ini_size) ini_size = width + 1;
@ -488,12 +488,15 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
/* If the default buffer is too small make it big enough.
*
* This size may not always be correct, but if the default
* size is big enough for any practical value then all we
* need to worry about is extra padding and this should work
* correctly for that case, but since this uses the standard
* sprintf() routine we don't know exactly what it will do. */
* This should always give enough space. The maximum double
* is approximately 1.8*10^308 this means we could need 310
* characters plus the precision. We'll use 320 to give some
* extra buffer space. The initial buffers size should work
* for most cases, but to be safe we add the precision to
* the maximum size (think %6.300f when passed 1.2*10^308). */
size = width + 1;
if (size < 320) size = 320;
size += prec;
if (size > ini_size) result = realloc(result, size*sizeof(char));
sprintf(result, fmtb+1, value.value.real);
size = strlen(result) + 1;

View File

@ -17,10 +17,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "sys_priv.h"
# include "lxt_write.h"
# include "vcd_priv.h"
# include "sys_priv.h"
# include "vcd_priv.h"
/*
* This file contains the implementations of the LXT related
@ -39,6 +38,29 @@
# include "stringheap.h"
static char *dump_path = NULL;
static struct lt_trace *dump_file = NULL;
struct vcd_info {
vpiHandle item;
vpiHandle cb;
struct t_vpi_time time;
struct lt_symbol *sym;
struct vcd_info *next;
struct vcd_info *dmp_next;
int scheduled;
};
static struct vcd_info *vcd_list = NULL;
static struct vcd_info *vcd_dmp_list = NULL;
static PLI_UINT64 vcd_cur_time = 0;
static int dump_is_off = 0;
static long dump_limit = 0;
static int dump_is_full = 0;
static int finish_status = 0;
static enum lxm_optimum_mode_e {
LXM_NONE = 0,
LXM_SPACE = 1,
@ -140,30 +162,6 @@ static char *create_full_name(const char *name)
return n;
}
static char *dump_path = 0;
static struct lt_trace *dump_file = 0;
struct vcd_info {
vpiHandle item;
vpiHandle cb;
struct t_vpi_time time;
struct lt_symbol *sym;
struct vcd_info *next;
struct vcd_info *dmp_next;
int scheduled;
};
static struct vcd_info*vcd_list = 0;
static struct vcd_info*vcd_dmp_list = 0;
static PLI_UINT64 vcd_cur_time = 0;
static int dump_is_off = 0;
static long dump_limit = 0;
static int dump_is_full = 0;
static int finish_status = 0;
static void show_this_item(struct vcd_info*info)
{
s_vpi_value value;
@ -434,7 +432,8 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
static void *close_dumpfile(void)
{
lt_close(dump_file);
return (dump_file = NULL);
dump_file = NULL;
return NULL;
}
static void open_dumpfile(vpiHandle callh)
@ -552,7 +551,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiNet: type = "wire"; if(0){
case vpiMemoryWord:
if (vpi_get(vpiConstantSelect, item) == 0) {
if (vpi_get(vpiConstantSelect, item) == 0) {
/* Turn a non-constant array word select into a
* constant word select. */
vpiHandle array = vpi_handle(vpiParent, item);
@ -592,12 +591,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
info->item = item;
info->sym = lt_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item),
LT_SYM_F_BITS);
info->item = item;
info->sym = lt_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item),
LT_SYM_F_BITS);
info->scheduled = 0;
cb.time = &info->time;

View File

@ -17,10 +17,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "sys_priv.h"
# include "lxt2_write.h"
# include "vcd_priv.h"
# include "sys_priv.h"
# include "vcd_priv.h"
/*
* This file contains the implementations of the LXT2 related
@ -39,6 +38,29 @@
# include "stringheap.h"
static char *dump_path = NULL;
static struct lxt2_wr_trace *dump_file = NULL;
struct vcd_info {
vpiHandle item;
vpiHandle cb;
struct t_vpi_time time;
struct lxt2_wr_symbol *sym;
struct vcd_info *next;
struct vcd_info *dmp_next;
int scheduled;
};
static struct vcd_info *vcd_list = NULL;
static struct vcd_info *vcd_dmp_list = NULL;
static PLI_UINT64 vcd_cur_time = 0;
static int dump_is_off = 0;
static long dump_limit = 0;
static int dump_is_full = 0;
static int finish_status = 0;
static enum lxm_optimum_mode_e {
LXM_NONE = 0,
LXM_SPACE = 1,
@ -141,30 +163,6 @@ static char *create_full_name(const char *name)
return n;
}
static char *dump_path = 0;
static struct lxt2_wr_trace *dump_file = 0;
struct vcd_info {
vpiHandle item;
vpiHandle cb;
struct t_vpi_time time;
struct lxt2_wr_symbol *sym;
struct vcd_info *next;
struct vcd_info *dmp_next;
int scheduled;
};
static struct vcd_info*vcd_list = 0;
static struct vcd_info*vcd_dmp_list = 0;
static PLI_UINT64 vcd_cur_time = 0;
static int dump_is_off = 0;
static long dump_limit = 0;
static int dump_is_full = 0;
static int finish_status = 0;
static void show_this_item(struct vcd_info*info)
{
s_vpi_value value;
@ -436,8 +434,8 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
static void *close_dumpfile(void)
{
lxt2_wr_close(dump_file);
dump_file = 0;
return 0;
dump_file = NULL;
return NULL;
}
static void open_dumpfile(vpiHandle callh)
@ -604,12 +602,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
info = malloc(sizeof(*info));
info->time.type = vpiSimTime;
info->item = item;
info->sym = lxt2_wr_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item),
LXT2_WR_SYM_F_BITS);
info->item = item;
info->sym = lxt2_wr_symbol_add(dump_file, ident,
0 /* array rows */,
vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item),
LXT2_WR_SYM_F_BITS);
info->scheduled = 0;
cb.time = &info->time;

View File

@ -18,6 +18,7 @@
*/
# include "sys_priv.h"
# include "vcd_priv.h"
/*
* This file contains the implementations of the VCD related
@ -33,10 +34,29 @@
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include "vcd_priv.h"
static char*dump_path = 0;
static FILE*dump_file = 0;
static char *dump_path = NULL;
static FILE *dump_file = NULL;
struct vcd_info {
vpiHandle item;
vpiHandle cb;
struct t_vpi_time time;
const char *ident;
struct vcd_info *next;
struct vcd_info *dmp_next;
int scheduled;
};
static struct vcd_info *vcd_list = NULL;
static struct vcd_info *vcd_dmp_list = NULL;
static PLI_UINT64 vcd_cur_time = 0;
static int dump_is_off = 0;
static long dump_limit = 0;
static int dump_is_full = 0;
static int finish_status = 0;
static const char*units_names[] = {
"s",
@ -47,17 +67,6 @@ static const char*units_names[] = {
"fs"
};
struct vcd_info {
vpiHandle item;
vpiHandle cb;
struct t_vpi_time time;
const char*ident;
struct vcd_info* next;
struct vcd_info* dmp_next;
int scheduled;
};
static char vcdid[8] = "!";
static void gen_new_vcd_id(void)
@ -76,14 +85,6 @@ static void gen_new_vcd_id(void)
}
}
static struct vcd_info *vcd_list = 0;
static struct vcd_info *vcd_dmp_list = 0;
PLI_UINT64 vcd_cur_time = 0;
static int dump_is_off = 0;
static long dump_limit = 0;
static int dump_is_full = 0;
static int finish_status = 0;
static char *truncate_bitvec(char *s)
{
char l, r;
@ -480,7 +481,6 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name)
s_vpi_value val;
/* Get the value and set the dump limit. */
assert(argv);
val.format = vpiIntVal;
vpi_get_value(vpi_scan(argv), &val);
dump_limit = val.value.integer;
@ -520,13 +520,13 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiNet: type = "wire"; if(0){
case vpiMemoryWord:
if (vpi_get(vpiConstantSelect, item) == 0) {
if (vpi_get(vpiConstantSelect, item) == 0) {
/* Turn a non-constant array word select into a
* constant word select. */
vpiHandle array = vpi_handle(vpiParent, item);
PLI_INT32 index = vpi_get(vpiIndex, item);
item = vpi_handle_by_index(array, index);
}
}
case vpiIntegerVar:
case vpiTimeVar:
case vpiReg: type = "reg"; }
@ -581,9 +581,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
cb.reason = cbValueChange;
cb.cb_rtn = variable_cb_1;
info->next = vcd_list;
info->dmp_next = 0;
info->dmp_next = 0;
info->next = vcd_list;
vcd_list = info;
info->cb = vpi_register_cb(&cb);

View File

@ -599,13 +599,11 @@ static vpiHandle array_iterator_scan(vpiHandle ref, int)
unsigned use_index = obj->next;
obj->next += 1;
if (obj->array->nets)
return obj->array->nets[obj->next];
if (obj->array->nets) return obj->array->nets[use_index];
assert(obj->array->vals4);
assert(obj->array->vals4 || obj->array->valsr);
if (obj->array->vals_words == 0)
array_make_vals_words(obj->array);
if (obj->array->vals_words == 0) array_make_vals_words(obj->array);
return &(obj->array->vals_words[use_index].as_word);
}
@ -850,6 +848,7 @@ void array_set_word(vvp_array_t arr, unsigned address, double val)
assert(arr->nets == 0);
arr->valsr->set_word(address, val);
array_word_change(arr, address);
}
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
@ -1146,7 +1145,11 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit
addr_valid_flag = vector4_to_value(bit, addr_);
if (! addr_valid_flag)
addr_ = arr_->array_count;
port.ptr()->send_vec4(array_get_word(arr_,addr_), 0);
if (vpi_array_is_real(arr_))
port.ptr()->send_real(array_get_word_r(arr_, addr_), 0);
else
port.ptr()->send_vec4(array_get_word(arr_,addr_), 0);
break;
default:
@ -1157,11 +1160,13 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit
void vvp_fun_arrayport_sa::check_word_change(unsigned long addr)
{
if (addr != addr_)
return;
if (addr != addr_) return;
vvp_vector4_t bit = array_get_word(arr_, addr_);
net_->send_vec4(bit, 0);
if (vpi_array_is_real(arr_)) {
net_->send_real(net_->out, array_get_word_r(arr_, addr_), 0);
} else {
net_->send_vec4(net_->out, array_get_word(arr_, addr_), 0);
}
}
class vvp_fun_arrayport_aa : public vvp_fun_arrayport, public automatic_hooks_s {
@ -1243,9 +1248,16 @@ void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit
case 0: // Address input
addr_valid_flag = vector4_to_value(bit, *addr);
if (! addr_valid_flag)
*addr = arr_->array_count;
port.ptr()->send_vec4(array_get_word(arr_,*addr), context);
if (! addr_valid_flag) *addr = arr_->array_count;
if (vpi_array_is_real(arr_)) {
port.ptr()->send_real(port.ptr()->out,
array_get_word_r(arr_, *addr),
context);
} else {
port.ptr()->send_vec4(port.ptr()->out,
array_get_word(arr_, *addr),
context);
}
break;
default:
@ -1269,8 +1281,13 @@ void vvp_fun_arrayport_aa::check_word_change(unsigned long addr)
if (addr != *port_addr)
return;
vvp_vector4_t bit = array_get_word(arr_, addr);
net_->send_vec4(bit, vthread_get_wt_context());
if (vpi_array_is_real(arr_)) {
net_->send_real(net_->out, array_get_word_r(arr_, addr),
vthread_get_wt_context());
} else {
net_->send_vec4(net_->out, array_get_word(arr_, addr),
vthread_get_wt_context());
}
}
static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun)
@ -1306,11 +1323,17 @@ void array_word_change(vvp_array_t array, unsigned long addr)
}
if (cur->cb_data.cb_rtn != 0) {
if (cur->cb_data.value)
vpip_vec4_get_value(array->vals4->get_word(addr),
array->vals_width,
array->signed_flag,
cur->cb_data.value);
if (cur->cb_data.value) {
if (vpi_array_is_real(array)) {
vpip_real_get_value(array->valsr->get_word(addr),
cur->cb_data.value);
} else {
vpip_vec4_get_value(array->vals4->get_word(addr),
array->vals_width,
array->signed_flag,
cur->cb_data.value);
}
}
callback_execute(cur);
prev = cur;

View File

@ -207,6 +207,7 @@ int main(int argc, char*argv[])
FILE *logfile = 0x0;
extern void vpi_set_vlog_info(int, char**);
extern bool stop_is_finish;
extern int stop_is_finish_exit_code;
#ifdef __MINGW32__
/* In the Windows world, we get the first module path
@ -225,7 +226,7 @@ int main(int argc, char*argv[])
/* For non-interactive runs we do not want to run the interactive
* debugger, so make $stop just execute a $finish. */
stop_is_finish = false;
while ((opt = getopt(argc, argv, "+hl:M:m:nsvV")) != EOF) switch (opt) {
while ((opt = getopt(argc, argv, "+hl:M:m:nNsvV")) != EOF) switch (opt) {
case 'h':
fprintf(stderr,
"Usage: vvp [options] input-file [+plusargs...]\n"
@ -236,6 +237,7 @@ int main(int argc, char*argv[])
" -M - Clear VPI module path\n"
" -m module Load vpi module.\n"
" -n Non-interactive ($stop = $finish).\n"
" -N Same as -n, but exit code is 1 instead of 0\n"
" -s $stop right away.\n"
" -v Verbose progress messages.\n"
" -V Print the version information.\n" );
@ -257,6 +259,10 @@ int main(int argc, char*argv[])
case 'n':
stop_is_finish = true;
break;
case 'N':
stop_is_finish = true;
stop_is_finish_exit_code = 1;
break;
case 's':
schedule_stop(0);
break;

View File

@ -44,6 +44,7 @@
struct __vpiScope*stop_current_scope = 0;
bool stop_is_finish; /* When set, $stop acts like $finish (set in main.cc). */
int stop_is_finish_exit_code = 0;
#ifndef USE_READLINE
static char* readline_stub(const char*prompt)
@ -490,6 +491,7 @@ void stop_handler(int rc)
/* The user may be running in a non-interactive environment, so
* they want $stop and <Control-C> to be the same as $finish. */
if (stop_is_finish) {
vpip_set_return_value(stop_is_finish_exit_code);
schedule_finish(0);
return;
}

View File

@ -1002,7 +1002,8 @@ static vpiHandle find_name(const char *name, vpiHandle handle)
if (!strcmp(name, nm)) {
rtn = ref->intern[i];
break;
} else if (vpi_get(vpiType, ref->intern[i]) == vpiMemory) {
} else if (vpi_get(vpiType, ref->intern[i]) == vpiMemory ||
vpi_get(vpiType, ref->intern[i]) == vpiNetArray) {
/* We need to iterate on the words */
vpiHandle word_i, word_h;
word_i = vpi_iterate(vpiMemoryWord, ref->intern[i]);

View File

@ -4,7 +4,7 @@ vvp - Icarus Verilog vvp runtime engine
.SH SYNOPSIS
.B vvp
[-sv] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...]
[-nNsvV] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...]
.SH DESCRIPTION
.PP
@ -46,6 +46,11 @@ This flag makes $stop or a <Control-C> a synonym for $finish.
It can be used to give the program a more meaningful interface when
running in a non-interactive environment.
.TP 8
.B -N
This flag does the same thing as -n, but results in an exit code
of 1 if the stimulation calls $stop. It can be used to indicate a
simulation failure when running a testbench.
.TP 8
.B -s
Stop. This will cause the simulation to stop in the beginning, before
any events are scheduled. This allows the interactive user to get

View File

@ -1422,6 +1422,10 @@ vvp_realarray_t::vvp_realarray_t(unsigned wor)
: words_(wor)
{
array_ = new double[words_];
// Real array words have a default value of zero.
for (unsigned idx = 0 ; idx < words_; idx += 1) {
array_[idx] = 0.0;
}
}
vvp_realarray_t::~vvp_realarray_t()