Merge branch 'master' into vvp-net-out-rework
Conflicts: vvp/array.cc
This commit is contained in:
commit
b5271137cf
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 };
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
14
lexor.lex
14
lexor.lex
|
|
@ -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
37
main.cc
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
49
parse.y
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
1
pform.cc
1
pform.cc
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
14
sys_funcs.cc
14
sys_funcs.cc
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
63
vvp/array.cc
63
vvp/array.cc
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue