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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -25,6 +25,11 @@
|
|||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
static char **string_pool = NULL;
|
||||
static unsigned string_pool_count = 0;
|
||||
#endif
|
||||
|
||||
StringHeap::StringHeap()
|
||||
{
|
||||
cell_base_ = 0;
|
||||
|
|
@ -46,6 +51,12 @@ const char* StringHeap::add(const char*text)
|
|||
unsigned rem = HEAPCELL - cell_ptr_;
|
||||
if (rem < (len+1)) {
|
||||
cell_base_ = (char*)malloc(HEAPCELL);
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
string_pool_count += 1;
|
||||
string_pool = (char **) realloc(string_pool,
|
||||
string_pool_count*sizeof(char **));
|
||||
string_pool[string_pool_count-1] = cell_base_;
|
||||
#endif
|
||||
cell_ptr_ = 0;
|
||||
cell_count_ += 1;
|
||||
assert(cell_base_ != 0);
|
||||
|
|
@ -80,6 +91,22 @@ StringHeapLex::~StringHeapLex()
|
|||
{
|
||||
}
|
||||
|
||||
void StringHeapLex::cleanup()
|
||||
{
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
for (unsigned idx = 0 ; idx < string_pool_count ; idx += 1) {
|
||||
free(string_pool[idx]);
|
||||
}
|
||||
free(string_pool);
|
||||
string_pool = NULL;
|
||||
string_pool_count = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < HASH_SIZE ; idx += 1) {
|
||||
hash_table_[idx] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned StringHeapLex::add_hit_count() const
|
||||
{
|
||||
return hit_count_;
|
||||
|
|
@ -175,4 +202,3 @@ bool operator < (perm_string a, perm_string b)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __StringHeap_H
|
||||
#define __StringHeap_H
|
||||
/*
|
||||
* Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -104,6 +104,7 @@ class StringHeapLex : private StringHeap {
|
|||
|
||||
unsigned add_count() const;
|
||||
unsigned add_hit_count() const;
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
enum { HASH_SIZE = 4096 };
|
||||
|
|
|
|||
|
|
@ -202,5 +202,6 @@ struct sfunc_return_type {
|
|||
|
||||
extern const struct sfunc_return_type* lookup_sys_func(const char*name);
|
||||
extern int load_sys_func_table(const char*path);
|
||||
extern void cleanup_sys_func_table();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __config_H /* -*- c++ -*- */
|
||||
#define __config_H
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -50,4 +50,10 @@
|
|||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define this if you want to compile vvp with memory freeing and
|
||||
* special valgrind hooks for the memory pools.
|
||||
*/
|
||||
# undef CHECK_WITH_VALGRIND
|
||||
|
||||
#endif /* __config_H */
|
||||
|
|
|
|||
|
|
@ -3786,14 +3786,12 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* Do not elaborate specify delay paths if this feature is
|
||||
turned off. */
|
||||
if (!gn_specify_blocks_flag)
|
||||
return;
|
||||
if (!gn_specify_blocks_flag) return;
|
||||
|
||||
ivl_assert(*this, conditional || (condition==0));
|
||||
|
||||
ndelays = delays.size();
|
||||
if (ndelays > 12)
|
||||
ndelays = 12;
|
||||
if (ndelays > 12) ndelays = 12;
|
||||
|
||||
/* Print a warning if we find default and `timescale based
|
||||
* delays in the design, since this is likely an error. */
|
||||
|
|
@ -4453,6 +4451,7 @@ Design* elaborate(list<perm_string>roots)
|
|||
NetScope *scope = root_elems[i]->scope;
|
||||
|
||||
rc &= rmod->elaborate(des, scope);
|
||||
delete root_elems[i];
|
||||
}
|
||||
|
||||
if (rc == false) {
|
||||
|
|
|
|||
14
lexor.lex
14
lexor.lex
|
|
@ -1374,3 +1374,17 @@ void reset_lexor()
|
|||
/* Announce the first file name. */
|
||||
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||
*/
|
||||
void destroy_lexor()
|
||||
{
|
||||
# ifdef FLEX_SCANNER
|
||||
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
|
||||
yylex_destroy();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
|
|
|||
37
main.cc
37
main.cc
|
|
@ -77,7 +77,7 @@ extern "C" const char*optarg;
|
|||
/* Count errors detected in flag processing. */
|
||||
unsigned flag_errors = 0;
|
||||
|
||||
const char*basedir = ".";
|
||||
const char*basedir = strdup(".");
|
||||
|
||||
/*
|
||||
* These are the language support control flags. These support which
|
||||
|
|
@ -280,7 +280,7 @@ static void parm_to_flagmap(const string&flag)
|
|||
unsigned off = flag.find('=');
|
||||
if (off > flag.size()) {
|
||||
key = flag;
|
||||
value = "";
|
||||
value = strdup("");
|
||||
|
||||
} else {
|
||||
key = flag.substr(0, off);
|
||||
|
|
@ -399,6 +399,7 @@ static void read_iconfig_file(const char*ipath)
|
|||
}
|
||||
|
||||
if (strcmp(buf, "basedir") == 0) {
|
||||
free((char *)basedir);
|
||||
basedir = strdup(cp);
|
||||
|
||||
} else if (strcmp(buf, "debug") == 0) {
|
||||
|
|
@ -472,6 +473,7 @@ static void read_iconfig_file(const char*ipath)
|
|||
flags["VPI_MODULE_LIST"] = vpi_module_list;
|
||||
|
||||
} else if (strcmp(buf, "out") == 0) {
|
||||
free((char *)flags["-o"]);
|
||||
flags["-o"] = strdup(cp);
|
||||
|
||||
} else if (strcmp(buf, "sys_func") == 0) {
|
||||
|
|
@ -529,6 +531,7 @@ static void read_iconfig_file(const char*ipath)
|
|||
|
||||
}
|
||||
}
|
||||
fclose(ifile);
|
||||
}
|
||||
|
||||
extern Design* elaborate(list <perm_string> root);
|
||||
|
|
@ -555,6 +558,30 @@ inline static void times(struct tms *) { }
|
|||
inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; }
|
||||
#endif // ! defined(HAVE_TIMES)
|
||||
|
||||
static void EOC_cleanup(void)
|
||||
{
|
||||
cleanup_sys_func_table();
|
||||
|
||||
for (list<const char*>::iterator suf = library_suff.begin() ;
|
||||
suf != library_suff.end() ; suf ++ ) {
|
||||
free((char *)*suf);
|
||||
}
|
||||
library_suff.clear();
|
||||
|
||||
free((char *) basedir);
|
||||
free(ivlpp_string);
|
||||
free(depfile_name);
|
||||
|
||||
for (map<string, const char*>::iterator flg = flags.begin() ;
|
||||
flg != flags.end() ; flg ++ ) {
|
||||
free((char *)flg->second);
|
||||
}
|
||||
flags.clear();
|
||||
|
||||
lex_strings.cleanup();
|
||||
filename_strings.cleanup();
|
||||
}
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
bool help_flag = false;
|
||||
|
|
@ -567,11 +594,11 @@ int main(int argc, char*argv[])
|
|||
|
||||
struct tms cycles[5];
|
||||
|
||||
library_suff.push_back(".v");
|
||||
library_suff.push_back(strdup(".v"));
|
||||
|
||||
vpi_module_list = strdup("system");
|
||||
flags["VPI_MODULE_LIST"] = vpi_module_list;
|
||||
flags["-o"] = "a.out";
|
||||
flags["-o"] = strdup("a.out");
|
||||
min_typ_max_flag = TYP;
|
||||
min_typ_max_warn = 10;
|
||||
|
||||
|
|
@ -933,6 +960,8 @@ int main(int argc, char*argv[])
|
|||
<< endl;
|
||||
}
|
||||
|
||||
delete des;
|
||||
EOC_cleanup();
|
||||
return 0;
|
||||
|
||||
errors_summary:
|
||||
|
|
|
|||
|
|
@ -114,6 +114,11 @@ NexusSet* NetESelect::nex_input(bool rem_out)
|
|||
}
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
/* See the comment for NetESignal below. */
|
||||
if (base_) {
|
||||
cerr << get_fileline() << ": warning: @* is sensitive to all "
|
||||
"bits in '" << *expr_ << "'." << endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +138,23 @@ NexusSet* NetESFunc::nex_input(bool rem_out)
|
|||
|
||||
NexusSet* NetESignal::nex_input(bool rem_out)
|
||||
{
|
||||
/*
|
||||
* This is not what I would expect for the various selects (bit,
|
||||
* part, index, array). This code adds all the bits/array words
|
||||
* instead of building the appropriate select and then using it
|
||||
* as the trigger. Other simulators also add everything.
|
||||
*/
|
||||
NexusSet*result = new NexusSet;
|
||||
/* If we have an array index add it to the sensitivity list. */
|
||||
if (word_) {
|
||||
NexusSet*tmp;
|
||||
tmp = word_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
cerr << get_fileline() << ": warning: @* is sensitive to all "
|
||||
<< net_->array_count() << " words in array '"
|
||||
<< name() << "'." << endl;
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
|
||||
result->add(net_->pin(idx).nexus());
|
||||
|
||||
|
|
|
|||
49
parse.y
49
parse.y
|
|
@ -719,6 +719,7 @@ delay_value_simple
|
|||
description
|
||||
: module
|
||||
| udp_primitive
|
||||
| config_declaration
|
||||
| nature_declaration
|
||||
| discipline_declaration
|
||||
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
|
||||
|
|
@ -783,6 +784,54 @@ nature_item
|
|||
{ delete[] $3; }
|
||||
;
|
||||
|
||||
config_declaration
|
||||
: K_config IDENTIFIER ';'
|
||||
K_design lib_cell_identifiers ';'
|
||||
list_of_config_rule_statements
|
||||
K_endconfig
|
||||
{ cerr << @1 << ": sorry: config declarations are not supported and "
|
||||
"will be skipped." << endl;
|
||||
delete[] $2;
|
||||
}
|
||||
;
|
||||
|
||||
lib_cell_identifiers
|
||||
: /* The BNF implies this can be blank, but I'm not sure exactly what
|
||||
* this means. */
|
||||
| lib_cell_identifiers lib_cell_id
|
||||
;
|
||||
|
||||
list_of_config_rule_statements
|
||||
: /* config rules are optional. */
|
||||
| list_of_config_rule_statements config_rule_statement
|
||||
;
|
||||
|
||||
config_rule_statement
|
||||
: K_default K_liblist list_of_libraries ';'
|
||||
| K_instance hierarchy_identifier K_liblist list_of_libraries ';'
|
||||
{ delete $2; }
|
||||
| K_instance hierarchy_identifier K_use lib_cell_id opt_config ';'
|
||||
{ delete $2; }
|
||||
| K_cell lib_cell_id K_liblist list_of_libraries ';'
|
||||
| K_cell lib_cell_id K_use lib_cell_id opt_config ';'
|
||||
;
|
||||
|
||||
opt_config
|
||||
: /* The use clause takse an optional :config. */
|
||||
| ':' K_config
|
||||
|
||||
lib_cell_id
|
||||
: IDENTIFIER
|
||||
{ delete[] $1; }
|
||||
| IDENTIFIER '.' IDENTIFIER
|
||||
{ delete[] $1; delete[] $3; }
|
||||
;
|
||||
|
||||
list_of_libraries
|
||||
: /* A NULL library means use the parents cell library. */
|
||||
| list_of_libraries IDENTIFIER
|
||||
{ delete[] $2; }
|
||||
|
||||
drive_strength
|
||||
: '(' dr_strength0 ',' dr_strength1 ')'
|
||||
{ $$.str0 = $2.str0;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ extern void VLerror(const YYLTYPE&loc, const char*msg);
|
|||
#define yywarn VLwarn
|
||||
extern void VLwarn(const YYLTYPE&loc, const char*msg);
|
||||
|
||||
extern void destroy_lexor();
|
||||
|
||||
extern ostream& operator << (ostream&, const YYLTYPE&loc);
|
||||
|
||||
extern unsigned error_count, warn_count;
|
||||
|
|
|
|||
1
pform.cc
1
pform.cc
|
|
@ -2170,6 +2170,7 @@ int pform_parse(const char*path, FILE*file)
|
|||
error_count += 1;
|
||||
}
|
||||
|
||||
destroy_lexor();
|
||||
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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -46,6 +46,16 @@ struct sfunc_return_type_cell : sfunc_return_type {
|
|||
|
||||
static struct sfunc_return_type_cell*sfunc_stack = 0;
|
||||
|
||||
void cleanup_sys_func_table()
|
||||
{
|
||||
struct sfunc_return_type_cell *next, *cur = sfunc_stack;
|
||||
while (cur) {
|
||||
next = cur->next;
|
||||
delete cur;
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
|
||||
const struct sfunc_return_type* lookup_sys_func(const char*name)
|
||||
{
|
||||
/* First, try to find then name in the function stack. */
|
||||
|
|
@ -186,7 +196,7 @@ int load_sys_func_table(const char*path)
|
|||
fprintf(stderr, "%s:%s: Unknown type: %s\n",
|
||||
path, name, stype);
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@
|
|||
|
||||
# include "vvp_priv.h"
|
||||
# include <assert.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -505,6 +505,16 @@ static char* draw_island_port(ivl_island_t island,
|
|||
/* Omit LPMPART_BI device pin-data(0) drivers. */
|
||||
# define OMIT_PART_BI_DATA 0x0001
|
||||
|
||||
static ivl_nexus_ptr_t *drivers = 0x0;
|
||||
static unsigned adrivers = 0;
|
||||
|
||||
void EOC_cleanup_drivers()
|
||||
{
|
||||
free(drivers);
|
||||
drivers = NULL;
|
||||
adrivers = 0;
|
||||
}
|
||||
|
||||
char* draw_net_input_x(ivl_nexus_t nex,
|
||||
ivl_nexus_ptr_t omit_ptr, int omit_flags,
|
||||
struct vvp_nexus_data*nex_data)
|
||||
|
|
@ -515,8 +525,6 @@ char* draw_net_input_x(ivl_nexus_t nex,
|
|||
unsigned idx;
|
||||
int level;
|
||||
unsigned ndrivers = 0;
|
||||
static ivl_nexus_ptr_t *drivers = 0x0;
|
||||
static unsigned adrivers = 0;
|
||||
|
||||
const char*resolv_type;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,6 @@
|
|||
*/
|
||||
# include "vvp_priv.h"
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <math.h>
|
||||
# include <assert.h>
|
||||
|
|
@ -55,9 +52,6 @@ static int draw_binary_real(ivl_expr_t expr)
|
|||
{
|
||||
int l, r = -1;
|
||||
|
||||
/* If the opcode is a vector only opcode then the sub expression
|
||||
* must not be a real expression, so use vector evaluation and
|
||||
* then convert that result to a real value. */
|
||||
switch (ivl_expr_opcode(expr)) {
|
||||
case 'E':
|
||||
case 'N':
|
||||
|
|
@ -70,22 +64,8 @@ static int draw_binary_real(ivl_expr_t expr)
|
|||
case 'A':
|
||||
case 'O':
|
||||
case 'X':
|
||||
{
|
||||
struct vector_info vi;
|
||||
int res;
|
||||
const char*sign_flag;
|
||||
|
||||
vi = draw_eval_expr(expr, STUFF_OK_XZ);
|
||||
res = allocate_word();
|
||||
sign_flag = ivl_expr_signed(expr)? "/s" : "";
|
||||
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
|
||||
sign_flag, res, vi.base, vi.wid);
|
||||
|
||||
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
|
||||
|
||||
clr_vector(vi);
|
||||
return res;
|
||||
}
|
||||
/* These should be caught in draw_eval_real(). */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
l = draw_eval_real(ivl_expr_oper1(expr));
|
||||
|
|
@ -120,16 +100,20 @@ static int draw_binary_real(ivl_expr_t expr)
|
|||
int lab_out = local_count++;
|
||||
int lab_r = local_count++;
|
||||
/* If r is NaN, the go out and accept l as result. */
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out);
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||
lab_out);
|
||||
/* If l is NaN, the go out and accept r as result. */
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r);
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||
lab_r);
|
||||
/* If l <= r then go out. */
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out);
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
|
||||
lab_out);
|
||||
/* At this point we know we want r as the result. */
|
||||
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r);
|
||||
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count,
|
||||
lab_r, l, r);
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
||||
break;
|
||||
}
|
||||
|
|
@ -138,16 +122,20 @@ static int draw_binary_real(ivl_expr_t expr)
|
|||
int lab_out = local_count++;
|
||||
int lab_r = local_count++;
|
||||
/* If r is NaN, the go out and accept l as result. */
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out);
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||
lab_out);
|
||||
/* If l is NaN, the go out and accept r as result. */
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r);
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||
lab_r);
|
||||
/* if l >= r then go out. */
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out);
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r);
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
|
||||
lab_out);
|
||||
|
||||
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r);
|
||||
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count,
|
||||
lab_r, l, r);
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
||||
break;
|
||||
}
|
||||
|
|
@ -508,8 +496,10 @@ static int draw_unary_real(ivl_expr_t expr)
|
|||
return sub;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub);
|
||||
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub);
|
||||
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n",
|
||||
ivl_expr_opcode(expr), sub);
|
||||
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n",
|
||||
ivl_expr_opcode(expr), sub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -517,6 +507,27 @@ int draw_eval_real(ivl_expr_t expr)
|
|||
{
|
||||
int res = 0;
|
||||
|
||||
/* If this expression/sub-expression is not real then we need
|
||||
* to evaluate it as a bit value and then convert the bit based
|
||||
* result to a real value. This is required to get integer
|
||||
* division to work correctly. */
|
||||
if (ivl_expr_value(expr) != IVL_VT_REAL) {
|
||||
struct vector_info vi;
|
||||
int res;
|
||||
const char*sign_flag;
|
||||
|
||||
vi = draw_eval_expr(expr, STUFF_OK_XZ);
|
||||
res = allocate_word();
|
||||
sign_flag = ivl_expr_signed(expr)? "/s" : "";
|
||||
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", sign_flag, res,
|
||||
vi.base, vi.wid);
|
||||
|
||||
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
|
||||
|
||||
clr_vector(vi);
|
||||
return res;
|
||||
}
|
||||
|
||||
switch (ivl_expr_type(expr)) {
|
||||
|
||||
case IVL_EX_BINARY:
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ int target_design(ivl_design_t des)
|
|||
}
|
||||
|
||||
fclose(vvp_out);
|
||||
EOC_cleanup_drivers();
|
||||
|
||||
return rc + vvp_errors;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __vvp_priv_H
|
||||
#define __vvp_priv_H
|
||||
/*
|
||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -141,6 +141,7 @@ struct vvp_nexus_data {
|
|||
* cache it.
|
||||
*/
|
||||
extern const char* draw_net_input(ivl_nexus_t nex);
|
||||
void EOC_cleanup_drivers();
|
||||
|
||||
/*
|
||||
* See draw_net_input.c for details on draw_net_input_x. (It would be
|
||||
|
|
|
|||
|
|
@ -665,25 +665,12 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
|||
ivl_drive_t str0, str1;
|
||||
|
||||
int level;
|
||||
int ninp = ivl_logic_pins(lptr) - 1;
|
||||
typedef const char*const_charp;
|
||||
const_charp*input_strings = calloc(ninp, sizeof(const_charp));
|
||||
|
||||
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
|
||||
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
|
||||
if (nex == 0) {
|
||||
/* Only UDPs can have unconnected inputs. */
|
||||
assert(ivl_logic_type(lptr) == IVL_LO_UDP);
|
||||
input_strings[pdx] = 0;
|
||||
} else {
|
||||
input_strings[pdx] = draw_net_input(nex);
|
||||
}
|
||||
}
|
||||
int ninp;
|
||||
const char **input_strings;
|
||||
|
||||
switch (ivl_logic_type(lptr)) {
|
||||
|
||||
case IVL_LO_UDP:
|
||||
free(input_strings);
|
||||
draw_udp_in_scope(lptr);
|
||||
return;
|
||||
|
||||
|
|
@ -706,7 +693,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
|||
/* Skip pullup and pulldown objects. Things that have
|
||||
pull objects as inputs will instead generate the
|
||||
appropriate C<?> symbol. */
|
||||
free(input_strings);
|
||||
return;
|
||||
|
||||
case IVL_LO_AND:
|
||||
|
|
@ -1862,12 +1848,14 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
fprintf(vvp_out, ">;\n");
|
||||
break;
|
||||
case IVL_EX_REALNUM:
|
||||
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%#g\n",
|
||||
par, ivl_parameter_basename(par),
|
||||
ivl_file_table_index(ivl_parameter_file(par)),
|
||||
ivl_parameter_lineno(par),
|
||||
draw_Cr_to_string(ivl_expr_dvalue(pex)),
|
||||
ivl_expr_dvalue(pex));
|
||||
{ char *res = draw_Cr_to_string(ivl_expr_dvalue(pex));
|
||||
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; "
|
||||
"value=%#g\n", par, ivl_parameter_basename(par),
|
||||
ivl_file_table_index(ivl_parameter_file(par)),
|
||||
ivl_parameter_lineno(par), res,
|
||||
ivl_expr_dvalue(pex));
|
||||
free(res);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(vvp_out, "; parameter type %d unsupported\n",
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
|||
s_vpi_value value;
|
||||
char *result, *fmtb;
|
||||
unsigned int size;
|
||||
unsigned int ini_size = 256; /* The initial size of the buffer. */
|
||||
unsigned int ini_size = 512; /* The initial size of the buffer. */
|
||||
|
||||
/* Make sure the width fits in the initial buffer. */
|
||||
if (width+1 > ini_size) ini_size = width + 1;
|
||||
|
|
@ -488,12 +488,15 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
|||
|
||||
/* If the default buffer is too small make it big enough.
|
||||
*
|
||||
* This size may not always be correct, but if the default
|
||||
* size is big enough for any practical value then all we
|
||||
* need to worry about is extra padding and this should work
|
||||
* correctly for that case, but since this uses the standard
|
||||
* sprintf() routine we don't know exactly what it will do. */
|
||||
* This should always give enough space. The maximum double
|
||||
* is approximately 1.8*10^308 this means we could need 310
|
||||
* characters plus the precision. We'll use 320 to give some
|
||||
* extra buffer space. The initial buffers size should work
|
||||
* for most cases, but to be safe we add the precision to
|
||||
* the maximum size (think %6.300f when passed 1.2*10^308). */
|
||||
size = width + 1;
|
||||
if (size < 320) size = 320;
|
||||
size += prec;
|
||||
if (size > ini_size) result = realloc(result, size*sizeof(char));
|
||||
sprintf(result, fmtb+1, value.value.real);
|
||||
size = strlen(result) + 1;
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "sys_priv.h"
|
||||
# include "lxt_write.h"
|
||||
# include "vcd_priv.h"
|
||||
# include "sys_priv.h"
|
||||
# include "vcd_priv.h"
|
||||
|
||||
/*
|
||||
* This file contains the implementations of the LXT related
|
||||
|
|
@ -39,6 +38,29 @@
|
|||
# include "stringheap.h"
|
||||
|
||||
|
||||
static char *dump_path = NULL;
|
||||
static struct lt_trace *dump_file = NULL;
|
||||
|
||||
struct vcd_info {
|
||||
vpiHandle item;
|
||||
vpiHandle cb;
|
||||
struct t_vpi_time time;
|
||||
struct lt_symbol *sym;
|
||||
struct vcd_info *next;
|
||||
struct vcd_info *dmp_next;
|
||||
int scheduled;
|
||||
};
|
||||
|
||||
|
||||
static struct vcd_info *vcd_list = NULL;
|
||||
static struct vcd_info *vcd_dmp_list = NULL;
|
||||
static PLI_UINT64 vcd_cur_time = 0;
|
||||
static int dump_is_off = 0;
|
||||
static long dump_limit = 0;
|
||||
static int dump_is_full = 0;
|
||||
static int finish_status = 0;
|
||||
|
||||
|
||||
static enum lxm_optimum_mode_e {
|
||||
LXM_NONE = 0,
|
||||
LXM_SPACE = 1,
|
||||
|
|
@ -140,30 +162,6 @@ static char *create_full_name(const char *name)
|
|||
return n;
|
||||
}
|
||||
|
||||
|
||||
static char *dump_path = 0;
|
||||
static struct lt_trace *dump_file = 0;
|
||||
|
||||
struct vcd_info {
|
||||
vpiHandle item;
|
||||
vpiHandle cb;
|
||||
struct t_vpi_time time;
|
||||
struct lt_symbol *sym;
|
||||
struct vcd_info *next;
|
||||
struct vcd_info *dmp_next;
|
||||
int scheduled;
|
||||
};
|
||||
|
||||
|
||||
static struct vcd_info*vcd_list = 0;
|
||||
static struct vcd_info*vcd_dmp_list = 0;
|
||||
static PLI_UINT64 vcd_cur_time = 0;
|
||||
static int dump_is_off = 0;
|
||||
static long dump_limit = 0;
|
||||
static int dump_is_full = 0;
|
||||
static int finish_status = 0;
|
||||
|
||||
|
||||
static void show_this_item(struct vcd_info*info)
|
||||
{
|
||||
s_vpi_value value;
|
||||
|
|
@ -434,7 +432,8 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
|
|||
static void *close_dumpfile(void)
|
||||
{
|
||||
lt_close(dump_file);
|
||||
return (dump_file = NULL);
|
||||
dump_file = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void open_dumpfile(vpiHandle callh)
|
||||
|
|
@ -552,7 +551,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
case vpiNet: type = "wire"; if(0){
|
||||
case vpiMemoryWord:
|
||||
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||
/* Turn a non-constant array word select into a
|
||||
* constant word select. */
|
||||
vpiHandle array = vpi_handle(vpiParent, item);
|
||||
|
|
@ -592,12 +591,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
info = malloc(sizeof(*info));
|
||||
|
||||
info->time.type = vpiSimTime;
|
||||
info->item = item;
|
||||
info->sym = lt_symbol_add(dump_file, ident,
|
||||
0 /* array rows */,
|
||||
vpi_get(vpiLeftRange, item),
|
||||
vpi_get(vpiRightRange, item),
|
||||
LT_SYM_F_BITS);
|
||||
info->item = item;
|
||||
info->sym = lt_symbol_add(dump_file, ident,
|
||||
0 /* array rows */,
|
||||
vpi_get(vpiLeftRange, item),
|
||||
vpi_get(vpiRightRange, item),
|
||||
LT_SYM_F_BITS);
|
||||
info->scheduled = 0;
|
||||
|
||||
cb.time = &info->time;
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "sys_priv.h"
|
||||
# include "lxt2_write.h"
|
||||
# include "vcd_priv.h"
|
||||
# include "sys_priv.h"
|
||||
# include "vcd_priv.h"
|
||||
|
||||
/*
|
||||
* This file contains the implementations of the LXT2 related
|
||||
|
|
@ -39,6 +38,29 @@
|
|||
# include "stringheap.h"
|
||||
|
||||
|
||||
static char *dump_path = NULL;
|
||||
static struct lxt2_wr_trace *dump_file = NULL;
|
||||
|
||||
struct vcd_info {
|
||||
vpiHandle item;
|
||||
vpiHandle cb;
|
||||
struct t_vpi_time time;
|
||||
struct lxt2_wr_symbol *sym;
|
||||
struct vcd_info *next;
|
||||
struct vcd_info *dmp_next;
|
||||
int scheduled;
|
||||
};
|
||||
|
||||
|
||||
static struct vcd_info *vcd_list = NULL;
|
||||
static struct vcd_info *vcd_dmp_list = NULL;
|
||||
static PLI_UINT64 vcd_cur_time = 0;
|
||||
static int dump_is_off = 0;
|
||||
static long dump_limit = 0;
|
||||
static int dump_is_full = 0;
|
||||
static int finish_status = 0;
|
||||
|
||||
|
||||
static enum lxm_optimum_mode_e {
|
||||
LXM_NONE = 0,
|
||||
LXM_SPACE = 1,
|
||||
|
|
@ -141,30 +163,6 @@ static char *create_full_name(const char *name)
|
|||
return n;
|
||||
}
|
||||
|
||||
|
||||
static char *dump_path = 0;
|
||||
static struct lxt2_wr_trace *dump_file = 0;
|
||||
|
||||
struct vcd_info {
|
||||
vpiHandle item;
|
||||
vpiHandle cb;
|
||||
struct t_vpi_time time;
|
||||
struct lxt2_wr_symbol *sym;
|
||||
struct vcd_info *next;
|
||||
struct vcd_info *dmp_next;
|
||||
int scheduled;
|
||||
};
|
||||
|
||||
|
||||
static struct vcd_info*vcd_list = 0;
|
||||
static struct vcd_info*vcd_dmp_list = 0;
|
||||
static PLI_UINT64 vcd_cur_time = 0;
|
||||
static int dump_is_off = 0;
|
||||
static long dump_limit = 0;
|
||||
static int dump_is_full = 0;
|
||||
static int finish_status = 0;
|
||||
|
||||
|
||||
static void show_this_item(struct vcd_info*info)
|
||||
{
|
||||
s_vpi_value value;
|
||||
|
|
@ -436,8 +434,8 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
|
|||
static void *close_dumpfile(void)
|
||||
{
|
||||
lxt2_wr_close(dump_file);
|
||||
dump_file = 0;
|
||||
return 0;
|
||||
dump_file = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void open_dumpfile(vpiHandle callh)
|
||||
|
|
@ -604,12 +602,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
info = malloc(sizeof(*info));
|
||||
|
||||
info->time.type = vpiSimTime;
|
||||
info->item = item;
|
||||
info->sym = lxt2_wr_symbol_add(dump_file, ident,
|
||||
0 /* array rows */,
|
||||
vpi_get(vpiLeftRange, item),
|
||||
vpi_get(vpiRightRange, item),
|
||||
LXT2_WR_SYM_F_BITS);
|
||||
info->item = item;
|
||||
info->sym = lxt2_wr_symbol_add(dump_file, ident,
|
||||
0 /* array rows */,
|
||||
vpi_get(vpiLeftRange, item),
|
||||
vpi_get(vpiRightRange, item),
|
||||
LXT2_WR_SYM_F_BITS);
|
||||
info->scheduled = 0;
|
||||
|
||||
cb.time = &info->time;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "sys_priv.h"
|
||||
# include "vcd_priv.h"
|
||||
|
||||
/*
|
||||
* This file contains the implementations of the VCD related
|
||||
|
|
@ -33,10 +34,29 @@
|
|||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include "vcd_priv.h"
|
||||
|
||||
static char*dump_path = 0;
|
||||
static FILE*dump_file = 0;
|
||||
static char *dump_path = NULL;
|
||||
static FILE *dump_file = NULL;
|
||||
|
||||
struct vcd_info {
|
||||
vpiHandle item;
|
||||
vpiHandle cb;
|
||||
struct t_vpi_time time;
|
||||
const char *ident;
|
||||
struct vcd_info *next;
|
||||
struct vcd_info *dmp_next;
|
||||
int scheduled;
|
||||
};
|
||||
|
||||
|
||||
static struct vcd_info *vcd_list = NULL;
|
||||
static struct vcd_info *vcd_dmp_list = NULL;
|
||||
static PLI_UINT64 vcd_cur_time = 0;
|
||||
static int dump_is_off = 0;
|
||||
static long dump_limit = 0;
|
||||
static int dump_is_full = 0;
|
||||
static int finish_status = 0;
|
||||
|
||||
|
||||
static const char*units_names[] = {
|
||||
"s",
|
||||
|
|
@ -47,17 +67,6 @@ static const char*units_names[] = {
|
|||
"fs"
|
||||
};
|
||||
|
||||
struct vcd_info {
|
||||
vpiHandle item;
|
||||
vpiHandle cb;
|
||||
struct t_vpi_time time;
|
||||
const char*ident;
|
||||
struct vcd_info* next;
|
||||
struct vcd_info* dmp_next;
|
||||
int scheduled;
|
||||
};
|
||||
|
||||
|
||||
static char vcdid[8] = "!";
|
||||
|
||||
static void gen_new_vcd_id(void)
|
||||
|
|
@ -76,14 +85,6 @@ static void gen_new_vcd_id(void)
|
|||
}
|
||||
}
|
||||
|
||||
static struct vcd_info *vcd_list = 0;
|
||||
static struct vcd_info *vcd_dmp_list = 0;
|
||||
PLI_UINT64 vcd_cur_time = 0;
|
||||
static int dump_is_off = 0;
|
||||
static long dump_limit = 0;
|
||||
static int dump_is_full = 0;
|
||||
static int finish_status = 0;
|
||||
|
||||
static char *truncate_bitvec(char *s)
|
||||
{
|
||||
char l, r;
|
||||
|
|
@ -480,7 +481,6 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name)
|
|||
s_vpi_value val;
|
||||
|
||||
/* Get the value and set the dump limit. */
|
||||
assert(argv);
|
||||
val.format = vpiIntVal;
|
||||
vpi_get_value(vpi_scan(argv), &val);
|
||||
dump_limit = val.value.integer;
|
||||
|
|
@ -520,13 +520,13 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
case vpiNet: type = "wire"; if(0){
|
||||
case vpiMemoryWord:
|
||||
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||
/* Turn a non-constant array word select into a
|
||||
* constant word select. */
|
||||
vpiHandle array = vpi_handle(vpiParent, item);
|
||||
PLI_INT32 index = vpi_get(vpiIndex, item);
|
||||
item = vpi_handle_by_index(array, index);
|
||||
}
|
||||
}
|
||||
case vpiIntegerVar:
|
||||
case vpiTimeVar:
|
||||
case vpiReg: type = "reg"; }
|
||||
|
|
@ -581,9 +581,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
cb.reason = cbValueChange;
|
||||
cb.cb_rtn = variable_cb_1;
|
||||
|
||||
|
||||
info->next = vcd_list;
|
||||
info->dmp_next = 0;
|
||||
info->dmp_next = 0;
|
||||
info->next = vcd_list;
|
||||
vcd_list = info;
|
||||
|
||||
info->cb = vpi_register_cb(&cb);
|
||||
|
|
|
|||
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;
|
||||
obj->next += 1;
|
||||
|
||||
if (obj->array->nets)
|
||||
return obj->array->nets[obj->next];
|
||||
if (obj->array->nets) return obj->array->nets[use_index];
|
||||
|
||||
assert(obj->array->vals4);
|
||||
assert(obj->array->vals4 || obj->array->valsr);
|
||||
|
||||
if (obj->array->vals_words == 0)
|
||||
array_make_vals_words(obj->array);
|
||||
if (obj->array->vals_words == 0) array_make_vals_words(obj->array);
|
||||
|
||||
return &(obj->array->vals_words[use_index].as_word);
|
||||
}
|
||||
|
|
@ -850,6 +848,7 @@ void array_set_word(vvp_array_t arr, unsigned address, double val)
|
|||
assert(arr->nets == 0);
|
||||
|
||||
arr->valsr->set_word(address, val);
|
||||
array_word_change(arr, address);
|
||||
}
|
||||
|
||||
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||
|
|
@ -1146,7 +1145,11 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit
|
|||
addr_valid_flag = vector4_to_value(bit, addr_);
|
||||
if (! addr_valid_flag)
|
||||
addr_ = arr_->array_count;
|
||||
port.ptr()->send_vec4(array_get_word(arr_,addr_), 0);
|
||||
if (vpi_array_is_real(arr_))
|
||||
port.ptr()->send_real(array_get_word_r(arr_, addr_), 0);
|
||||
else
|
||||
port.ptr()->send_vec4(array_get_word(arr_,addr_), 0);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -1157,11 +1160,13 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit
|
|||
|
||||
void vvp_fun_arrayport_sa::check_word_change(unsigned long addr)
|
||||
{
|
||||
if (addr != addr_)
|
||||
return;
|
||||
if (addr != addr_) return;
|
||||
|
||||
vvp_vector4_t bit = array_get_word(arr_, addr_);
|
||||
net_->send_vec4(bit, 0);
|
||||
if (vpi_array_is_real(arr_)) {
|
||||
net_->send_real(net_->out, array_get_word_r(arr_, addr_), 0);
|
||||
} else {
|
||||
net_->send_vec4(net_->out, array_get_word(arr_, addr_), 0);
|
||||
}
|
||||
}
|
||||
|
||||
class vvp_fun_arrayport_aa : public vvp_fun_arrayport, public automatic_hooks_s {
|
||||
|
|
@ -1243,9 +1248,16 @@ void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit
|
|||
|
||||
case 0: // Address input
|
||||
addr_valid_flag = vector4_to_value(bit, *addr);
|
||||
if (! addr_valid_flag)
|
||||
*addr = arr_->array_count;
|
||||
port.ptr()->send_vec4(array_get_word(arr_,*addr), context);
|
||||
if (! addr_valid_flag) *addr = arr_->array_count;
|
||||
if (vpi_array_is_real(arr_)) {
|
||||
port.ptr()->send_real(port.ptr()->out,
|
||||
array_get_word_r(arr_, *addr),
|
||||
context);
|
||||
} else {
|
||||
port.ptr()->send_vec4(port.ptr()->out,
|
||||
array_get_word(arr_, *addr),
|
||||
context);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -1269,8 +1281,13 @@ void vvp_fun_arrayport_aa::check_word_change(unsigned long addr)
|
|||
if (addr != *port_addr)
|
||||
return;
|
||||
|
||||
vvp_vector4_t bit = array_get_word(arr_, addr);
|
||||
net_->send_vec4(bit, vthread_get_wt_context());
|
||||
if (vpi_array_is_real(arr_)) {
|
||||
net_->send_real(net_->out, array_get_word_r(arr_, addr),
|
||||
vthread_get_wt_context());
|
||||
} else {
|
||||
net_->send_vec4(net_->out, array_get_word(arr_, addr),
|
||||
vthread_get_wt_context());
|
||||
}
|
||||
}
|
||||
|
||||
static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun)
|
||||
|
|
@ -1306,11 +1323,17 @@ void array_word_change(vvp_array_t array, unsigned long addr)
|
|||
}
|
||||
|
||||
if (cur->cb_data.cb_rtn != 0) {
|
||||
if (cur->cb_data.value)
|
||||
vpip_vec4_get_value(array->vals4->get_word(addr),
|
||||
array->vals_width,
|
||||
array->signed_flag,
|
||||
cur->cb_data.value);
|
||||
if (cur->cb_data.value) {
|
||||
if (vpi_array_is_real(array)) {
|
||||
vpip_real_get_value(array->valsr->get_word(addr),
|
||||
cur->cb_data.value);
|
||||
} else {
|
||||
vpip_vec4_get_value(array->vals4->get_word(addr),
|
||||
array->vals_width,
|
||||
array->signed_flag,
|
||||
cur->cb_data.value);
|
||||
}
|
||||
}
|
||||
|
||||
callback_execute(cur);
|
||||
prev = cur;
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ int main(int argc, char*argv[])
|
|||
FILE *logfile = 0x0;
|
||||
extern void vpi_set_vlog_info(int, char**);
|
||||
extern bool stop_is_finish;
|
||||
extern int stop_is_finish_exit_code;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
/* In the Windows world, we get the first module path
|
||||
|
|
@ -225,7 +226,7 @@ int main(int argc, char*argv[])
|
|||
/* For non-interactive runs we do not want to run the interactive
|
||||
* debugger, so make $stop just execute a $finish. */
|
||||
stop_is_finish = false;
|
||||
while ((opt = getopt(argc, argv, "+hl:M:m:nsvV")) != EOF) switch (opt) {
|
||||
while ((opt = getopt(argc, argv, "+hl:M:m:nNsvV")) != EOF) switch (opt) {
|
||||
case 'h':
|
||||
fprintf(stderr,
|
||||
"Usage: vvp [options] input-file [+plusargs...]\n"
|
||||
|
|
@ -236,6 +237,7 @@ int main(int argc, char*argv[])
|
|||
" -M - Clear VPI module path\n"
|
||||
" -m module Load vpi module.\n"
|
||||
" -n Non-interactive ($stop = $finish).\n"
|
||||
" -N Same as -n, but exit code is 1 instead of 0\n"
|
||||
" -s $stop right away.\n"
|
||||
" -v Verbose progress messages.\n"
|
||||
" -V Print the version information.\n" );
|
||||
|
|
@ -257,6 +259,10 @@ int main(int argc, char*argv[])
|
|||
case 'n':
|
||||
stop_is_finish = true;
|
||||
break;
|
||||
case 'N':
|
||||
stop_is_finish = true;
|
||||
stop_is_finish_exit_code = 1;
|
||||
break;
|
||||
case 's':
|
||||
schedule_stop(0);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
struct __vpiScope*stop_current_scope = 0;
|
||||
bool stop_is_finish; /* When set, $stop acts like $finish (set in main.cc). */
|
||||
int stop_is_finish_exit_code = 0;
|
||||
|
||||
#ifndef USE_READLINE
|
||||
static char* readline_stub(const char*prompt)
|
||||
|
|
@ -490,6 +491,7 @@ void stop_handler(int rc)
|
|||
/* The user may be running in a non-interactive environment, so
|
||||
* they want $stop and <Control-C> to be the same as $finish. */
|
||||
if (stop_is_finish) {
|
||||
vpip_set_return_value(stop_is_finish_exit_code);
|
||||
schedule_finish(0);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1002,7 +1002,8 @@ static vpiHandle find_name(const char *name, vpiHandle handle)
|
|||
if (!strcmp(name, nm)) {
|
||||
rtn = ref->intern[i];
|
||||
break;
|
||||
} else if (vpi_get(vpiType, ref->intern[i]) == vpiMemory) {
|
||||
} else if (vpi_get(vpiType, ref->intern[i]) == vpiMemory ||
|
||||
vpi_get(vpiType, ref->intern[i]) == vpiNetArray) {
|
||||
/* We need to iterate on the words */
|
||||
vpiHandle word_i, word_h;
|
||||
word_i = vpi_iterate(vpiMemoryWord, ref->intern[i]);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ vvp - Icarus Verilog vvp runtime engine
|
|||
|
||||
.SH SYNOPSIS
|
||||
.B vvp
|
||||
[-sv] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...]
|
||||
[-nNsvV] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
|
|
@ -46,6 +46,11 @@ This flag makes $stop or a <Control-C> a synonym for $finish.
|
|||
It can be used to give the program a more meaningful interface when
|
||||
running in a non-interactive environment.
|
||||
.TP 8
|
||||
.B -N
|
||||
This flag does the same thing as -n, but results in an exit code
|
||||
of 1 if the stimulation calls $stop. It can be used to indicate a
|
||||
simulation failure when running a testbench.
|
||||
.TP 8
|
||||
.B -s
|
||||
Stop. This will cause the simulation to stop in the beginning, before
|
||||
any events are scheduled. This allows the interactive user to get
|
||||
|
|
|
|||
|
|
@ -1422,6 +1422,10 @@ vvp_realarray_t::vvp_realarray_t(unsigned wor)
|
|||
: words_(wor)
|
||||
{
|
||||
array_ = new double[words_];
|
||||
// Real array words have a default value of zero.
|
||||
for (unsigned idx = 0 ; idx < words_; idx += 1) {
|
||||
array_[idx] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
vvp_realarray_t::~vvp_realarray_t()
|
||||
|
|
|
|||
Loading…
Reference in New Issue