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 * 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
@ -25,6 +25,11 @@
# include <string.h> # include <string.h>
# include <assert.h> # include <assert.h>
#ifdef CHECK_WITH_VALGRIND
static char **string_pool = NULL;
static unsigned string_pool_count = 0;
#endif
StringHeap::StringHeap() StringHeap::StringHeap()
{ {
cell_base_ = 0; cell_base_ = 0;
@ -46,6 +51,12 @@ const char* StringHeap::add(const char*text)
unsigned rem = HEAPCELL - cell_ptr_; unsigned rem = HEAPCELL - cell_ptr_;
if (rem < (len+1)) { if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL); 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_ptr_ = 0;
cell_count_ += 1; cell_count_ += 1;
assert(cell_base_ != 0); 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 unsigned StringHeapLex::add_hit_count() const
{ {
return hit_count_; return hit_count_;
@ -175,4 +202,3 @@ bool operator < (perm_string a, perm_string b)
return false; return false;
} }

View File

@ -1,7 +1,7 @@
#ifndef __StringHeap_H #ifndef __StringHeap_H
#define __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 * 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
@ -104,6 +104,7 @@ class StringHeapLex : private StringHeap {
unsigned add_count() const; unsigned add_count() const;
unsigned add_hit_count() const; unsigned add_hit_count() const;
void cleanup();
private: private:
enum { HASH_SIZE = 4096 }; 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 const struct sfunc_return_type* lookup_sys_func(const char*name);
extern int load_sys_func_table(const char*path); extern int load_sys_func_table(const char*path);
extern void cleanup_sys_func_table();
#endif #endif

View File

@ -1,7 +1,7 @@
#ifndef __config_H /* -*- c++ -*- */ #ifndef __config_H /* -*- c++ -*- */
#define __config_H #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 * 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
@ -50,4 +50,10 @@
# include <inttypes.h> # include <inttypes.h>
#endif #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 */ #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 /* Do not elaborate specify delay paths if this feature is
turned off. */ turned off. */
if (!gn_specify_blocks_flag) if (!gn_specify_blocks_flag) return;
return;
ivl_assert(*this, conditional || (condition==0)); ivl_assert(*this, conditional || (condition==0));
ndelays = delays.size(); ndelays = delays.size();
if (ndelays > 12) if (ndelays > 12) ndelays = 12;
ndelays = 12;
/* Print a warning if we find default and `timescale based /* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */ * 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; NetScope *scope = root_elems[i]->scope;
rc &= rmod->elaborate(des, scope); rc &= rmod->elaborate(des, scope);
delete root_elems[i];
} }
if (rc == false) { if (rc == false) {

View File

@ -1374,3 +1374,17 @@ void reset_lexor()
/* Announce the first file name. */ /* Announce the first file name. */
yylloc.text = set_file_name(strdupnew(vl_file.c_str())); 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. */ /* Count errors detected in flag processing. */
unsigned flag_errors = 0; unsigned flag_errors = 0;
const char*basedir = "."; const char*basedir = strdup(".");
/* /*
* These are the language support control flags. These support which * 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('='); unsigned off = flag.find('=');
if (off > flag.size()) { if (off > flag.size()) {
key = flag; key = flag;
value = ""; value = strdup("");
} else { } else {
key = flag.substr(0, off); key = flag.substr(0, off);
@ -399,6 +399,7 @@ static void read_iconfig_file(const char*ipath)
} }
if (strcmp(buf, "basedir") == 0) { if (strcmp(buf, "basedir") == 0) {
free((char *)basedir);
basedir = strdup(cp); basedir = strdup(cp);
} else if (strcmp(buf, "debug") == 0) { } 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; flags["VPI_MODULE_LIST"] = vpi_module_list;
} else if (strcmp(buf, "out") == 0) { } else if (strcmp(buf, "out") == 0) {
free((char *)flags["-o"]);
flags["-o"] = strdup(cp); flags["-o"] = strdup(cp);
} else if (strcmp(buf, "sys_func") == 0) { } 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); 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; } inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; }
#endif // ! defined(HAVE_TIMES) #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[]) int main(int argc, char*argv[])
{ {
bool help_flag = false; bool help_flag = false;
@ -567,11 +594,11 @@ int main(int argc, char*argv[])
struct tms cycles[5]; struct tms cycles[5];
library_suff.push_back(".v"); library_suff.push_back(strdup(".v"));
vpi_module_list = strdup("system"); vpi_module_list = strdup("system");
flags["VPI_MODULE_LIST"] = vpi_module_list; flags["VPI_MODULE_LIST"] = vpi_module_list;
flags["-o"] = "a.out"; flags["-o"] = strdup("a.out");
min_typ_max_flag = TYP; min_typ_max_flag = TYP;
min_typ_max_warn = 10; min_typ_max_warn = 10;
@ -933,6 +960,8 @@ int main(int argc, char*argv[])
<< endl; << endl;
} }
delete des;
EOC_cleanup();
return 0; return 0;
errors_summary: errors_summary:

View File

@ -114,6 +114,11 @@ NexusSet* NetESelect::nex_input(bool rem_out)
} }
result->add(*tmp); result->add(*tmp);
delete 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; return result;
} }
@ -133,7 +138,23 @@ NexusSet* NetESFunc::nex_input(bool rem_out)
NexusSet* NetESignal::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; 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) for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
result->add(net_->pin(idx).nexus()); result->add(net_->pin(idx).nexus());

49
parse.y
View File

@ -719,6 +719,7 @@ delay_value_simple
description description
: module : module
| udp_primitive | udp_primitive
| config_declaration
| nature_declaration | nature_declaration
| discipline_declaration | discipline_declaration
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' | KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
@ -783,6 +784,54 @@ nature_item
{ delete[] $3; } { 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 drive_strength
: '(' dr_strength0 ',' dr_strength1 ')' : '(' dr_strength0 ',' dr_strength1 ')'
{ $$.str0 = $2.str0; { $$.str0 = $2.str0;

View File

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

View File

@ -2170,6 +2170,7 @@ int pform_parse(const char*path, FILE*file)
error_count += 1; error_count += 1;
} }
destroy_lexor();
return error_count; 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 * 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
@ -46,6 +46,16 @@ struct sfunc_return_type_cell : sfunc_return_type {
static struct sfunc_return_type_cell*sfunc_stack = 0; 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) const struct sfunc_return_type* lookup_sys_func(const char*name)
{ {
/* First, try to find then name in the function stack. */ /* 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", fprintf(stderr, "%s:%s: Unknown type: %s\n",
path, name, stype); path, name, stype);
} }
fclose(fd);
return 0; return 0;
} }

View File

@ -19,9 +19,6 @@
# include "vvp_priv.h" # include "vvp_priv.h"
# include <assert.h> # include <assert.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h> # include <stdlib.h>
# include <string.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. */ /* Omit LPMPART_BI device pin-data(0) drivers. */
# define OMIT_PART_BI_DATA 0x0001 # 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, char* draw_net_input_x(ivl_nexus_t nex,
ivl_nexus_ptr_t omit_ptr, int omit_flags, ivl_nexus_ptr_t omit_ptr, int omit_flags,
struct vvp_nexus_data*nex_data) struct vvp_nexus_data*nex_data)
@ -515,8 +525,6 @@ char* draw_net_input_x(ivl_nexus_t nex,
unsigned idx; unsigned idx;
int level; int level;
unsigned ndrivers = 0; unsigned ndrivers = 0;
static ivl_nexus_ptr_t *drivers = 0x0;
static unsigned adrivers = 0;
const char*resolv_type; const char*resolv_type;

View File

@ -22,9 +22,6 @@
*/ */
# include "vvp_priv.h" # include "vvp_priv.h"
# include <string.h> # include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h> # include <stdlib.h>
# include <math.h> # include <math.h>
# include <assert.h> # include <assert.h>
@ -55,9 +52,6 @@ static int draw_binary_real(ivl_expr_t expr)
{ {
int l, r = -1; 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)) { switch (ivl_expr_opcode(expr)) {
case 'E': case 'E':
case 'N': case 'N':
@ -70,22 +64,8 @@ static int draw_binary_real(ivl_expr_t expr)
case 'A': case 'A':
case 'O': case 'O':
case 'X': case 'X':
{ /* These should be caught in draw_eval_real(). */
struct vector_info vi; assert(0);
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;
}
} }
l = draw_eval_real(ivl_expr_oper1(expr)); 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_out = local_count++;
int lab_r = local_count++; int lab_r = local_count++;
/* If r is NaN, the go out and accept l as result. */ /* 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, " %%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, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
lab_out);
/* If l is NaN, the go out and accept r as result. */ /* 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, " %%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, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
lab_r);
/* If l <= r then go out. */ /* If l <= r then go out. */
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l); 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, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
lab_out);
/* At this point we know we want r as the result. */ /* 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); fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
break; break;
} }
@ -138,16 +122,20 @@ static int draw_binary_real(ivl_expr_t expr)
int lab_out = local_count++; int lab_out = local_count++;
int lab_r = local_count++; int lab_r = local_count++;
/* If r is NaN, the go out and accept l as result. */ /* 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, " %%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, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
lab_out);
/* If l is NaN, the go out and accept r as result. */ /* 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, " %%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, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
lab_r);
/* if l >= r then go out. */ /* if l >= r then go out. */
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r); 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, " %%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); fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
break; break;
} }
@ -508,8 +496,10 @@ static int draw_unary_real(ivl_expr_t expr)
return sub; return sub;
} }
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub); fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n",
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub); ivl_expr_opcode(expr), sub);
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n",
ivl_expr_opcode(expr), sub);
return 0; return 0;
} }
@ -517,6 +507,27 @@ int draw_eval_real(ivl_expr_t expr)
{ {
int res = 0; 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)) { switch (ivl_expr_type(expr)) {
case IVL_EX_BINARY: case IVL_EX_BINARY:

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __vvp_priv_H #ifndef __vvp_priv_H
#define __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 * 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
@ -141,6 +141,7 @@ struct vvp_nexus_data {
* cache it. * cache it.
*/ */
extern const char* draw_net_input(ivl_nexus_t nex); 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 * 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; ivl_drive_t str0, str1;
int level; int level;
int ninp = ivl_logic_pins(lptr) - 1; int ninp;
typedef const char*const_charp; const char **input_strings;
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);
}
}
switch (ivl_logic_type(lptr)) { switch (ivl_logic_type(lptr)) {
case IVL_LO_UDP: case IVL_LO_UDP:
free(input_strings);
draw_udp_in_scope(lptr); draw_udp_in_scope(lptr);
return; return;
@ -706,7 +693,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
/* Skip pullup and pulldown objects. Things that have /* Skip pullup and pulldown objects. Things that have
pull objects as inputs will instead generate the pull objects as inputs will instead generate the
appropriate C<?> symbol. */ appropriate C<?> symbol. */
free(input_strings);
return; return;
case IVL_LO_AND: case IVL_LO_AND:
@ -1862,12 +1848,14 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
fprintf(vvp_out, ">;\n"); fprintf(vvp_out, ">;\n");
break; break;
case IVL_EX_REALNUM: case IVL_EX_REALNUM:
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%#g\n", { char *res = draw_Cr_to_string(ivl_expr_dvalue(pex));
par, ivl_parameter_basename(par), fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; "
ivl_file_table_index(ivl_parameter_file(par)), "value=%#g\n", par, ivl_parameter_basename(par),
ivl_parameter_lineno(par), ivl_file_table_index(ivl_parameter_file(par)),
draw_Cr_to_string(ivl_expr_dvalue(pex)), ivl_parameter_lineno(par), res,
ivl_expr_dvalue(pex)); ivl_expr_dvalue(pex));
free(res);
}
break; break;
default: default:
fprintf(vvp_out, "; parameter type %d unsupported\n", 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; s_vpi_value value;
char *result, *fmtb; char *result, *fmtb;
unsigned int size; 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. */ /* Make sure the width fits in the initial buffer. */
if (width+1 > ini_size) ini_size = width + 1; 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. /* If the default buffer is too small make it big enough.
* *
* This size may not always be correct, but if the default * This should always give enough space. The maximum double
* size is big enough for any practical value then all we * is approximately 1.8*10^308 this means we could need 310
* need to worry about is extra padding and this should work * characters plus the precision. We'll use 320 to give some
* correctly for that case, but since this uses the standard * extra buffer space. The initial buffers size should work
* sprintf() routine we don't know exactly what it will do. */ * 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; size = width + 1;
if (size < 320) size = 320;
size += prec;
if (size > ini_size) result = realloc(result, size*sizeof(char)); if (size > ini_size) result = realloc(result, size*sizeof(char));
sprintf(result, fmtb+1, value.value.real); sprintf(result, fmtb+1, value.value.real);
size = strlen(result) + 1; size = strlen(result) + 1;

View File

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

View File

@ -17,10 +17,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
# include "sys_priv.h"
# include "lxt2_write.h" # include "lxt2_write.h"
# include "vcd_priv.h"
# include "sys_priv.h" # include "sys_priv.h"
# include "vcd_priv.h"
/* /*
* This file contains the implementations of the LXT2 related * This file contains the implementations of the LXT2 related
@ -39,6 +38,29 @@
# include "stringheap.h" # 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 { static enum lxm_optimum_mode_e {
LXM_NONE = 0, LXM_NONE = 0,
LXM_SPACE = 1, LXM_SPACE = 1,
@ -141,30 +163,6 @@ static char *create_full_name(const char *name)
return n; 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) static void show_this_item(struct vcd_info*info)
{ {
s_vpi_value value; s_vpi_value value;
@ -436,8 +434,8 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
static void *close_dumpfile(void) static void *close_dumpfile(void)
{ {
lxt2_wr_close(dump_file); lxt2_wr_close(dump_file);
dump_file = 0; dump_file = NULL;
return 0; return NULL;
} }
static void open_dumpfile(vpiHandle callh) 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 = malloc(sizeof(*info));
info->time.type = vpiSimTime; info->time.type = vpiSimTime;
info->item = item; info->item = item;
info->sym = lxt2_wr_symbol_add(dump_file, ident, info->sym = lxt2_wr_symbol_add(dump_file, ident,
0 /* array rows */, 0 /* array rows */,
vpi_get(vpiLeftRange, item), vpi_get(vpiLeftRange, item),
vpi_get(vpiRightRange, item), vpi_get(vpiRightRange, item),
LXT2_WR_SYM_F_BITS); LXT2_WR_SYM_F_BITS);
info->scheduled = 0; info->scheduled = 0;
cb.time = &info->time; cb.time = &info->time;

View File

@ -18,6 +18,7 @@
*/ */
# include "sys_priv.h" # include "sys_priv.h"
# include "vcd_priv.h"
/* /*
* This file contains the implementations of the VCD related * This file contains the implementations of the VCD related
@ -33,10 +34,29 @@
#ifdef HAVE_MALLOC_H #ifdef HAVE_MALLOC_H
# include <malloc.h> # include <malloc.h>
#endif #endif
# include "vcd_priv.h"
static char*dump_path = 0; static char *dump_path = NULL;
static FILE*dump_file = 0; 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[] = { static const char*units_names[] = {
"s", "s",
@ -47,17 +67,6 @@ static const char*units_names[] = {
"fs" "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 char vcdid[8] = "!";
static void gen_new_vcd_id(void) 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) static char *truncate_bitvec(char *s)
{ {
char l, r; char l, r;
@ -480,7 +481,6 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name)
s_vpi_value val; s_vpi_value val;
/* Get the value and set the dump limit. */ /* Get the value and set the dump limit. */
assert(argv);
val.format = vpiIntVal; val.format = vpiIntVal;
vpi_get_value(vpi_scan(argv), &val); vpi_get_value(vpi_scan(argv), &val);
dump_limit = val.value.integer; 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 vpiNet: type = "wire"; if(0){
case vpiMemoryWord: case vpiMemoryWord:
if (vpi_get(vpiConstantSelect, item) == 0) { if (vpi_get(vpiConstantSelect, item) == 0) {
/* Turn a non-constant array word select into a /* Turn a non-constant array word select into a
* constant word select. */ * constant word select. */
vpiHandle array = vpi_handle(vpiParent, item); vpiHandle array = vpi_handle(vpiParent, item);
PLI_INT32 index = vpi_get(vpiIndex, item); PLI_INT32 index = vpi_get(vpiIndex, item);
item = vpi_handle_by_index(array, index); item = vpi_handle_by_index(array, index);
} }
case vpiIntegerVar: case vpiIntegerVar:
case vpiTimeVar: case vpiTimeVar:
case vpiReg: type = "reg"; } case vpiReg: type = "reg"; }
@ -581,9 +581,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
cb.reason = cbValueChange; cb.reason = cbValueChange;
cb.cb_rtn = variable_cb_1; cb.cb_rtn = variable_cb_1;
info->dmp_next = 0;
info->next = vcd_list; info->next = vcd_list;
info->dmp_next = 0;
vcd_list = info; vcd_list = info;
info->cb = vpi_register_cb(&cb); 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; unsigned use_index = obj->next;
obj->next += 1; obj->next += 1;
if (obj->array->nets) if (obj->array->nets) return obj->array->nets[use_index];
return obj->array->nets[obj->next];
assert(obj->array->vals4); assert(obj->array->vals4 || obj->array->valsr);
if (obj->array->vals_words == 0) if (obj->array->vals_words == 0) array_make_vals_words(obj->array);
array_make_vals_words(obj->array);
return &(obj->array->vals_words[use_index].as_word); 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); assert(arr->nets == 0);
arr->valsr->set_word(address, val); arr->valsr->set_word(address, val);
array_word_change(arr, address);
} }
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned 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_); addr_valid_flag = vector4_to_value(bit, addr_);
if (! addr_valid_flag) if (! addr_valid_flag)
addr_ = arr_->array_count; 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; break;
default: 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) void vvp_fun_arrayport_sa::check_word_change(unsigned long addr)
{ {
if (addr != addr_) if (addr != addr_) return;
return;
vvp_vector4_t bit = array_get_word(arr_, addr_); if (vpi_array_is_real(arr_)) {
net_->send_vec4(bit, 0); 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 { 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 case 0: // Address input
addr_valid_flag = vector4_to_value(bit, *addr); addr_valid_flag = vector4_to_value(bit, *addr);
if (! addr_valid_flag) if (! addr_valid_flag) *addr = arr_->array_count;
*addr = arr_->array_count; if (vpi_array_is_real(arr_)) {
port.ptr()->send_vec4(array_get_word(arr_,*addr), context); 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; break;
default: default:
@ -1269,8 +1281,13 @@ void vvp_fun_arrayport_aa::check_word_change(unsigned long addr)
if (addr != *port_addr) if (addr != *port_addr)
return; return;
vvp_vector4_t bit = array_get_word(arr_, addr); if (vpi_array_is_real(arr_)) {
net_->send_vec4(bit, vthread_get_wt_context()); 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) 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.cb_rtn != 0) {
if (cur->cb_data.value) if (cur->cb_data.value) {
vpip_vec4_get_value(array->vals4->get_word(addr), if (vpi_array_is_real(array)) {
array->vals_width, vpip_real_get_value(array->valsr->get_word(addr),
array->signed_flag, cur->cb_data.value);
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); callback_execute(cur);
prev = cur; prev = cur;

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@ vvp - Icarus Verilog vvp runtime engine
.SH SYNOPSIS .SH SYNOPSIS
.B vvp .B vvp
[-sv] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...] [-nNsvV] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...]
.SH DESCRIPTION .SH DESCRIPTION
.PP .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 It can be used to give the program a more meaningful interface when
running in a non-interactive environment. running in a non-interactive environment.
.TP 8 .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 .B -s
Stop. This will cause the simulation to stop in the beginning, before Stop. This will cause the simulation to stop in the beginning, before
any events are scheduled. This allows the interactive user to get 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) : words_(wor)
{ {
array_ = new double[words_]; 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() vvp_realarray_t::~vvp_realarray_t()