Merge branch 'master' into work9
This commit is contained in:
commit
5e4c0c9783
|
|
@ -64,7 +64,7 @@ fi
|
|||
# AX_WIN32
|
||||
# --------
|
||||
# Combined check for several flavors of Microsoft Windows so
|
||||
# their "issues" can be dealt with
|
||||
# their "issues" can be dealt with
|
||||
AC_DEFUN([AX_WIN32],
|
||||
[AC_MSG_CHECKING([for Microsoft Windows])
|
||||
AC_REQUIRE([AC_CANONICAL_HOST]) []dnl
|
||||
|
|
@ -230,6 +230,17 @@ case "${host}" in
|
|||
esac
|
||||
])# AX_CPP_PRECOMP
|
||||
|
||||
# AX_C99_STRTOD
|
||||
# -------------
|
||||
AC_DEFUN([AX_C99_STRTOD],
|
||||
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
|
||||
case "${host}" in
|
||||
*-*-mingw*)
|
||||
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
|
||||
;;
|
||||
esac
|
||||
])# AX_C99_STRTOD
|
||||
|
||||
# When config.status generates a header, we must update the stamp-h file.
|
||||
# This file resides in the same directory as the config header
|
||||
# that is generated. The stamp file name are based on the header name.
|
||||
|
|
|
|||
|
|
@ -192,6 +192,9 @@ AX_C_PICFLAG
|
|||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# may modify LDFLAGS
|
||||
AX_C99_STRTOD
|
||||
|
||||
# Processor specific compile flags
|
||||
case "${host}" in
|
||||
alpha*-*-linux*)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
%{
|
||||
/*
|
||||
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2011 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
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
263
elab_expr.cc
263
elab_expr.cc
|
|
@ -1268,6 +1268,156 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine to look for and build enumeration method calls.
|
||||
*/
|
||||
static NetExpr* check_for_enum_methods(const LineInfo*li,
|
||||
Design*des, NetScope*scope,
|
||||
netenum_t*netenum,
|
||||
pform_name_t use_path,
|
||||
perm_string method_name,
|
||||
NetExpr*expr,
|
||||
unsigned rtn_wid,
|
||||
PExpr*parg, unsigned args)
|
||||
{
|
||||
// The "num()" method returns the number of elements.
|
||||
if (method_name == "num") {
|
||||
if (args != 0) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".num() does not "
|
||||
"take an argument." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
NetEConst*tmp = make_const_val(netenum->size());
|
||||
tmp->set_line(*li);
|
||||
delete expr; // The elaborated enum variable is not needed.
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// The "first()" method returns the first enumeration value.
|
||||
if (method_name == "first") {
|
||||
if (args != 0) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".first() does not "
|
||||
"take an argument." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
netenum_t::iterator item = netenum->first_name();
|
||||
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
|
||||
netenum, item->second);
|
||||
tmp->set_line(*li);
|
||||
delete expr; // The elaborated enum variable is not needed.
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// The "last()" method returns the first enumeration value.
|
||||
if (method_name == "last") {
|
||||
if (args != 0) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".last() does not "
|
||||
"take an argument." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
netenum_t::iterator item = netenum->last_name();
|
||||
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
|
||||
netenum, item->second);
|
||||
tmp->set_line(*li);
|
||||
delete expr; // The elaborated enum variable is not needed.
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESFunc*sys_expr;
|
||||
|
||||
// Process the method argument if it is available.
|
||||
NetExpr* count = 0;
|
||||
if (args != 0 && parg) {
|
||||
count = elaborate_rval_expr(des, scope, IVL_VT_BOOL, 32, parg);
|
||||
if (count == 0) {
|
||||
cerr << li->get_fileline() << ": error: unable to elaborate "
|
||||
"enumeration method argument " << use_path << "."
|
||||
<< method_name << "(" << parg << ")." << endl;
|
||||
args = 0;
|
||||
des->errors += 1;
|
||||
} else if (NetEEvent*evt = dynamic_cast<NetEEvent*> (count)) {
|
||||
cerr << evt->get_fileline() << ": error: An event '"
|
||||
<< evt->event()->name() << "' cannot be an enumeration "
|
||||
"method argument." << endl;
|
||||
args = 0;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// The "name()" method returns the name of the current
|
||||
// enumeration value.
|
||||
if (method_name == "name") {
|
||||
if (args != 0) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".name() does not "
|
||||
"take an argument." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
sys_expr = new NetESFunc("$ivl_enum_method$name", IVL_VT_STRING,
|
||||
rtn_wid, 2);
|
||||
sys_expr->parm(0, new NetENetenum(netenum));
|
||||
sys_expr->parm(1, expr);
|
||||
|
||||
/* The compiler/code generators need to be fixed to support a
|
||||
* string return value. In some contexts we could use the
|
||||
* expression width, but that doesn't always work. */
|
||||
if (rtn_wid == 0) {
|
||||
cerr << li->get_fileline() << ": sorry: Enumeration method "
|
||||
"name() is not currently supported in this context "
|
||||
"(self-determined)." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// The "next()" method returns the next enumeration value.
|
||||
} else if (method_name == "next") {
|
||||
if (args > 1) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".next() take at "
|
||||
"most one argument." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
sys_expr = new NetESFunc("$ivl_enum_method$next", netenum,
|
||||
2 + (args != 0));
|
||||
sys_expr->parm(0, new NetENetenum(netenum));
|
||||
sys_expr->parm(1, expr);
|
||||
if (args != 0) sys_expr->parm(2, count);
|
||||
|
||||
// The "prev()" method returns the previous enumeration value.
|
||||
} else if (method_name == "prev") {
|
||||
if (args > 1) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".prev() take at "
|
||||
"most one argument." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
sys_expr = new NetESFunc("$ivl_enum_method$prev", netenum,
|
||||
2 + (args != 0));
|
||||
sys_expr->parm(0, new NetENetenum(netenum));
|
||||
sys_expr->parm(1, expr);
|
||||
if (args != 0) sys_expr->parm(2, count);
|
||||
|
||||
// This is an unknown enumeration method.
|
||||
} else {
|
||||
cerr << li->get_fileline() << ": error: Unknown enumeration "
|
||||
"method " << use_path << "." << method_name << "()."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return expr;
|
||||
}
|
||||
|
||||
sys_expr->set_line(*li);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": debug: Generate "
|
||||
<< sys_expr->name() << "(" << use_path << ")" << endl;
|
||||
}
|
||||
|
||||
return sys_expr;
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
|
|
@ -1286,6 +1436,46 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
return elaborate_access_func_(des, scope, access_nature,
|
||||
expr_wid);
|
||||
|
||||
// Maybe this is a method attached to an enumeration name? If
|
||||
// this is system verilog, then test to see if the name is
|
||||
// really a method attached to an object.
|
||||
if (gn_system_verilog() && path_.size() >= 2) {
|
||||
pform_name_t use_path = path_;
|
||||
perm_string method_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
|
||||
NetNet *net;
|
||||
const NetExpr *par;
|
||||
NetEvent *eve;
|
||||
const NetExpr *ex1, *ex2;
|
||||
|
||||
symbol_search(this, des, scope, use_path,
|
||||
net, par, eve, ex1, ex2);
|
||||
|
||||
// Check to see if we have a net and if so is it an
|
||||
// enumeration? If so then check to see if this is an
|
||||
// enumeration method call.
|
||||
if (net != 0) {
|
||||
netenum_t*netenum = net->enumeration();
|
||||
if (netenum) {
|
||||
// We may need the net expression for the
|
||||
// enumeration variable so get it.
|
||||
NetESignal*expr = new NetESignal(net);
|
||||
expr->set_line(*this);
|
||||
// This expression cannot be a select!
|
||||
assert(use_path.back().index.empty());
|
||||
|
||||
PExpr*tmp = parms_.size() ? parms_[0] : 0;
|
||||
return check_for_enum_methods(this, des, scope,
|
||||
netenum, use_path,
|
||||
method_name, expr,
|
||||
expr_wid, tmp,
|
||||
parms_.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing was found so report this as an error.
|
||||
cerr << get_fileline() << ": error: No function named `" << path_
|
||||
<< "' found in this context (" << scope_path(scope) << ")."
|
||||
<< endl;
|
||||
|
|
@ -2087,73 +2277,32 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// Maybe this is a method attached to an enumeration name? If
|
||||
// this is system verilog, then test to see if the name is
|
||||
// really a method attached to an object.
|
||||
|
||||
if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
|
||||
pform_name_t use_path = path_;
|
||||
perm_string method_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
|
||||
found_in = symbol_search(this, des, scope, use_path,
|
||||
net, par, eve, ex1, ex2);
|
||||
net, par, eve, ex1, ex2);
|
||||
|
||||
// Check to see if we have a net and if so is it an
|
||||
// enumeration? If so then check to see if this is an
|
||||
// enumeration method call.
|
||||
if (net != 0) {
|
||||
// Special case: The net is an enum, and the
|
||||
// method name is "num".
|
||||
netenum_t*netenum = net->enumeration();
|
||||
if (netenum && method_name == "num") {
|
||||
NetEConst*tmp = make_const_val(netenum->size());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
if (netenum) {
|
||||
// We may need the net expression for the
|
||||
// enumeration variable so get it.
|
||||
NetESignal*expr = new NetESignal(net);
|
||||
expr->set_line(*this);
|
||||
// This expression cannot be a select!
|
||||
assert(use_path.back().index.empty());
|
||||
|
||||
return check_for_enum_methods(this, des, scope,
|
||||
netenum,
|
||||
use_path, method_name,
|
||||
expr, expr_wid, NULL, 0);
|
||||
}
|
||||
|
||||
// Special case: The net is an enum, and the
|
||||
// method name is "first" or "last". These
|
||||
// evaluate to constant values.
|
||||
if (netenum && method_name == "first") {
|
||||
netenum_t::iterator item = netenum->first_name();
|
||||
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
|
||||
netenum, item->second);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
if (netenum && method_name == "last") {
|
||||
netenum_t::iterator item = netenum->last_name();
|
||||
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
|
||||
netenum, item->second);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*expr = elaborate_expr_net(des, scope, net, found_in,
|
||||
expr_wid, NO_FLAGS);
|
||||
NetESFunc*sys_expr = 0;
|
||||
|
||||
if (method_name == "name") {
|
||||
sys_expr = new NetESFunc("$ivl_method$name", IVL_VT_STRING,0, 1);
|
||||
sys_expr->parm(0, expr);
|
||||
} else if (method_name == "next") {
|
||||
sys_expr = new NetESFunc("$ivl_method$next", netenum, 2);
|
||||
sys_expr->parm(0, new NetENetenum(netenum));
|
||||
sys_expr->parm(1, expr);
|
||||
} else if (method_name == "prev") {
|
||||
sys_expr = new NetESFunc("$ivl_method$prev", netenum, 2);
|
||||
sys_expr->parm(0, new NetENetenum(netenum));
|
||||
sys_expr->parm(1, expr);
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Unknown method name `" << method_name << "'"
|
||||
<< " attached to " << use_path << "." << endl;
|
||||
des->errors += 1;
|
||||
return elaborate_expr_net(des, scope, net, found_in,
|
||||
expr_wid, NO_FLAGS);
|
||||
}
|
||||
|
||||
sys_expr->set_line(*this);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: Generate "
|
||||
<< sys_expr->name() << "(" << use_path << ")" << endl;
|
||||
return sys_expr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3500,7 +3500,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
|
|||
/* Elaborate wait expression. Don't eval yet, we will do that
|
||||
shortly, after we apply a reduction or. */
|
||||
|
||||
PExpr::width_mode_t mode;
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
pe->test_width(des, scope, mode);
|
||||
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(),
|
||||
PExpr::NO_FLAGS);
|
||||
|
|
|
|||
|
|
@ -364,7 +364,6 @@ NetEConst* NetEBComp::eval_leeq_()
|
|||
left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_(left_, right_, true);
|
||||
// assert(expr_type() == IVL_VT_LOGIC);
|
||||
// HERE
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
|
@ -1090,7 +1089,6 @@ NetEConst* NetEBShift::eval_tree()
|
|||
|
||||
NetEConst* NetEConcat::eval_tree()
|
||||
{
|
||||
// HERE
|
||||
unsigned repeat_val = repeat();
|
||||
unsigned local_errors = 0;
|
||||
|
||||
|
|
@ -1182,7 +1180,6 @@ NetEConst* NetEConcat::eval_tree()
|
|||
|
||||
NetEConst* NetESelect::eval_tree()
|
||||
{
|
||||
// HERE
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": debug: Evaluating expression:"
|
||||
<< *this << endl;
|
||||
|
|
@ -1846,7 +1843,6 @@ static NetExpr* evaluate_min_max(NetExpr*&arg0_, NetExpr*&arg1_,
|
|||
|
||||
NetExpr* NetESFunc::eval_tree()
|
||||
{
|
||||
// HERE
|
||||
/* If we are not targeting at least Verilog-2005, Verilog-AMS
|
||||
* or using the Icarus misc flag then we do not support these
|
||||
* functions as constant. */
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ modules, then exit. It is a convenience for makefiles or automated
|
|||
plug-in installers.
|
||||
|
||||
.TP 8
|
||||
.B --cflags, --ldflags and -ldlibs
|
||||
.B --cflags, --ldflags and --ldlibs
|
||||
These flags provide compile time information.
|
||||
|
||||
.SH "PC-ONLY OPTIONS"
|
||||
|
|
|
|||
|
|
@ -1795,14 +1795,14 @@ static void open_input_file(struct include_stack_t*isp)
|
|||
for (idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1) {
|
||||
size_t next_len = 6 + strlen(vhdlpp_libdir[idx]);
|
||||
libs = realloc(libs, liblen+next_len);
|
||||
snprintf(libs+liblen-1, next_len, " -L'%s'", vhdlpp_libdir[idx]);
|
||||
snprintf(libs+liblen-1, next_len, " -L\"%s\"", vhdlpp_libdir[idx]);
|
||||
liblen = strlen(libs) + 1;
|
||||
}
|
||||
|
||||
cmdlen += liblen;
|
||||
|
||||
char*cmd = malloc(cmdlen);
|
||||
snprintf(cmd, cmdlen, "%s -w'%s'%s %s", vhdlpp_path, vhdlpp_work, libs, isp->path);
|
||||
snprintf(cmd, cmdlen, "%s -w\"%s\"%s %s", vhdlpp_path, vhdlpp_work, libs, isp->path);
|
||||
|
||||
if (verbose_flag)
|
||||
fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
|
||||
|
|
|
|||
10
ivlpp/main.c
10
ivlpp/main.c
|
|
@ -1,5 +1,5 @@
|
|||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)";
|
||||
"Copyright (c) 1999-2011 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
|
||||
|
|
@ -457,6 +457,14 @@ int main(int argc, char*argv[])
|
|||
}
|
||||
free(include_dir);
|
||||
|
||||
/* Free the VHDL library directories, the path and work directory. */
|
||||
for (lp = 0; lp < vhdlpp_libdir_cnt; lp += 1) {
|
||||
free(vhdlpp_libdir[lp]);
|
||||
}
|
||||
free(vhdlpp_libdir);
|
||||
free(vhdlpp_path);
|
||||
free(vhdlpp_work);
|
||||
|
||||
free_macros();
|
||||
|
||||
return error_count;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2010 Michael Ruff (mruff at chiaro.com)
|
||||
* Copyright (c) 2002-2011 Michael Ruff (mruff at chiaro.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
|
||||
|
|
@ -83,9 +83,24 @@ PLI_INT32 tf_getlongtime(PLI_INT32 *high)
|
|||
return tf_igetlongtime(high, 0);
|
||||
}
|
||||
|
||||
/* Alias for commercial simulators */
|
||||
PLI_INT32 tf_getlongsimtime(PLI_INT32 *high) \
|
||||
__attribute__ ((weak, alias ("tf_getlongtime")));
|
||||
/*
|
||||
* This function is not defined in the IEE standard, but is provided for
|
||||
* compatibility with other simulators. On platforms that support this,
|
||||
* make it a weak symbol just in case the user has defined their own
|
||||
* function for this.
|
||||
*/
|
||||
#if !defined(__CYGWIN__) && !defined(__MINGW32__)
|
||||
PLI_INT32 tf_getlongsimtime(PLI_INT32 *high) __attribute__ ((weak));
|
||||
#endif
|
||||
PLI_INT32 tf_getlongsimtime(PLI_INT32 *high)
|
||||
{
|
||||
s_vpi_time timerec;
|
||||
timerec.type = vpiSimTime;
|
||||
vpi_get_time (0, &timerec);
|
||||
|
||||
*high = timerec.high;
|
||||
return timerec.low;
|
||||
}
|
||||
|
||||
void tf_scale_longdelay(void*obj, PLI_INT32 low, PLI_INT32 high,
|
||||
PLI_INT32 *alow, PLI_INT32 *ahigh)
|
||||
|
|
|
|||
2
main.cc
2
main.cc
|
|
@ -737,7 +737,7 @@ static double cycles_diff(struct tms *a, struct tms *b)
|
|||
// Provide dummies
|
||||
struct tms { int x; };
|
||||
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 *, struct tms *) { return 0; }
|
||||
#endif // ! defined(HAVE_TIMES)
|
||||
|
||||
static void EOC_cleanup(void)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2010-2011 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
|
||||
|
|
@ -62,7 +62,7 @@ perm_string netenum_t::find_value(const verinum&val) const
|
|||
{
|
||||
perm_string res;
|
||||
for(netenum_t::iterator cur = names_map_.begin();
|
||||
cur != names_map_.end(); cur++) {
|
||||
cur != names_map_.end(); ++ cur) {
|
||||
if (cur->second == val) {
|
||||
res = cur->first;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -589,8 +589,7 @@ void eval_expr(NetExpr*&expr, int context_width)
|
|||
// The expression is a constant, so resize it if needed.
|
||||
if (ce->expr_width() < (unsigned)context_width) {
|
||||
expr = pad_to_width(expr, context_width, *expr);
|
||||
}
|
||||
if (ce->expr_width() > (unsigned)context_width) {
|
||||
} else if (ce->expr_width() > (unsigned)context_width) {
|
||||
verinum value(ce->value(), context_width);
|
||||
ce = new NetEConst(value);
|
||||
ce->set_line(*expr);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __sv_vpi_user_H
|
||||
#define __sv_vpi_user_H
|
||||
/*
|
||||
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2010-2011 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
|
||||
|
|
@ -54,6 +54,9 @@ EXTERN_C_START
|
|||
#define vpiEnumTypespec 633
|
||||
#define vpiEnumConst 634
|
||||
|
||||
/********* One-to-One ***********/
|
||||
#define vpiBaseTypespec 703
|
||||
|
||||
/********* Many-to-One ***********/
|
||||
#define vpiMember 742
|
||||
|
||||
|
|
|
|||
1
t-dll.cc
1
t-dll.cc
|
|
@ -1045,6 +1045,7 @@ bool dll_target::ureduce(const NetUReduce*net)
|
|||
switch (net->type()) {
|
||||
case NetUReduce::NONE:
|
||||
assert(0);
|
||||
delete obj;
|
||||
return false;
|
||||
case NetUReduce::AND:
|
||||
obj->type = IVL_LPM_RE_AND;
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ static void show_lpm_arithmetic_pins(ivl_lpm_t net)
|
|||
{
|
||||
ivl_nexus_t nex;
|
||||
nex = ivl_lpm_q(net);
|
||||
fprintf(out, " Q: %p\n", ivl_lpm_q(net));
|
||||
fprintf(out, " Q: %p\n", nex);
|
||||
|
||||
nex = ivl_lpm_data(net, 0);
|
||||
fprintf(out, " DataA: %p\n", nex);
|
||||
|
|
@ -247,7 +247,7 @@ static void show_lpm_abs(ivl_lpm_t net)
|
|||
ivl_lpm_basename(net), width);
|
||||
|
||||
nex = ivl_lpm_q(net);
|
||||
fprintf(out, " Q: %p\n", ivl_lpm_q(net));
|
||||
fprintf(out, " Q: %p\n", nex);
|
||||
|
||||
nex = ivl_lpm_data(net, 0);
|
||||
fprintf(out, " D: %p\n", nex);
|
||||
|
|
@ -690,6 +690,7 @@ static void show_lpm_re(ivl_lpm_t net)
|
|||
break;
|
||||
case IVL_LPM_RE_NOR:
|
||||
type = "NOR";
|
||||
break;
|
||||
case IVL_LPM_RE_XOR:
|
||||
type = "XOR";
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* VHDL code generation for statements.
|
||||
*
|
||||
* Copyright (C) 2008-2010 Nick Gasson (nick@nickg.me.uk)
|
||||
* Copyright (C) 2008-2011 Nick Gasson (nick@nickg.me.uk)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -1312,6 +1312,15 @@ static bool process_signal(vhdl_binop_expr *all, vhdl_var_ref *test,
|
|||
}
|
||||
|
||||
unsigned ewid = ivl_expr_width(expr);
|
||||
if (sizeof(unsigned) >= sizeof(long)) {
|
||||
// Since we will be casting i (constrained by swid) to a long make sure
|
||||
// it will fit into a long. This is actually off by one, but this is the
|
||||
// best we can do since on 32 bit machines an unsigned and long are the
|
||||
// same size.
|
||||
assert(swid <= static_cast<unsigned>(numeric_limits<long>::max()));
|
||||
// We are also going to cast ewid to long so check it as well.
|
||||
assert(ewid <= static_cast<unsigned>(numeric_limits<long>::max()));
|
||||
}
|
||||
for (unsigned i = 0; i < swid; i++) {
|
||||
// Generate a comparison for this bit position
|
||||
vhdl_binop_expr *cmp;
|
||||
|
|
@ -1321,7 +1330,8 @@ static bool process_signal(vhdl_binop_expr *all, vhdl_var_ref *test,
|
|||
// Check if this is an out of bounds access. If this is a casez
|
||||
// then check against a constant 'x' for the out of bound bits
|
||||
// otherwise skip the check (casex).
|
||||
if (i + sbase >= ewid || i + sbase < 0) {
|
||||
if (static_cast<long>(i) + sbase >= static_cast<long>(ewid) ||
|
||||
static_cast<long>(i) + sbase < 0) {
|
||||
if (is_casez) {
|
||||
// Get the current test bit.
|
||||
type = vhdl_type::nunsigned(width);
|
||||
|
|
|
|||
|
|
@ -1015,7 +1015,6 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
|||
emit_nexus_as_ca(scope, nex);
|
||||
if (have_data | have_sset) fprintf(vlog_out, " & ");
|
||||
if (have_data & have_sset) fprintf(vlog_out, "(");
|
||||
emitted = 1;
|
||||
}
|
||||
nex = ivl_lpm_sync_set(lpm);
|
||||
if (nex) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
# include <string.h>
|
||||
# include "config.h"
|
||||
# include "vlog95_priv.h"
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
static void emit_entry(ivl_udp_t udp, char entry, unsigned *rerun)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1276,10 +1276,31 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
|||
}
|
||||
if (ivl_signal_width(lsig) > ivl_signal_width(rsig) ||
|
||||
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
|
||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s signal to "
|
||||
"a bit/part select.\n", ivl_expr_file(rval),
|
||||
ivl_expr_lineno(rval), command_name);
|
||||
exit(1);
|
||||
/* Normalize the bit/part select. */
|
||||
long real_msb = ivl_signal_msb(lsig);
|
||||
long real_lsb = ivl_signal_lsb(lsig);
|
||||
long use_wid = ivl_signal_width(rsig);
|
||||
long use_lsb, use_msb;
|
||||
if (real_msb >= real_lsb) {
|
||||
use_lsb = get_number_immediate(part_off_ex);
|
||||
use_lsb += real_lsb;
|
||||
use_msb = use_lsb + use_wid - 1;
|
||||
} else {
|
||||
use_lsb = real_lsb;
|
||||
use_lsb -= get_number_immediate(part_off_ex);
|
||||
use_msb = use_lsb;
|
||||
use_msb -= use_wid - 1;
|
||||
}
|
||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s signal to a ",
|
||||
ivl_stmt_file(net), ivl_stmt_lineno(net), command_name);
|
||||
if (use_wid > 1) {
|
||||
fprintf(stderr, "part select (%s[%lu:%lu]).\n",
|
||||
ivl_signal_basename(lsig), use_msb, use_lsb);
|
||||
} else {
|
||||
fprintf(stderr, "bit select (%s[%lu]).\n",
|
||||
ivl_signal_basename(lsig), use_lsb);
|
||||
}
|
||||
vvp_errors += 1;
|
||||
}
|
||||
|
||||
/* At least for now, only handle force to fixed words of an array. */
|
||||
|
|
@ -1287,17 +1308,42 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
|||
assert(number_is_immediate(lword_idx, IMM_WID, 0));
|
||||
assert(! number_is_unknown(lword_idx));
|
||||
use_lword = get_number_immediate(lword_idx);
|
||||
/* We do not currently support using a word from a variable
|
||||
* array as the L-value (Icarus extension). */
|
||||
if (ivl_signal_type(lsig) == IVL_SIT_REG) {
|
||||
/* Normalize the array access. */
|
||||
long real_word = use_lword;
|
||||
real_word += ivl_signal_array_base(lsig);
|
||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s to the "
|
||||
"word of a variable array (%s[%ld]).\n",
|
||||
ivl_stmt_file(net), ivl_stmt_lineno(net),
|
||||
command_name, ivl_signal_basename(lsig), real_word);
|
||||
vvp_errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
|
||||
assert(ivl_signal_dimensions(rsig) != 0);
|
||||
assert(number_is_immediate(rword_idx, IMM_WID, 0));
|
||||
assert(! number_is_unknown(rword_idx));
|
||||
use_rword = get_number_immediate(rword_idx);
|
||||
/* We do not currently support using a word from a variable
|
||||
* array as the R-value. */
|
||||
if (ivl_signal_type(rsig) == IVL_SIT_REG) {
|
||||
/* Normalize the array access. */
|
||||
long real_word = use_rword;
|
||||
real_word += ivl_signal_array_base(rsig);
|
||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s from the "
|
||||
"word of a variable array (%s[%ld]).\n",
|
||||
ivl_expr_file(rval), ivl_expr_lineno(rval),
|
||||
command_name, ivl_signal_basename(rsig), real_word);
|
||||
vvp_errors += 1;
|
||||
}
|
||||
} else {
|
||||
assert(ivl_signal_dimensions(rsig) == 0);
|
||||
use_rword = 0;
|
||||
}
|
||||
|
||||
assert(ivl_signal_dimensions(rsig) == 0);
|
||||
use_rword = 0;
|
||||
|
||||
fprintf(vvp_out, " %s/link", command_name);
|
||||
fprintf(vvp_out, " v%p_%lu", lsig, use_lword);
|
||||
fprintf(vvp_out, ", v%p_%lu;\n", rsig, use_rword);
|
||||
|
|
|
|||
|
|
@ -162,8 +162,8 @@ Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag)
|
|||
ExpAggregate::element_t::element_t(list<choice_t*>*fields, Expression*val)
|
||||
: fields_(fields? fields->size() : 0), val_(val)
|
||||
{
|
||||
size_t idx = 0;
|
||||
if (fields) {
|
||||
size_t idx = 0;
|
||||
while (! fields->empty()) {
|
||||
assert(idx < fields_.size());
|
||||
fields_[idx++] = fields->front();
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ static bool is_based_correct(char* text)
|
|||
if(base == 0)
|
||||
return 0;
|
||||
}
|
||||
bool point = 0;
|
||||
bool point = false;
|
||||
set<char> allowed_chars;
|
||||
|
||||
unsigned c;
|
||||
|
|
@ -299,12 +299,12 @@ static bool is_based_correct(char* text)
|
|||
if(*ptr == '.')
|
||||
{
|
||||
//we found a dot and another one was already found
|
||||
if(point == 1)
|
||||
if(point)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
//notice the fact of finding a point and continue, without increasing the length
|
||||
point = 1;
|
||||
point = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,10 @@ const char NOTICE[] =
|
|||
# include <getopt.h>
|
||||
#endif
|
||||
# include <sys/stat.h>
|
||||
#if defined(__MINGW32__)
|
||||
# include <io.h>
|
||||
# define mkdir(path, mode) _mkdir(path)
|
||||
#endif
|
||||
|
||||
|
||||
bool verbose_flag = false;
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ class Scope : public ScopeBase {
|
|||
class ActiveScope : public ScopeBase {
|
||||
|
||||
public:
|
||||
ActiveScope() { }
|
||||
ActiveScope() : context_entity_(0) { }
|
||||
ActiveScope(ActiveScope*par) : ScopeBase(*par), context_entity_(0) { }
|
||||
|
||||
~ActiveScope() { }
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ va_math.vpi: $V ../vvp/libvpi.a
|
|||
$(CC) @shared@ -o $@ $V -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS)
|
||||
|
||||
vhdl_sys.vpi: $(VHDL_SYS) ../vvp/libvpi.a
|
||||
$(CXX) @shared@ -o $@ $(VHDL_SYS) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
|
||||
$(CC) @shared@ -o $@ $(VHDL_SYS) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
|
||||
|
||||
stamp-vpi_config-h: $(srcdir)/vpi_config.h.in ../config.status
|
||||
@rm -f $@
|
||||
|
|
|
|||
|
|
@ -3,22 +3,23 @@
|
|||
// problems will not be fixed.
|
||||
|
||||
// fstapi.c from GTKWave
|
||||
variableScope:fstapi.c:1689
|
||||
variableScope:fstapi.c:1817
|
||||
variableScope:fstapi.c:1911
|
||||
variableScope:fstapi.c:1912
|
||||
variableScope:fstapi.c:2617
|
||||
variableScope:fstapi.c:2937
|
||||
variableScope:fstapi.c:2941
|
||||
variableScope:fstapi.c:2942
|
||||
variableScope:fstapi.c:1713
|
||||
variableScope:fstapi.c:1841
|
||||
variableScope:fstapi.c:1935
|
||||
variableScope:fstapi.c:1936
|
||||
variableScope:fstapi.c:2642
|
||||
variableScope:fstapi.c:2962
|
||||
variableScope:fstapi.c:2966
|
||||
variableScope:fstapi.c:2967
|
||||
variableScope:fstapi.c:4641
|
||||
|
||||
// lxt2_write.c from GTKWave
|
||||
variableScope:lxt2_write.c:63
|
||||
variableScope:lxt2_write.c:523
|
||||
variableScope:lxt2_write.c:581
|
||||
variableScope:lxt2_write.c:587
|
||||
variableScope:lxt2_write.c:1602
|
||||
variableScope:lxt2_write.c:2049
|
||||
variableScope:lxt2_write.c:1600
|
||||
variableScope:lxt2_write.c:2047
|
||||
|
||||
// lxt_write.c from GTKWave
|
||||
variableScope:lxt_write.c:31
|
||||
|
|
|
|||
607
vpi/fstapi.c
607
vpi/fstapi.c
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2010 Tony Bybell.
|
||||
* Copyright (c) 2009-2011 Tony Bybell.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
|
@ -505,6 +505,7 @@ unsigned repack_on_close : 1;
|
|||
unsigned skip_writing_section_hdr : 1;
|
||||
unsigned size_limit_locked : 1;
|
||||
unsigned section_header_only : 1;
|
||||
unsigned flush_context_pending : 1;
|
||||
|
||||
/* should really be semaphores, but are bytes to cut down on read-modify-write window size */
|
||||
unsigned char already_in_flush; /* in case control-c handlers interrupt */
|
||||
|
|
@ -758,272 +759,6 @@ return(xc);
|
|||
}
|
||||
|
||||
|
||||
void fstWriterClose(void *ctx)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if(xc && !xc->already_in_close && !xc->already_in_flush)
|
||||
{
|
||||
unsigned char *tmem;
|
||||
off_t fixup_offs, tlen, hlen;
|
||||
|
||||
xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */
|
||||
|
||||
if(xc->section_header_only && xc->section_header_truncpos && (xc->vchg_siz <= 1) && (!xc->is_initial_time))
|
||||
{
|
||||
fstFtruncate(fileno(xc->handle), xc->section_header_truncpos);
|
||||
fseeko(xc->handle, xc->section_header_truncpos, SEEK_SET);
|
||||
xc->section_header_only = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xc->skip_writing_section_hdr = 1;
|
||||
if(!xc->size_limit_locked)
|
||||
{
|
||||
if(xc->is_initial_time) /* simulation time never advanced so mock up the changes as time zero ones */
|
||||
{
|
||||
fstHandle dupe_idx;
|
||||
|
||||
fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */
|
||||
for(dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */
|
||||
{
|
||||
fstWriterEmitValueChange(xc, dupe_idx+1, xc->curval_mem + xc->valpos_mem[4*dupe_idx]);
|
||||
}
|
||||
}
|
||||
fstWriterFlushContext(xc);
|
||||
}
|
||||
}
|
||||
fstDestroyMmaps(xc, 1);
|
||||
|
||||
/* write out geom section */
|
||||
fflush(xc->geom_handle);
|
||||
tlen = ftello(xc->geom_handle);
|
||||
tmem = fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0);
|
||||
if(tmem)
|
||||
{
|
||||
unsigned long destlen = tlen;
|
||||
unsigned char *dmem = malloc(destlen);
|
||||
int rc = compress2(dmem, &destlen, tmem, tlen, 9);
|
||||
|
||||
if((rc != Z_OK) || (destlen > tlen))
|
||||
{
|
||||
destlen = tlen;
|
||||
}
|
||||
|
||||
fixup_offs = ftello(xc->handle);
|
||||
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
|
||||
fstWriterUint64(xc->handle, destlen + 24); /* section length */
|
||||
fstWriterUint64(xc->handle, tlen); /* uncompressed */
|
||||
/* compressed len is section length - 24 */
|
||||
fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */
|
||||
fstFwrite((destlen != tlen) ? dmem : tmem, destlen, 1, xc->handle);
|
||||
fflush(xc->handle);
|
||||
|
||||
fseeko(xc->handle, fixup_offs, SEEK_SET);
|
||||
fputc(FST_BL_GEOM, xc->handle); /* actual tag */
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
|
||||
fflush(xc->handle);
|
||||
|
||||
free(dmem);
|
||||
fstMunmap(tmem, tlen);
|
||||
}
|
||||
|
||||
if(xc->num_blackouts)
|
||||
{
|
||||
uint64_t cur_bl = 0;
|
||||
off_t bpos, eos;
|
||||
uint32_t i;
|
||||
|
||||
fixup_offs = ftello(xc->handle);
|
||||
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
|
||||
bpos = fixup_offs + 1;
|
||||
fstWriterUint64(xc->handle, 0); /* section length */
|
||||
fstWriterVarint(xc->handle, xc->num_blackouts);
|
||||
|
||||
for(i=0;i<xc->num_blackouts;i++)
|
||||
{
|
||||
fputc(xc->blackout_head->active, xc->handle);
|
||||
fstWriterVarint(xc->handle, xc->blackout_head->tim - cur_bl);
|
||||
cur_bl = xc->blackout_head->tim;
|
||||
xc->blackout_curr = xc->blackout_head->next;
|
||||
free(xc->blackout_head);
|
||||
xc->blackout_head = xc->blackout_curr;
|
||||
}
|
||||
|
||||
eos = ftello(xc->handle);
|
||||
fseeko(xc->handle, bpos, SEEK_SET);
|
||||
fstWriterUint64(xc->handle, eos - bpos);
|
||||
fflush(xc->handle);
|
||||
|
||||
fseeko(xc->handle, fixup_offs, SEEK_SET);
|
||||
fputc(FST_BL_BLACKOUT, xc->handle); /* actual tag */
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
|
||||
fflush(xc->handle);
|
||||
}
|
||||
|
||||
if(xc->compress_hier)
|
||||
{
|
||||
unsigned char *mem = malloc(FST_GZIO_LEN);
|
||||
off_t hl, eos;
|
||||
gzFile zhandle;
|
||||
int zfd;
|
||||
#ifndef __MINGW32__
|
||||
char *fnam = malloc(strlen(xc->filename) + 5 + 1);
|
||||
#endif
|
||||
|
||||
fixup_offs = ftello(xc->handle);
|
||||
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
|
||||
hlen = ftello(xc->handle);
|
||||
fstWriterUint64(xc->handle, 0); /* section length */
|
||||
fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */
|
||||
|
||||
fflush(xc->handle);
|
||||
zfd = dup(fileno(xc->handle));
|
||||
zhandle = gzdopen(zfd, "wb4");
|
||||
if(zhandle)
|
||||
{
|
||||
fseeko(xc->hier_handle, 0, SEEK_SET);
|
||||
for(hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN)
|
||||
{
|
||||
unsigned len = ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl);
|
||||
fstFread(mem, len, 1, xc->hier_handle);
|
||||
gzwrite(zhandle, mem, len);
|
||||
}
|
||||
gzclose(zhandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
close(zfd);
|
||||
}
|
||||
free(mem);
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END);
|
||||
eos = ftello(xc->handle);
|
||||
fseeko(xc->handle, hlen, SEEK_SET);
|
||||
fstWriterUint64(xc->handle, eos - hlen);
|
||||
fflush(xc->handle);
|
||||
|
||||
fseeko(xc->handle, fixup_offs, SEEK_SET);
|
||||
fputc(FST_BL_HIER, xc->handle); /* actual tag */
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
|
||||
fflush(xc->handle);
|
||||
|
||||
#ifndef __MINGW32__
|
||||
sprintf(fnam, "%s.hier", xc->filename);
|
||||
unlink(fnam);
|
||||
free(fnam);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* finalize out header */
|
||||
fseeko(xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET);
|
||||
fstWriterUint64(xc->handle, xc->firsttime);
|
||||
fstWriterUint64(xc->handle, xc->curtime);
|
||||
fseeko(xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET);
|
||||
fstWriterUint64(xc->handle, xc->numscopes);
|
||||
fstWriterUint64(xc->handle, xc->numsigs);
|
||||
fstWriterUint64(xc->handle, xc->maxhandle);
|
||||
fstWriterUint64(xc->handle, xc->secnum);
|
||||
fflush(xc->handle);
|
||||
|
||||
if(xc->tchn_handle) { fclose(xc->tchn_handle); xc->tchn_handle = NULL; }
|
||||
free(xc->vchg_mem); xc->vchg_mem = NULL;
|
||||
if(xc->curval_handle) { fclose(xc->curval_handle); xc->curval_handle = NULL; }
|
||||
if(xc->valpos_handle) { fclose(xc->valpos_handle); xc->valpos_handle = NULL; }
|
||||
if(xc->geom_handle) { fclose(xc->geom_handle); xc->geom_handle = NULL; }
|
||||
if(xc->hier_handle) { fclose(xc->hier_handle); xc->hier_handle = NULL; }
|
||||
if(xc->handle)
|
||||
{
|
||||
if(xc->repack_on_close)
|
||||
{
|
||||
FILE *fp;
|
||||
off_t offpnt, uclen;
|
||||
int flen = strlen(xc->filename);
|
||||
char *hf = calloc(1, flen + 5);
|
||||
|
||||
strcpy(hf, xc->filename);
|
||||
strcpy(hf+flen, ".pak");
|
||||
fp = fopen(hf, "wb");
|
||||
|
||||
if(fp)
|
||||
{
|
||||
void *dsth;
|
||||
int zfd;
|
||||
char gz_membuf[FST_GZIO_LEN];
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END);
|
||||
uclen = ftello(xc->handle);
|
||||
|
||||
fputc(FST_BL_ZWRAPPER, fp);
|
||||
fstWriterUint64(fp, 0);
|
||||
fstWriterUint64(fp, uclen);
|
||||
fflush(fp);
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_SET);
|
||||
zfd = dup(fileno(fp));
|
||||
dsth = gzdopen(zfd, "wb4");
|
||||
if(dsth)
|
||||
{
|
||||
for(offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN)
|
||||
{
|
||||
size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt);
|
||||
fstFread(gz_membuf, this_len, 1, xc->handle);
|
||||
gzwrite(dsth, gz_membuf, this_len);
|
||||
}
|
||||
gzclose(dsth);
|
||||
}
|
||||
else
|
||||
{
|
||||
close(zfd);
|
||||
}
|
||||
fseeko(fp, 0, SEEK_END);
|
||||
offpnt = ftello(fp);
|
||||
fseeko(fp, 1, SEEK_SET);
|
||||
fstWriterUint64(fp, offpnt - 1);
|
||||
fclose(fp);
|
||||
fclose(xc->handle); xc->handle = NULL;
|
||||
|
||||
unlink(xc->filename);
|
||||
rename(hf, xc->filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
xc->repack_on_close = 0;
|
||||
fclose(xc->handle); xc->handle = NULL;
|
||||
}
|
||||
|
||||
free(hf);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(xc->handle); xc->handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
{
|
||||
int flen = strlen(xc->filename);
|
||||
char *hf = calloc(1, flen + 6);
|
||||
strcpy(hf, xc->filename);
|
||||
|
||||
if(xc->compress_hier)
|
||||
{
|
||||
strcpy(hf + flen, ".hier");
|
||||
unlink(hf); /* no longer needed as a section now exists for this */
|
||||
}
|
||||
|
||||
free(hf);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(xc->filename); xc->filename = NULL;
|
||||
free(xc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* generation and writing out of value change data sections
|
||||
*/
|
||||
|
|
@ -1074,7 +809,11 @@ if(xc)
|
|||
}
|
||||
|
||||
|
||||
void fstWriterFlushContext(void *ctx)
|
||||
/*
|
||||
* only to be called directly by fst code...otherwise must
|
||||
* be synced up with time changes
|
||||
*/
|
||||
static void fstWriterFlushContextPrivate(void *ctx)
|
||||
{
|
||||
#ifdef FST_DEBUG
|
||||
int cnt = 0;
|
||||
|
|
@ -1409,7 +1148,7 @@ for(i=0;i<xc->maxhandle;i++)
|
|||
JudyHSFreeArray(&PJHSArray, NULL);
|
||||
#endif
|
||||
|
||||
free(packmem); packmem = NULL; packmemlen = 0;
|
||||
free(packmem); packmem = NULL; /* packmemlen = 0; */ /* scan-build */
|
||||
|
||||
prevpos = 0; zerocnt = 0;
|
||||
free(scratchpad); scratchpad = NULL;
|
||||
|
|
@ -1449,7 +1188,7 @@ for(i=0;i<xc->maxhandle;i++)
|
|||
}
|
||||
if(zerocnt)
|
||||
{
|
||||
fpos += fstWriterVarint(f, (zerocnt << 1));
|
||||
/* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */
|
||||
}
|
||||
#ifdef FST_DEBUG
|
||||
printf("value chains: %d\n", cnt);
|
||||
|
|
@ -1538,6 +1277,291 @@ xc->already_in_flush = 0;
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* queues up a flush context operation
|
||||
*/
|
||||
void fstWriterFlushContext(void *ctx)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if(xc)
|
||||
{
|
||||
if(xc->tchn_idx > 1)
|
||||
{
|
||||
xc->flush_context_pending = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* close out FST file
|
||||
*/
|
||||
void fstWriterClose(void *ctx)
|
||||
{
|
||||
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
|
||||
if(xc && !xc->already_in_close && !xc->already_in_flush)
|
||||
{
|
||||
unsigned char *tmem;
|
||||
off_t fixup_offs, tlen, hlen;
|
||||
|
||||
xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */
|
||||
|
||||
if(xc->section_header_only && xc->section_header_truncpos && (xc->vchg_siz <= 1) && (!xc->is_initial_time))
|
||||
{
|
||||
fstFtruncate(fileno(xc->handle), xc->section_header_truncpos);
|
||||
fseeko(xc->handle, xc->section_header_truncpos, SEEK_SET);
|
||||
xc->section_header_only = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xc->skip_writing_section_hdr = 1;
|
||||
if(!xc->size_limit_locked)
|
||||
{
|
||||
if(xc->is_initial_time) /* simulation time never advanced so mock up the changes as time zero ones */
|
||||
{
|
||||
fstHandle dupe_idx;
|
||||
|
||||
fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */
|
||||
for(dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */
|
||||
{
|
||||
fstWriterEmitValueChange(xc, dupe_idx+1, xc->curval_mem + xc->valpos_mem[4*dupe_idx]);
|
||||
}
|
||||
}
|
||||
fstWriterFlushContextPrivate(xc);
|
||||
}
|
||||
}
|
||||
fstDestroyMmaps(xc, 1);
|
||||
|
||||
/* write out geom section */
|
||||
fflush(xc->geom_handle);
|
||||
tlen = ftello(xc->geom_handle);
|
||||
tmem = fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0);
|
||||
if(tmem)
|
||||
{
|
||||
unsigned long destlen = tlen;
|
||||
unsigned char *dmem = malloc(destlen);
|
||||
int rc = compress2(dmem, &destlen, tmem, tlen, 9);
|
||||
|
||||
if((rc != Z_OK) || (destlen > tlen))
|
||||
{
|
||||
destlen = tlen;
|
||||
}
|
||||
|
||||
fixup_offs = ftello(xc->handle);
|
||||
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
|
||||
fstWriterUint64(xc->handle, destlen + 24); /* section length */
|
||||
fstWriterUint64(xc->handle, tlen); /* uncompressed */
|
||||
/* compressed len is section length - 24 */
|
||||
fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */
|
||||
fstFwrite((destlen != tlen) ? dmem : tmem, destlen, 1, xc->handle);
|
||||
fflush(xc->handle);
|
||||
|
||||
fseeko(xc->handle, fixup_offs, SEEK_SET);
|
||||
fputc(FST_BL_GEOM, xc->handle); /* actual tag */
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
|
||||
fflush(xc->handle);
|
||||
|
||||
free(dmem);
|
||||
fstMunmap(tmem, tlen);
|
||||
}
|
||||
|
||||
if(xc->num_blackouts)
|
||||
{
|
||||
uint64_t cur_bl = 0;
|
||||
off_t bpos, eos;
|
||||
uint32_t i;
|
||||
|
||||
fixup_offs = ftello(xc->handle);
|
||||
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
|
||||
bpos = fixup_offs + 1;
|
||||
fstWriterUint64(xc->handle, 0); /* section length */
|
||||
fstWriterVarint(xc->handle, xc->num_blackouts);
|
||||
|
||||
for(i=0;i<xc->num_blackouts;i++)
|
||||
{
|
||||
fputc(xc->blackout_head->active, xc->handle);
|
||||
fstWriterVarint(xc->handle, xc->blackout_head->tim - cur_bl);
|
||||
cur_bl = xc->blackout_head->tim;
|
||||
xc->blackout_curr = xc->blackout_head->next;
|
||||
free(xc->blackout_head);
|
||||
xc->blackout_head = xc->blackout_curr;
|
||||
}
|
||||
|
||||
eos = ftello(xc->handle);
|
||||
fseeko(xc->handle, bpos, SEEK_SET);
|
||||
fstWriterUint64(xc->handle, eos - bpos);
|
||||
fflush(xc->handle);
|
||||
|
||||
fseeko(xc->handle, fixup_offs, SEEK_SET);
|
||||
fputc(FST_BL_BLACKOUT, xc->handle); /* actual tag */
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
|
||||
fflush(xc->handle);
|
||||
}
|
||||
|
||||
if(xc->compress_hier)
|
||||
{
|
||||
unsigned char *mem = malloc(FST_GZIO_LEN);
|
||||
off_t hl, eos;
|
||||
gzFile zhandle;
|
||||
int zfd;
|
||||
#ifndef __MINGW32__
|
||||
char *fnam = malloc(strlen(xc->filename) + 5 + 1);
|
||||
#endif
|
||||
|
||||
fixup_offs = ftello(xc->handle);
|
||||
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
|
||||
hlen = ftello(xc->handle);
|
||||
fstWriterUint64(xc->handle, 0); /* section length */
|
||||
fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */
|
||||
|
||||
fflush(xc->handle);
|
||||
zfd = dup(fileno(xc->handle));
|
||||
zhandle = gzdopen(zfd, "wb4");
|
||||
if(zhandle)
|
||||
{
|
||||
fseeko(xc->hier_handle, 0, SEEK_SET);
|
||||
for(hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN)
|
||||
{
|
||||
unsigned len = ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl);
|
||||
fstFread(mem, len, 1, xc->hier_handle);
|
||||
gzwrite(zhandle, mem, len);
|
||||
}
|
||||
gzclose(zhandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
close(zfd);
|
||||
}
|
||||
free(mem);
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END);
|
||||
eos = ftello(xc->handle);
|
||||
fseeko(xc->handle, hlen, SEEK_SET);
|
||||
fstWriterUint64(xc->handle, eos - hlen);
|
||||
fflush(xc->handle);
|
||||
|
||||
fseeko(xc->handle, fixup_offs, SEEK_SET);
|
||||
fputc(FST_BL_HIER, xc->handle); /* actual tag */
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
|
||||
fflush(xc->handle);
|
||||
|
||||
#ifndef __MINGW32__
|
||||
sprintf(fnam, "%s.hier", xc->filename);
|
||||
unlink(fnam);
|
||||
free(fnam);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* finalize out header */
|
||||
fseeko(xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET);
|
||||
fstWriterUint64(xc->handle, xc->firsttime);
|
||||
fstWriterUint64(xc->handle, xc->curtime);
|
||||
fseeko(xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET);
|
||||
fstWriterUint64(xc->handle, xc->numscopes);
|
||||
fstWriterUint64(xc->handle, xc->numsigs);
|
||||
fstWriterUint64(xc->handle, xc->maxhandle);
|
||||
fstWriterUint64(xc->handle, xc->secnum);
|
||||
fflush(xc->handle);
|
||||
|
||||
if(xc->tchn_handle) { fclose(xc->tchn_handle); xc->tchn_handle = NULL; }
|
||||
free(xc->vchg_mem); xc->vchg_mem = NULL;
|
||||
if(xc->curval_handle) { fclose(xc->curval_handle); xc->curval_handle = NULL; }
|
||||
if(xc->valpos_handle) { fclose(xc->valpos_handle); xc->valpos_handle = NULL; }
|
||||
if(xc->geom_handle) { fclose(xc->geom_handle); xc->geom_handle = NULL; }
|
||||
if(xc->hier_handle) { fclose(xc->hier_handle); xc->hier_handle = NULL; }
|
||||
if(xc->handle)
|
||||
{
|
||||
if(xc->repack_on_close)
|
||||
{
|
||||
FILE *fp;
|
||||
off_t offpnt, uclen;
|
||||
int flen = strlen(xc->filename);
|
||||
char *hf = calloc(1, flen + 5);
|
||||
|
||||
strcpy(hf, xc->filename);
|
||||
strcpy(hf+flen, ".pak");
|
||||
fp = fopen(hf, "wb");
|
||||
|
||||
if(fp)
|
||||
{
|
||||
void *dsth;
|
||||
int zfd;
|
||||
char gz_membuf[FST_GZIO_LEN];
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_END);
|
||||
uclen = ftello(xc->handle);
|
||||
|
||||
fputc(FST_BL_ZWRAPPER, fp);
|
||||
fstWriterUint64(fp, 0);
|
||||
fstWriterUint64(fp, uclen);
|
||||
fflush(fp);
|
||||
|
||||
fseeko(xc->handle, 0, SEEK_SET);
|
||||
zfd = dup(fileno(fp));
|
||||
dsth = gzdopen(zfd, "wb4");
|
||||
if(dsth)
|
||||
{
|
||||
for(offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN)
|
||||
{
|
||||
size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt);
|
||||
fstFread(gz_membuf, this_len, 1, xc->handle);
|
||||
gzwrite(dsth, gz_membuf, this_len);
|
||||
}
|
||||
gzclose(dsth);
|
||||
}
|
||||
else
|
||||
{
|
||||
close(zfd);
|
||||
}
|
||||
fseeko(fp, 0, SEEK_END);
|
||||
offpnt = ftello(fp);
|
||||
fseeko(fp, 1, SEEK_SET);
|
||||
fstWriterUint64(fp, offpnt - 1);
|
||||
fclose(fp);
|
||||
fclose(xc->handle); xc->handle = NULL;
|
||||
|
||||
unlink(xc->filename);
|
||||
rename(hf, xc->filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
xc->repack_on_close = 0;
|
||||
fclose(xc->handle); xc->handle = NULL;
|
||||
}
|
||||
|
||||
free(hf);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(xc->handle); xc->handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
{
|
||||
int flen = strlen(xc->filename);
|
||||
char *hf = calloc(1, flen + 6);
|
||||
strcpy(hf, xc->filename);
|
||||
|
||||
if(xc->compress_hier)
|
||||
{
|
||||
strcpy(hf + flen, ".hier");
|
||||
unlink(hf); /* no longer needed as a section now exists for this */
|
||||
}
|
||||
|
||||
free(hf);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(xc->filename); xc->filename = NULL;
|
||||
free(xc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* functions to set miscellaneous header/block information
|
||||
*/
|
||||
|
|
@ -1940,9 +1964,10 @@ if(xc)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(xc->vchg_siz >= FST_BREAK_SIZE)
|
||||
if((xc->vchg_siz >= FST_BREAK_SIZE) || (xc->flush_context_pending))
|
||||
{
|
||||
fstWriterFlushContext(xc);
|
||||
xc->flush_context_pending = 0;
|
||||
fstWriterFlushContextPrivate(xc);
|
||||
xc->tchn_cnt++;
|
||||
fstWriterVarint(xc->tchn_handle, xc->curtime);
|
||||
}
|
||||
|
|
@ -3359,7 +3384,10 @@ uint64_t tsec_nitems;
|
|||
int secnum = 0;
|
||||
int blocks_skipped = 0;
|
||||
off_t blkpos = 0;
|
||||
uint64_t seclen, beg_tim, end_tim;
|
||||
uint64_t seclen, beg_tim;
|
||||
#ifdef FST_DEBUG
|
||||
uint64_t end_tim;
|
||||
#endif
|
||||
uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle;
|
||||
off_t vc_start;
|
||||
off_t indx_pntr, indx_pos;
|
||||
|
|
@ -3414,7 +3442,10 @@ for(;;)
|
|||
if(!seclen) break;
|
||||
|
||||
beg_tim = fstReaderUint64(xc->f);
|
||||
end_tim = fstReaderUint64(xc->f);
|
||||
#ifdef FST_DEBUG
|
||||
end_tim =
|
||||
#endif
|
||||
fstReaderUint64(xc->f);
|
||||
|
||||
if(xc->limit_range_valid)
|
||||
{
|
||||
|
|
@ -3443,8 +3474,8 @@ for(;;)
|
|||
{
|
||||
unsigned char *ucdata;
|
||||
unsigned char *cdata;
|
||||
unsigned long destlen = tsec_uclen;
|
||||
unsigned long sourcelen = tsec_clen;
|
||||
unsigned long destlen /* = tsec_uclen */; /* scan-build */
|
||||
unsigned long sourcelen /*= tsec_clen */; /* scan-build */
|
||||
int rc;
|
||||
unsigned char *tpnt;
|
||||
uint64_t tpval;
|
||||
|
|
@ -3896,12 +3927,12 @@ for(;;)
|
|||
unsigned char val;
|
||||
if(!(vli & 1))
|
||||
{
|
||||
tdelta = vli >> 2;
|
||||
/* tdelta = vli >> 2; */ /* scan-build */
|
||||
val = ((vli >> 1) & 1) | '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
tdelta = vli >> 4;
|
||||
/* tdelta = vli >> 4; */ /* scan-build */
|
||||
val = FST_RCV_STR[((vli >> 1) & 7)];
|
||||
}
|
||||
|
||||
|
|
@ -3946,7 +3977,7 @@ for(;;)
|
|||
|
||||
vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
|
||||
len = fstGetVarint32(mem_for_traversal + headptr[idx] + skiplen, &skiplen2);
|
||||
tdelta = vli >> 1;
|
||||
/* tdelta = vli >> 1; */ /* scan-build */
|
||||
skiplen += skiplen2;
|
||||
vdata = mem_for_traversal + headptr[idx] + skiplen;
|
||||
|
||||
|
|
@ -4002,7 +4033,7 @@ for(;;)
|
|||
unsigned char *vdata;
|
||||
|
||||
vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
|
||||
tdelta = vli >> 1;
|
||||
/* tdelta = vli >> 1; */ /* scan-build */
|
||||
vdata = mem_for_traversal + headptr[idx] + skiplen;
|
||||
|
||||
if(xc->signal_typs[idx] != FST_VT_VCD_REAL)
|
||||
|
|
@ -4058,7 +4089,7 @@ for(;;)
|
|||
else
|
||||
{
|
||||
double d;
|
||||
unsigned char *clone_d = (unsigned char *)&d;
|
||||
unsigned char *clone_d /*= (unsigned char *)&d */; /* scan-build */
|
||||
unsigned char buf[8];
|
||||
unsigned char *srcdata;
|
||||
|
||||
|
|
@ -4261,7 +4292,9 @@ uint64_t seclen;
|
|||
uint64_t tsec_uclen = 0, tsec_clen = 0;
|
||||
uint64_t tsec_nitems;
|
||||
uint64_t frame_uclen, frame_clen;
|
||||
#ifdef FST_DEBUG
|
||||
uint64_t mem_required_for_traversal;
|
||||
#endif
|
||||
off_t indx_pntr, indx_pos;
|
||||
long chain_clen;
|
||||
unsigned char *chain_cmem;
|
||||
|
|
@ -4352,7 +4385,11 @@ for(;;)
|
|||
xc->rvat_beg_tim = beg_tim;
|
||||
xc->rvat_end_tim = end_tim;
|
||||
|
||||
mem_required_for_traversal = fstReaderUint64(xc->f);
|
||||
#ifdef FST_DEBUG
|
||||
mem_required_for_traversal =
|
||||
#endif
|
||||
fstReaderUint64(xc->f);
|
||||
|
||||
#ifdef FST_DEBUG
|
||||
printf("rvat sec: %d seclen: %d begtim: %d endtim: %d\n",
|
||||
secnum, (int)seclen, (int)beg_tim, (int)end_tim);
|
||||
|
|
@ -4363,8 +4400,8 @@ printf("\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
|
|||
{
|
||||
unsigned char *ucdata;
|
||||
unsigned char *cdata;
|
||||
unsigned long destlen = tsec_uclen;
|
||||
unsigned long sourcelen = tsec_clen;
|
||||
unsigned long destlen /* = tsec_uclen */; /* scan-build */
|
||||
unsigned long sourcelen /* = tsec_clen */; /* scan-build */
|
||||
int rc;
|
||||
unsigned char *tpnt;
|
||||
uint64_t tpval;
|
||||
|
|
@ -4628,7 +4665,7 @@ if(xc->signal_lens[facidx] == 1)
|
|||
iprev = i;
|
||||
pvli = vli;
|
||||
ptidx = tidx;
|
||||
pskip = skiplen;
|
||||
/* pskip = skiplen; */ /* scan-build */
|
||||
|
||||
tidx += tdelta;
|
||||
i+=skiplen;
|
||||
|
|
|
|||
|
|
@ -1144,7 +1144,7 @@ unsigned int total_chgs;
|
|||
unsigned int partial_length;
|
||||
|
||||
total_chgs = 0;
|
||||
partial_length = 0;
|
||||
/* partial_length = 0; */ /* scan-build : never read */
|
||||
|
||||
iter_hi = iter + partial_iter;
|
||||
if(iter_hi > lt->numfacs) iter_hi = lt->numfacs;
|
||||
|
|
@ -1491,8 +1491,6 @@ if(lt)
|
|||
|
||||
if( (!lt->timepos) && (!lt->timegranule) && ((!lt->numblock)||(!lt->no_checkpoint)) )
|
||||
{
|
||||
struct lxt2_wr_symbol *s = lt->symchain;
|
||||
|
||||
/* fprintf(stderr, "initial value burst timepos==0, timegranule==0\n"); */
|
||||
if(lt->blackout)
|
||||
{
|
||||
|
|
@ -1501,7 +1499,7 @@ if(lt)
|
|||
}
|
||||
else
|
||||
{
|
||||
s = lt->symchain;
|
||||
struct lxt2_wr_symbol *s = lt->symchain;
|
||||
while(s)
|
||||
{
|
||||
if((!(s->flags&LXT2_WR_SYM_F_ALIAS))&&(s->rows<2))
|
||||
|
|
|
|||
|
|
@ -248,9 +248,11 @@ static void get_time(char *rtn, const char *value, int prec,
|
|||
static void get_time_real(char *rtn, double value, int prec,
|
||||
PLI_INT32 time_units)
|
||||
{
|
||||
/* Scale the value if its time units differ from the format units. */
|
||||
if (time_units != timeformat_info.units) {
|
||||
/* Scale the value from its time units to the format time units. */
|
||||
if (time_units >= timeformat_info.units) {
|
||||
value *= pow(10.0, time_units - timeformat_info.units);
|
||||
} else {
|
||||
value /= pow(10.0, timeformat_info.units - time_units);
|
||||
}
|
||||
sprintf(rtn, "%0.*f%s", prec, value, timeformat_info.suff);
|
||||
}
|
||||
|
|
@ -444,7 +446,9 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
|||
strcpy(cpb+pad, cp);
|
||||
|
||||
/* If a width was not given, use the default, unless we have a
|
||||
* leading zero (width of zero). */
|
||||
* leading zero (width of zero). Because the width of a real in
|
||||
* Icarus is 1 the string length will set the width of a real
|
||||
* displayed using %d. */
|
||||
if (width == -1) {
|
||||
width = (ld_zero == 1) ? 0 : vpi_get_dec_size(info->items[*idx]);
|
||||
}
|
||||
|
|
@ -856,7 +860,7 @@ static unsigned int get_format(char **rtn, char *fmt,
|
|||
static unsigned int get_numeric(char **rtn, const struct strobe_cb_info *info,
|
||||
vpiHandle item)
|
||||
{
|
||||
int size;
|
||||
int size, min;
|
||||
s_vpi_value val;
|
||||
|
||||
val.format = info->default_format;
|
||||
|
|
@ -865,6 +869,11 @@ static unsigned int get_numeric(char **rtn, const struct strobe_cb_info *info,
|
|||
switch(info->default_format){
|
||||
case vpiDecStrVal:
|
||||
size = vpi_get_dec_size(item);
|
||||
/* -1 can be represented as a one bit signed value. This returns
|
||||
* a size of 1 which is too small for the -1 string value so make
|
||||
* the string width the minimum display width. */
|
||||
min = strlen(val.value.str);
|
||||
if (size < min) size = min;
|
||||
*rtn = malloc((size+1)*sizeof(char));
|
||||
sprintf(*rtn, "%*s", size, val.value.str);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ static PLI_INT32 task_not_implemented_compiletf(ICARUS_VPI_CONST PLI_BYTE8* name
|
|||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
|
||||
vpi_printf("%s:%d: SORRY: task %s() is not currently implemented.\n",
|
||||
vpi_printf("SORRY: %s:%d: task %s() is not currently implemented.\n",
|
||||
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
||||
name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
@ -60,7 +60,7 @@ static PLI_INT32 missing_optional_compiletf(ICARUS_VPI_CONST PLI_BYTE8* name)
|
|||
{
|
||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||
|
||||
vpi_printf("%s:%d: SORRY: %s() is not available in Icarus verilog.\n",
|
||||
vpi_printf("SORRY: %s:%d: %s() is not available in Icarus verilog.\n",
|
||||
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
||||
name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
|
|||
|
|
@ -524,7 +524,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
struct t_cb_data cb;
|
||||
struct vcd_info* info;
|
||||
|
||||
const char* type;
|
||||
const char* name;
|
||||
const char* ident;
|
||||
int nexus_id;
|
||||
|
|
@ -547,7 +546,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
switch (vpi_get(vpiType, item)) {
|
||||
|
||||
case vpiNet: type = "wire"; if(0){
|
||||
case vpiMemoryWord:
|
||||
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||
/* Turn a non-constant array word select into a
|
||||
|
|
@ -563,7 +561,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
case vpiTimeVar:
|
||||
case vpiReg: type = "reg"; }
|
||||
case vpiReg:
|
||||
case vpiNet:
|
||||
|
||||
/* An array word is implicitly escaped so look for an
|
||||
* escaped identifier that this could conflict with. */
|
||||
|
|
@ -656,11 +655,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
break;
|
||||
|
||||
case vpiModule: type = "module"; if(0){
|
||||
case vpiNamedBegin: type = "begin"; }if(0){
|
||||
case vpiTask: type = "task"; }if(0){
|
||||
case vpiFunction: type = "function"; }if(0){
|
||||
case vpiNamedFork: type = "fork"; }
|
||||
case vpiModule:
|
||||
case vpiNamedBegin:
|
||||
case vpiTask:
|
||||
case vpiFunction:
|
||||
case vpiNamedFork:
|
||||
|
||||
if (depth > 0) {
|
||||
int nskip;
|
||||
|
|
@ -683,7 +682,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
|
||||
push_scope(name); /* keep in type info determination for possible future usage */
|
||||
push_scope(name);
|
||||
|
||||
for (i=0; types[i]>0; i++) {
|
||||
vpiHandle hand;
|
||||
|
|
|
|||
|
|
@ -587,7 +587,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
struct t_cb_data cb;
|
||||
struct vcd_info* info;
|
||||
|
||||
const char* type;
|
||||
const char* name;
|
||||
const char* ident;
|
||||
int nexus_id;
|
||||
|
|
@ -610,7 +609,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
switch (vpi_get(vpiType, item)) {
|
||||
|
||||
case vpiNet: type = "wire"; if(0){
|
||||
case vpiMemoryWord:
|
||||
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||
/* Turn a non-constant array word select into a
|
||||
|
|
@ -626,7 +624,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
case vpiTimeVar:
|
||||
case vpiReg: type = "reg"; }
|
||||
case vpiReg:
|
||||
case vpiNet:
|
||||
|
||||
/* An array word is implicitly escaped so look for an
|
||||
* escaped identifier that this could conflict with. */
|
||||
|
|
@ -711,11 +710,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
break;
|
||||
|
||||
case vpiModule: type = "module"; if(0){
|
||||
case vpiNamedBegin: type = "begin"; }if(0){
|
||||
case vpiTask: type = "task"; }if(0){
|
||||
case vpiFunction: type = "function"; }if(0){
|
||||
case vpiNamedFork: type = "fork"; }
|
||||
case vpiModule:
|
||||
case vpiNamedBegin:
|
||||
case vpiTask:
|
||||
case vpiFunction:
|
||||
case vpiNamedFork:
|
||||
|
||||
if (depth > 0) {
|
||||
int nskip;
|
||||
|
|
@ -738,7 +737,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
|
||||
push_scope(name); /* keep in type info determination for possible future usage */
|
||||
push_scope(name);
|
||||
|
||||
for (i=0; types[i]>0; i++) {
|
||||
vpiHandle hand;
|
||||
|
|
|
|||
|
|
@ -567,6 +567,7 @@ static PLI_INT32 sys_urandom_range_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
|
|||
|
||||
/* Check that there are at least two arguments. */
|
||||
arg = vpi_scan(argv); /* This should never be zero. */
|
||||
assert(arg);
|
||||
arg = vpi_scan(argv);
|
||||
if (arg == 0) {
|
||||
vpi_printf("ERROR: %s requires two arguments.\n", name);
|
||||
|
|
|
|||
1013
vpi/sys_scanf.c
1013
vpi/sys_scanf.c
File diff suppressed because it is too large
Load Diff
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2011 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
|
||||
|
|
@ -95,7 +95,9 @@ static PLI_INT32 sys_realtime_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
|||
|
||||
/* For $abstime() we return the time in second. */
|
||||
if (strcmp(name, "$abstime") == 0) {
|
||||
now.real *= pow(10.0, vpi_get(vpiTimeUnit, mod));
|
||||
PLI_INT32 scale = vpi_get(vpiTimeUnit, mod);
|
||||
if (scale >= 0) now.real *= pow(10.0, scale);
|
||||
else now.real /= pow(10.0, -scale);
|
||||
}
|
||||
|
||||
val.format = vpiRealVal;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Verilog-2005 math library for Icarus Verilog
|
||||
* http://www.icarus.com/eda/verilog/
|
||||
*
|
||||
* Copyright (C) 2007-2010 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2007-2011 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -191,6 +191,7 @@ static PLI_INT32 va_single_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
|
|||
arg = vpi_scan(argv);
|
||||
if (arg != 0) {
|
||||
va_error_message(callh, "%s takes only one argument.\n", name);
|
||||
vpi_free_object(argv);
|
||||
}
|
||||
|
||||
/* Get the function that is to be used by the calltf routine. */
|
||||
|
|
@ -274,6 +275,7 @@ static PLI_INT32 va_double_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
|
|||
arg = vpi_scan(argv);
|
||||
if (arg != 0) {
|
||||
va_error_message(callh, "%s takes only two arguments.\n", name);
|
||||
vpi_free_object(argv);
|
||||
}
|
||||
|
||||
/* Get the function that is to be used by the calltf routine. */
|
||||
|
|
|
|||
551
vpi/v2009_enum.c
551
vpi/v2009_enum.c
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2010-2011 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
|
||||
|
|
@ -20,243 +20,514 @@
|
|||
# include "vpi_config.h"
|
||||
# include "sv_vpi_user.h"
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
static void missing_arguments(vpiHandle sys)
|
||||
{
|
||||
vpi_printf("%s:%d: error: Invalid/missing arguments next/prev method\n",
|
||||
vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo,sys));
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
static PLI_INT32 ivl_method_next_prev_compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
||||
/*
|
||||
* The compiletf routine for the enumeration next() and prev() methods.
|
||||
*/
|
||||
static PLI_INT32 ivl_enum_method_next_prev_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle arg_enum, arg_item, arg_extra;
|
||||
vpiHandle arg_enum, arg_var, arg_count;
|
||||
|
||||
/* These routines must have arguments. */
|
||||
if (argv == 0) {
|
||||
missing_arguments(sys);
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("No arguments given for enum method %s().\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for the enumeration type argument. */
|
||||
arg_enum = vpi_scan(argv);
|
||||
if (arg_enum == 0) {
|
||||
missing_arguments(sys);
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("No enumeration type argument given for enum "
|
||||
"method %s().\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg_item = vpi_scan(argv);
|
||||
if (arg_item == 0) {
|
||||
missing_arguments(sys);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure there are no excess arguments */
|
||||
arg_extra = vpi_scan(argv);
|
||||
if (arg_extra != 0) {
|
||||
missing_arguments(sys);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The first argument must be an enum typespec */
|
||||
if (vpi_get(vpiType, arg_enum) != vpiEnumTypespec) {
|
||||
missing_arguments(sys);
|
||||
return 0;
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("The first argument to enum method %s() must be an "
|
||||
"enumeration type, found a %s.\n", name,
|
||||
vpi_get_str(vpiType, arg_enum));
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
/* The return value and input value must be the same size */
|
||||
if (vpi_get(vpiSize,sys) != vpi_get(vpiSize,arg_item)) {
|
||||
missing_arguments(sys);
|
||||
/* Check for the enumeration variable. */
|
||||
arg_var = vpi_scan(argv);
|
||||
if (arg_var == 0) {
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("No enumeration variable argument given for enum "
|
||||
"method %s().\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
switch(vpi_get(vpiType, arg_var)) {
|
||||
case vpiBitVar:
|
||||
case vpiByteVar:
|
||||
case vpiIntegerVar:
|
||||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
case vpiReg:
|
||||
case vpiShortIntVar:
|
||||
break;
|
||||
default:
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("The second argument to enum method %s() must be an "
|
||||
"enumeration variable, found a %s.\n", name,
|
||||
vpi_get_str(vpiType, arg_var));
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
/* We can have an optional numeric count value. */
|
||||
arg_count = vpi_scan(argv);
|
||||
if (arg_count) {
|
||||
switch(vpi_get(vpiType, arg_count)) {
|
||||
case vpiBitVar:
|
||||
case vpiByteVar:
|
||||
case vpiIntegerVar:
|
||||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
case vpiMemoryWord:
|
||||
case vpiNet:
|
||||
case vpiPartSelect:
|
||||
case vpiRealVar:
|
||||
case vpiReg:
|
||||
case vpiShortIntVar:
|
||||
case vpiTimeVar:
|
||||
break;
|
||||
case vpiConstant:
|
||||
case vpiParameter:
|
||||
if (vpi_get(vpiConstType, arg_count) != vpiStringConst) break;
|
||||
default:
|
||||
vpi_printf("%s:%d: compiler error: ",
|
||||
vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("The second argument to enum method %s() must be "
|
||||
"numeric, found a %s.\n", name,
|
||||
vpi_get_str(vpiType, arg_count));
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have a count argument then check to see if any extra
|
||||
* arguments were given. */
|
||||
if (arg_count && (vpi_scan(argv) != 0)) {
|
||||
vpi_free_object(argv);
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("Extra argument(s) given to enum method %s().\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
/* The method return value and the enum variable must be the
|
||||
* same size */
|
||||
if (vpi_get(vpiSize, sys) != vpi_get(vpiSize, arg_var)) {
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("The enum method %s() return width (%d) must match "
|
||||
"the enum variable width (%d).\n", name,
|
||||
(int) vpi_get(vpiSize, sys),
|
||||
(int) vpi_get(vpiSize, arg_var));
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_value_eequal(s_vpi_value*ref1, s_vpi_value*ref2, long wid)
|
||||
/*
|
||||
* Compare it two values are equal to each other.
|
||||
*/
|
||||
static int compare_value_eequal(s_vpi_value*ref1, s_vpi_value*ref2,
|
||||
PLI_INT32 wid)
|
||||
{
|
||||
/* Two integer values are easy. */
|
||||
if (ref1->format == vpiIntVal && ref2->format == vpiIntVal)
|
||||
return ref1->value.integer == ref2->value.integer;
|
||||
|
||||
/* For two vectors compare them word by word. */
|
||||
if (ref1->format == vpiVectorVal && ref2->format == vpiVectorVal) {
|
||||
int words = (wid-1)/32 + 1;
|
||||
int idx;
|
||||
PLI_INT32 words = (wid-1)/32 + 1;
|
||||
PLI_INT32 idx;
|
||||
|
||||
for (idx = 0 ; idx < words ; idx += 1) {
|
||||
if (ref1->value.vector[idx].aval != ref2->value.vector[idx].aval)
|
||||
return 0;
|
||||
if (ref1->value.vector[idx].bval != ref2->value.vector[idx].bval)
|
||||
return 0;
|
||||
if (ref1->value.vector[idx].aval !=
|
||||
ref2->value.vector[idx].aval) return 0;
|
||||
if (ref1->value.vector[idx].bval !=
|
||||
ref2->value.vector[idx].bval) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Swap the order so the code below can be used. */
|
||||
if (ref1->format == vpiVectorVal && ref2->format == vpiIntVal) {
|
||||
s_vpi_value*tmp = ref1;
|
||||
ref1 = ref2;
|
||||
ref2 = tmp;
|
||||
}
|
||||
|
||||
/* Compare an integer to a vector. */
|
||||
if (ref1->format == vpiIntVal && ref2->format == vpiVectorVal) {
|
||||
int use_aval = ref1->value.integer;
|
||||
int words = (wid-1)/32 + 1;
|
||||
int idx;
|
||||
PLI_INT32 aval = ref1->value.integer;
|
||||
PLI_INT32 words = (wid-1)/32 + 1;
|
||||
PLI_INT32 idx;
|
||||
|
||||
for (idx = 0 ; idx < words ; idx += 1) {
|
||||
if (use_aval != ref2->value.vector[idx].aval)
|
||||
return 0;
|
||||
if (0 != ref2->value.vector[idx].bval)
|
||||
return 0;
|
||||
if (aval != ref2->value.vector[idx].aval) return 0;
|
||||
if (ref2->value.vector[idx].bval) return 0;
|
||||
|
||||
use_aval = 0;
|
||||
aval = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Unsupported types. */
|
||||
vpi_printf("XXXX formats are: %d vs %d\n", ref1->format, ref2->format);
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 ivl_method_next_calltf(PLI_BYTE8*data)
|
||||
/*
|
||||
* If the current value is not found in the enumeration. Then we need to
|
||||
* return X/0 for the next()/prev() value.
|
||||
*/
|
||||
static void fill_handle_with_init(vpiHandle arg, int is_two_state)
|
||||
{
|
||||
s_vpi_value val;
|
||||
PLI_INT32 words = ((vpi_get(vpiSize, arg) - 1) / 32) + 1;
|
||||
PLI_INT32 idx;
|
||||
p_vpi_vecval val_ptr = (p_vpi_vecval) malloc(words*sizeof(s_vpi_vecval));
|
||||
PLI_INT32 fill = (is_two_state) ? 0x0 : 0xffffffff;
|
||||
|
||||
assert(val_ptr);
|
||||
|
||||
/* Fill the vector with X. */
|
||||
for (idx=0; idx < words; idx += 1) {
|
||||
val_ptr[idx].aval = fill;
|
||||
val_ptr[idx].bval = fill;
|
||||
}
|
||||
|
||||
/* Put the vector to the argument. */
|
||||
val.format = vpiVectorVal;
|
||||
val.value.vector = val_ptr;
|
||||
vpi_put_value(arg, &val, 0, vpiNoDelay);
|
||||
free(val_ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the next()/prev() enumeration methods.
|
||||
*/
|
||||
static PLI_INT32 ivl_enum_method_next_prev_calltf(PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle arg_enum = vpi_scan(argv);
|
||||
vpiHandle arg_item = vpi_scan(argv);
|
||||
vpiHandle arg_extra = vpi_scan(argv);
|
||||
vpiHandle arg_var = vpi_scan(argv);
|
||||
vpiHandle arg_count = vpi_scan(argv);
|
||||
|
||||
vpiHandle enum_list = 0;
|
||||
vpiHandle memb = 0, first_memb = 0;
|
||||
long use_width = 0;
|
||||
long item_width = vpi_get(vpiSize, arg_item);
|
||||
vpiHandle enum_list;
|
||||
vpiHandle cur;
|
||||
PLI_INT32 var_width = vpi_get(vpiSize, arg_var);
|
||||
PLI_UINT32 enum_size = vpi_get(vpiSize, arg_enum);
|
||||
PLI_UINT32 count = 1;
|
||||
PLI_UINT32 loc = 0;
|
||||
|
||||
s_vpi_value memb_value, item_value;
|
||||
s_vpi_value cur_val, var_val;
|
||||
|
||||
assert(arg_extra == 0);
|
||||
/* Get the count value if one was given. */
|
||||
if (arg_count) {
|
||||
s_vpi_value count_val;
|
||||
|
||||
item_value.format = vpiObjTypeVal;
|
||||
vpi_get_value(arg_item, &item_value);
|
||||
|
||||
/* If this value is a vector value, then make a safe copy of
|
||||
the vector so that other vpi functions don't trash it. */
|
||||
if (item_value.format == vpiVectorVal) {
|
||||
unsigned idx;
|
||||
unsigned hwid = (item_width - 1)/32 + 1;
|
||||
s_vpi_vecval*op = calloc(hwid, sizeof(s_vpi_vecval));
|
||||
for (idx = 0 ; idx < hwid ; idx += 1) {
|
||||
op[idx].aval = item_value.value.vector[idx].aval;
|
||||
op[idx].bval = item_value.value.vector[idx].bval;
|
||||
}
|
||||
item_value.value.vector = op;
|
||||
/* Get the count value. */
|
||||
count_val.format = vpiIntVal;
|
||||
vpi_get_value(arg_count, &count_val);
|
||||
count = count_val.value.integer;
|
||||
/* Remove any multiple loops around the enumeration. */
|
||||
count %= enum_size;
|
||||
/* Free the argument iterator. */
|
||||
vpi_free_object(argv);
|
||||
}
|
||||
|
||||
enum_list = vpi_iterate(vpiMember, arg_enum);
|
||||
assert(enum_list);
|
||||
/* Get the current value. */
|
||||
var_val.format = vpiObjTypeVal;
|
||||
vpi_get_value(arg_var, &var_val);
|
||||
|
||||
/* Search for the current value in the member list. */
|
||||
do {
|
||||
memb = vpi_scan(enum_list);
|
||||
if (first_memb == 0) {
|
||||
first_memb = memb;
|
||||
use_width = vpi_get(vpiSize, first_memb);
|
||||
assert(use_width == vpi_get(vpiSize, arg_item));
|
||||
/* If the count is zero then just return the current value. */
|
||||
if (count == 0) {
|
||||
vpi_put_value(sys, &var_val, 0, vpiNoDelay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the current value is a vector, then make a safe copy of
|
||||
it so that other vpi_get_value() calls don't trash the value. */
|
||||
if (var_val.format == vpiVectorVal) {
|
||||
PLI_INT32 idx;
|
||||
PLI_INT32 words = (var_width - 1)/32 + 1;
|
||||
p_vpi_vecval nvec = malloc(words*sizeof(s_vpi_vecval));
|
||||
for (idx = 0 ; idx < words ; idx += 1) {
|
||||
nvec[idx].aval = var_val.value.vector[idx].aval;
|
||||
nvec[idx].bval = var_val.value.vector[idx].bval;
|
||||
}
|
||||
if (memb == 0) break;
|
||||
var_val.value.vector = nvec;
|
||||
}
|
||||
|
||||
memb_value.format = vpiObjTypeVal;
|
||||
vpi_get_value(memb, &memb_value);
|
||||
/* Search for the current value in the enumeration list. */
|
||||
enum_list = vpi_iterate(vpiEnumConst, arg_enum);
|
||||
assert(enum_list);
|
||||
do {
|
||||
cur = vpi_scan(enum_list);
|
||||
if (cur == 0) break;
|
||||
|
||||
} while (! compare_value_eequal(&item_value, &memb_value, use_width));
|
||||
cur_val.format = vpiObjTypeVal;
|
||||
vpi_get_value(cur, &cur_val);
|
||||
assert(var_width == vpi_get(vpiSize, cur));
|
||||
loc += 1;
|
||||
} while (! compare_value_eequal(&cur_val, &var_val, var_width));
|
||||
|
||||
if (memb != 0)
|
||||
memb = vpi_scan(enum_list);
|
||||
/* If the variable is a vector then free the copy we created above. */
|
||||
if (var_val.format == vpiVectorVal) free(var_val.value.vector);
|
||||
|
||||
if (memb != 0)
|
||||
/* The current value was not found in the list so return X/0. */
|
||||
if (cur == 0) {
|
||||
/* This only works correctly since we don't really define the
|
||||
* the correct base typespec. */
|
||||
int is_two_state = vpi_get(vpiBaseTypespec, arg_enum) != vpiReg;
|
||||
fill_handle_with_init(sys, is_two_state);
|
||||
} else {
|
||||
if (strcmp(name, "$ivl_enum_method$next") == 0) {
|
||||
/* Check to see if we need to wrap to the beginning. */
|
||||
if (loc + count > enum_size) {
|
||||
/* Free the current iterator before creating a new
|
||||
* one that is at the beginning of the list. */
|
||||
vpi_free_object(enum_list);
|
||||
enum_list = vpi_iterate(vpiEnumConst, arg_enum);
|
||||
assert(enum_list);
|
||||
count -= (enum_size - loc);
|
||||
}
|
||||
} else if (strcmp(name, "$ivl_enum_method$prev") == 0) {
|
||||
/* Because of wrapping the count could be either before
|
||||
* or after the current element. */
|
||||
if (loc <= count ) {
|
||||
/* The element we want is after the current
|
||||
* element. */
|
||||
count = enum_size - count;
|
||||
} else {
|
||||
/* The element we want is before the current
|
||||
* element (at the beginning of the list). Free
|
||||
* the current iterator before creating a new
|
||||
* one that is at the beginning of the list. */
|
||||
vpi_free_object(enum_list);
|
||||
enum_list = vpi_iterate(vpiEnumConst, arg_enum);
|
||||
assert(enum_list);
|
||||
count = loc - count;
|
||||
}
|
||||
} else assert(0);
|
||||
|
||||
/* Find the correct element. */
|
||||
while (count) {
|
||||
cur = vpi_scan(enum_list);
|
||||
count -= 1;
|
||||
}
|
||||
assert(cur != 0);
|
||||
|
||||
/* Free the iterator. */
|
||||
vpi_free_object(enum_list);
|
||||
|
||||
if (memb == 0) {
|
||||
memb = first_memb;
|
||||
memb_value.format = vpiIntVal;
|
||||
/* Get the value and return it. */
|
||||
cur_val.format = vpiObjTypeVal;
|
||||
vpi_get_value(cur, &cur_val);
|
||||
vpi_put_value(sys, &cur_val, 0, vpiNoDelay);
|
||||
}
|
||||
|
||||
/* Free any stached copy of the vector. */
|
||||
if (item_value.format == vpiVectorVal)
|
||||
free(item_value.value.vector);
|
||||
|
||||
vpi_get_value(memb, &memb_value);
|
||||
vpi_put_value(sys, &memb_value, 0, vpiNoDelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 ivl_method_prev_calltf(PLI_BYTE8*data)
|
||||
/*
|
||||
* The compiletf routine for the enumeration name() method.
|
||||
*/
|
||||
static PLI_INT32 ivl_enum_method_name_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle arg_enum, arg_var;
|
||||
|
||||
/* This routine must have arguments. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("No arguments given for enum method %s().\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for the enumeration type argument. */
|
||||
arg_enum = vpi_scan(argv);
|
||||
if (arg_enum == 0) {
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("No enumeration type argument given for enum "
|
||||
"method %s().\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
if (vpi_get(vpiType, arg_enum) != vpiEnumTypespec) {
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("The first argument to enum method %s() must be an "
|
||||
"enumeration type, found a %s.\n", name,
|
||||
vpi_get_str(vpiType, arg_enum));
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
/* Check for the enumeration variable. */
|
||||
arg_var = vpi_scan(argv);
|
||||
if (arg_var == 0) {
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("No enumeration variable argument given for enum "
|
||||
"method %s().\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
switch(vpi_get(vpiType, arg_var)) {
|
||||
case vpiBitVar:
|
||||
case vpiByteVar:
|
||||
case vpiIntegerVar:
|
||||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
case vpiReg:
|
||||
case vpiShortIntVar:
|
||||
break;
|
||||
default:
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("The second argument to enum method %s() must be an "
|
||||
"enumeration variable, found a %s.\n", name,
|
||||
vpi_get_str(vpiType, arg_var));
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
/* Only two arguments are supported. */
|
||||
if (vpi_scan(argv) != 0) {
|
||||
vpi_free_object(argv);
|
||||
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||
(int) vpi_get(vpiLineNo,sys));
|
||||
vpi_printf("Extra argument(s) given to enum method %s().\n", name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the name() enumeration method.
|
||||
*/
|
||||
static PLI_INT32 ivl_enum_method_name_calltf(PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle arg_enum = vpi_scan(argv);
|
||||
vpiHandle arg_item = vpi_scan(argv);
|
||||
vpiHandle arg_extra = vpi_scan(argv);
|
||||
vpiHandle arg_var = vpi_scan(argv);
|
||||
|
||||
vpiHandle enum_list = 0;
|
||||
vpiHandle memb = 0, prev = 0, last_memb = 0;
|
||||
int use_wid = 0;
|
||||
vpiHandle enum_list;
|
||||
vpiHandle cur;
|
||||
PLI_INT32 var_width = vpi_get(vpiSize, arg_var);
|
||||
|
||||
s_vpi_value memb_value, item_value;
|
||||
s_vpi_value cur_val, var_val;
|
||||
|
||||
assert(arg_extra == 0);
|
||||
/* Free the argument iterator. */
|
||||
vpi_free_object(argv);
|
||||
|
||||
item_value.format = vpiIntVal;
|
||||
vpi_get_value(arg_item, &item_value);
|
||||
/* Get the current value. */
|
||||
var_val.format = vpiObjTypeVal;
|
||||
vpi_get_value(arg_var, &var_val);
|
||||
|
||||
enum_list = vpi_iterate(vpiMember, arg_enum);
|
||||
assert(enum_list);
|
||||
|
||||
/* Search for the current value in the member list. */
|
||||
do {
|
||||
prev = memb;
|
||||
memb = vpi_scan(enum_list);
|
||||
if (memb == 0) break;
|
||||
if (use_wid == 0)
|
||||
use_wid = vpi_get(vpiSize, memb);
|
||||
|
||||
last_memb = memb;
|
||||
memb_value.format = vpiIntVal;
|
||||
vpi_get_value(memb, &memb_value);
|
||||
} while (! compare_value_eequal(&memb_value, &item_value, use_wid));
|
||||
|
||||
while (memb) {
|
||||
last_memb = memb;
|
||||
memb = vpi_scan(enum_list);
|
||||
/* If the current value is a vector, then make a safe copy of
|
||||
it so that other vpi_get_value() calls don't trash the value. */
|
||||
if (var_val.format == vpiVectorVal) {
|
||||
PLI_INT32 idx;
|
||||
PLI_INT32 words = (var_width - 1)/32 + 1;
|
||||
p_vpi_vecval nvec = malloc(words*sizeof(s_vpi_vecval));
|
||||
for (idx = 0 ; idx < words ; idx += 1) {
|
||||
nvec[idx].aval = var_val.value.vector[idx].aval;
|
||||
nvec[idx].bval = var_val.value.vector[idx].bval;
|
||||
}
|
||||
var_val.value.vector = nvec;
|
||||
}
|
||||
|
||||
if (prev == 0)
|
||||
prev = last_memb;
|
||||
/* Search for the current value in the enumeration list. */
|
||||
enum_list = vpi_iterate(vpiEnumConst, arg_enum);
|
||||
assert(enum_list);
|
||||
do {
|
||||
cur = vpi_scan(enum_list);
|
||||
if (cur == 0) break;
|
||||
|
||||
vpi_get_value(prev, &memb_value);
|
||||
vpi_put_value(sys, &memb_value, 0, vpiNoDelay);
|
||||
cur_val.format = vpiObjTypeVal;
|
||||
vpi_get_value(cur, &cur_val);
|
||||
assert(var_width == vpi_get(vpiSize, cur));
|
||||
} while (! compare_value_eequal(&cur_val, &var_val, var_width));
|
||||
|
||||
/* If the variable is a vector then free the copy we created above. */
|
||||
if (var_val.format == vpiVectorVal) free(var_val.value.vector);
|
||||
|
||||
/* The current value was not found in the list so return an empty
|
||||
* string. */
|
||||
cur_val.format = vpiStringVal;
|
||||
if (cur == 0) {
|
||||
cur_val.value.str = "";
|
||||
} else {
|
||||
cur_val.value.str = vpi_get_str(vpiName, cur);
|
||||
|
||||
/* Free the iterator. */
|
||||
vpi_free_object(enum_list);
|
||||
}
|
||||
|
||||
/* Return the appropriate string value. */
|
||||
vpi_put_value(sys, &cur_val, 0, vpiNoDelay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void v2009_enum_register(void)
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
vpiHandle res;
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.calltf = ivl_method_next_calltf;
|
||||
tf_data.compiletf = ivl_method_next_prev_compiletf;
|
||||
tf_data.calltf = ivl_enum_method_name_calltf;
|
||||
tf_data.compiletf = ivl_enum_method_name_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.tfname = "$ivl_method$next";
|
||||
tf_data.user_data = "$ivl_method$next";
|
||||
vpi_register_systf(&tf_data);
|
||||
tf_data.tfname = "$ivl_enum_method$name";
|
||||
tf_data.user_data = "$ivl_enum_method$name";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
/* This is not a user defined system function so hide it. */
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.calltf = ivl_method_prev_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.calltf = ivl_enum_method_next_prev_calltf;
|
||||
tf_data.compiletf = ivl_enum_method_next_prev_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.tfname = "$ivl_method$prev";
|
||||
tf_data.user_data = "$ivl_method$prev";
|
||||
vpi_register_systf(&tf_data);
|
||||
tf_data.tfname = "$ivl_enum_method$next";
|
||||
tf_data.user_data = "$ivl_enum_method$next";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
/* This is not a user defined system function so hide it. */
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.calltf = ivl_enum_method_next_prev_calltf;
|
||||
tf_data.compiletf = ivl_enum_method_next_prev_compiletf;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.tfname = "$ivl_enum_method$prev";
|
||||
tf_data.user_data = "$ivl_enum_method$prev";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
/* This is not a user defined system function so hide it. */
|
||||
vpip_make_systf_system_defined(res);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Verilog-A math library for Icarus Verilog
|
||||
* http://www.icarus.com/eda/verilog/
|
||||
*
|
||||
* Copyright (C) 2007-2010 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2007-2011 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -218,6 +218,7 @@ static PLI_INT32 va_single_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
|
|||
arg = vpi_scan(argv);
|
||||
if (arg != 0) {
|
||||
va_error_message(callh, "%s takes only one argument.\n", name);
|
||||
vpi_free_object(argv);
|
||||
}
|
||||
|
||||
/* Get the function that is to be used by the calltf routine. */
|
||||
|
|
@ -301,6 +302,7 @@ static PLI_INT32 va_double_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
|
|||
arg = vpi_scan(argv);
|
||||
if (arg != 0) {
|
||||
va_error_message(callh, "%s takes only two arguments.\n", name);
|
||||
vpi_free_object(argv);
|
||||
}
|
||||
|
||||
/* Get the function that is to be used by the calltf routine. */
|
||||
|
|
|
|||
|
|
@ -214,8 +214,7 @@ static PLI_INT32 simparam_str_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name_ext)
|
|||
char path [MAX_STRING_RESULT];
|
||||
char *ptr = getcwd(path, MAX_STRING_RESULT);
|
||||
if (ptr == NULL) {
|
||||
ptr = strcpy(path, "<error getting the cwd, "
|
||||
"is it too long?>");
|
||||
strcpy(path, "<error getting the cwd, is it too long?>");
|
||||
}
|
||||
retval = strdup(path);
|
||||
} else if (strcmp(param, "module") == 0) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
# include "vpi_config.h"
|
||||
# include "vpi_user.h"
|
||||
# include <cassert>
|
||||
# include <assert.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
/*
|
||||
* The $ivlh_attribute_event implements the VHDL <varname>'event
|
||||
|
|
@ -32,14 +33,28 @@ struct monitor_data {
|
|||
struct t_vpi_time last_event;
|
||||
};
|
||||
|
||||
/*
|
||||
* All the following are called from C so define them for C linkage.
|
||||
*/
|
||||
extern "C" {
|
||||
static struct monitor_data **mdata = 0;
|
||||
static unsigned mdata_count = 0;
|
||||
|
||||
/* To keep valgrind happy free the allocated memory. */
|
||||
static PLI_INT32 cleanup_mdata(p_cb_data cause)
|
||||
{
|
||||
unsigned idx;
|
||||
(void) cause; /* Unused argument. */
|
||||
|
||||
for (idx= 0; idx < mdata_count; idx += 1) {
|
||||
free(mdata[idx]);
|
||||
}
|
||||
free(mdata);
|
||||
mdata = 0;
|
||||
mdata_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 monitor_events(struct t_cb_data*cb)
|
||||
{
|
||||
struct monitor_data*mon = reinterpret_cast<monitor_data*> (cb->user_data);
|
||||
struct monitor_data*mon = (struct monitor_data*)(cb->user_data);
|
||||
|
||||
assert(cb->time);
|
||||
assert(cb->time->type == vpiSimTime);
|
||||
|
|
@ -48,56 +63,71 @@ static PLI_INT32 monitor_events(struct t_cb_data*cb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 ivlh_attribute_event_compiletf(ICARUS_VPI_CONST PLI_BYTE8*)
|
||||
static PLI_INT32 ivlh_attribute_event_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle arg;
|
||||
struct monitor_data*mon;
|
||||
struct t_cb_data cb;
|
||||
struct t_vpi_time tb;
|
||||
|
||||
// Check that there is at least 1 argument...
|
||||
/* Check that there are arguments. */
|
||||
if (argv == 0) {
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
|
||||
vpi_printf("Call to %s missing its argument\n", vpi_get_str(vpiName,sys));
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
|
||||
(int)vpi_get(vpiLineNo, sys));
|
||||
vpi_printf("(compiler error) %s requires a single argument.\n",
|
||||
name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Icarus either returns 0 above or has one argument. */
|
||||
arg = vpi_scan(argv);
|
||||
assert(arg);
|
||||
|
||||
struct monitor_data*monitor_handle = new struct monitor_data;
|
||||
mon = malloc(sizeof(struct monitor_data));
|
||||
/* Add this to the list of data. */
|
||||
mdata_count += 1;
|
||||
mdata = (struct monitor_data **) realloc(mdata,
|
||||
sizeof(struct monitor_data **) *
|
||||
mdata_count);
|
||||
mdata[mdata_count-1] = mon;
|
||||
|
||||
struct t_cb_data cb;
|
||||
struct t_vpi_time tb;
|
||||
tb.type = vpiSimTime;
|
||||
cb.reason = cbValueChange;
|
||||
cb.cb_rtn = monitor_events;
|
||||
cb.obj = arg;
|
||||
cb.time = &tb;
|
||||
cb.value = 0;
|
||||
cb.user_data = reinterpret_cast<char*>(monitor_handle);
|
||||
cb.user_data = (char*) (mon);
|
||||
vpi_register_cb(&cb);
|
||||
vpi_put_userdata(sys, monitor_handle);
|
||||
vpi_put_userdata(sys, mon);
|
||||
|
||||
// check that there is no more then 1 argument
|
||||
/* Check that there are no more then one argument. */
|
||||
arg = vpi_scan(argv);
|
||||
if (arg != 0) {
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
|
||||
vpi_printf("Too many arguments for call to %s.\n", vpi_get_str(vpiName,sys));
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
|
||||
(int)vpi_get(vpiLineNo, sys));
|
||||
vpi_printf("(compiler error) %s only takes a single argument.\n",
|
||||
name);
|
||||
vpi_free_object(argv);
|
||||
vpi_control(vpiFinish, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
|
||||
static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
|
||||
struct t_vpi_value rval;
|
||||
struct monitor_data*mon;
|
||||
(void) name;
|
||||
|
||||
rval.format = vpiScalarVal;
|
||||
|
||||
struct monitor_data*mon = reinterpret_cast<monitor_data*>(vpi_get_userdata(sys));
|
||||
mon = (struct monitor_data*) (vpi_get_userdata(sys));
|
||||
|
||||
if (mon->last_event.type == 0) {
|
||||
rval.value.scalar = vpi0;
|
||||
|
|
@ -105,7 +135,7 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
|
|||
} else {
|
||||
struct t_vpi_time tnow;
|
||||
tnow.type = vpiSimTime;
|
||||
vpi_get_time(0,&tnow);
|
||||
vpi_get_time(0, &tnow);
|
||||
|
||||
rval.value.scalar = vpi1;
|
||||
if (mon->last_event.high != tnow.high)
|
||||
|
|
@ -119,14 +149,16 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 ivlh_attribute_event_sizetf(ICARUS_VPI_CONST PLI_BYTE8*)
|
||||
static PLI_INT32 ivlh_attribute_event_sizetf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||
{
|
||||
(void) name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void vhdl_register(void)
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
s_cb_data cb;
|
||||
vpiHandle res;
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
|
|
@ -138,11 +170,19 @@ static void vhdl_register(void)
|
|||
tf_data.user_data = (PLI_BYTE8 *) "$ivlh_attribute_event";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
/* Create a callback to clear the monitor data memory when the
|
||||
* simulator finishes. */
|
||||
cb.time = NULL;
|
||||
cb.reason = cbEndOfSimulation;
|
||||
cb.cb_rtn = cleanup_mdata;
|
||||
cb.user_data = NULL;
|
||||
cb.obj = NULL;
|
||||
|
||||
vpi_register_cb(&cb);
|
||||
}
|
||||
|
||||
void (*vlog_startup_routines[])() = {
|
||||
vhdl_register,
|
||||
0
|
||||
};
|
||||
|
||||
} /* extern "C" */
|
||||
|
|
@ -27,24 +27,3 @@
|
|||
#define wave_alloca alloca
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Id: wavealloca.h,v 1.3 2009/12/06 00:10:17 gtkwave Exp $
|
||||
* $Log: wavealloca.h,v $
|
||||
* Revision 1.3 2009/12/06 00:10:17 gtkwave
|
||||
* mingw compatibility fix from icarus
|
||||
*
|
||||
* Revision 1.2 2007/08/26 21:35:50 gtkwave
|
||||
* integrated global context management from SystemOfCode2007 branch
|
||||
*
|
||||
* Revision 1.1.1.1.2.1 2007/08/06 03:50:50 gtkwave
|
||||
* globals support for ae2, gtk1, cygwin, mingw. also cleaned up some machine
|
||||
* generated structs, etc.
|
||||
*
|
||||
* Revision 1.1.1.1 2007/05/30 04:27:29 gtkwave
|
||||
* Imported sources
|
||||
*
|
||||
* Revision 1.2 2007/04/20 02:08:18 gtkwave
|
||||
* initial release
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ typedef struct t_vpi_delay {
|
|||
#define vpiSysTaskCall 57
|
||||
#define vpiTask 59
|
||||
#define vpiTimeVar 63
|
||||
#define vpiUdpDefn 66
|
||||
#define vpiUserSystf 67
|
||||
#define vpiNetArray 114
|
||||
#define vpiIndex 78
|
||||
|
|
@ -362,7 +363,7 @@ typedef struct t_vpi_delay {
|
|||
# define vpiSysFuncReal vpiRealFunc
|
||||
# define vpiSysFuncTime vpiTimeFunc
|
||||
# define vpiSysFuncSized vpiSizedFunc
|
||||
#define vpiUserDefn 49
|
||||
#define vpiUserDefn 45
|
||||
#define vpiAutomatic 50
|
||||
#define vpiConstantSelect 53
|
||||
#define vpiSigned 65
|
||||
|
|
|
|||
|
|
@ -101,6 +101,12 @@ void codespace_delete(void)
|
|||
{
|
||||
vvp_code_t cur = first_chunk;
|
||||
|
||||
/* If there are no opcodes then just delete the code space. */
|
||||
if (count_opcodes == 0) {
|
||||
delete [] cur;
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
vvp_code_t next = cur[code_chunk_size-1].cptr;
|
||||
for (unsigned idx = 0 ; idx < code_chunk_size; idx += 1) {
|
||||
|
|
|
|||
|
|
@ -1512,7 +1512,6 @@ void compile_udp_def(int sequ, char *label, char *name,
|
|||
u->compile_table(table);
|
||||
}
|
||||
free(label);
|
||||
delete[] name;
|
||||
}
|
||||
|
||||
char **compile_udp_table(char **table, char *row)
|
||||
|
|
|
|||
33
vvp/delay.cc
33
vvp/delay.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005-2010 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 2005-2011 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
|
||||
|
|
@ -771,6 +771,11 @@ static vpiHandle modpath_src_get_handle(int code, vpiHandle ref)
|
|||
return vpi_handle(scope);
|
||||
}
|
||||
|
||||
// Handles to path term objects should really be obtained via
|
||||
// the vpi_iterate and vpi_scan functions. Continue to allow
|
||||
// them to be obtained here for backwards compatibility with
|
||||
// older versions of Icarus Verilog.
|
||||
|
||||
case vpiModPathIn:
|
||||
return vpi_handle(&rfp->path_term_in);
|
||||
|
||||
|
|
@ -780,6 +785,30 @@ static vpiHandle modpath_src_get_handle(int code, vpiHandle ref)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static vpiHandle modpath_src_iterate(int code, vpiHandle ref)
|
||||
{
|
||||
struct __vpiModPathSrc*rfp = vpip_modpath_src_from_handle(ref);
|
||||
assert(rfp);
|
||||
|
||||
// Module paths with multiple sources or destinations are
|
||||
// currently represented by a separate modpath object for
|
||||
// each source/destination combination, so there is only
|
||||
// ever one input path term and one output path term.
|
||||
switch (code) {
|
||||
case vpiModPathIn: {
|
||||
vpiHandle*args = (vpiHandle*)calloc(1, sizeof(vpiHandle*));
|
||||
args[0] = vpi_handle(&rfp->path_term_in);
|
||||
return vpip_make_iterator(1, args, true);
|
||||
}
|
||||
case vpiModPathOut: {
|
||||
vpiHandle*args = (vpiHandle*)calloc(1, sizeof(vpiHandle*));
|
||||
args[0] = vpi_handle(&rfp->dest->path_term_out);
|
||||
return vpip_make_iterator(1, args, true);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vpiHandle modpath_src_index ( vpiHandle ref, int)
|
||||
{
|
||||
assert(ref->vpi_type->type_code == vpiModPathIn);
|
||||
|
|
@ -946,7 +975,7 @@ static const struct __vpirt vpip_modpath_src_rt = {
|
|||
modpath_src_get_value,
|
||||
modpath_src_put_value,
|
||||
modpath_src_get_handle,
|
||||
0, /* modpath_src_iterate,*/
|
||||
modpath_src_iterate,
|
||||
modpath_src_index,
|
||||
modpath_src_free_object,
|
||||
modpath_src_get_delays,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
# include "compile.h"
|
||||
# include "enum_type.h"
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
# include "vvp_cleanup.h"
|
||||
#endif
|
||||
# include <iostream>
|
||||
# include <cassert>
|
||||
|
||||
|
|
@ -40,6 +43,7 @@ static struct enumconst_s* enumconst_from_handle(vpiHandle obj)
|
|||
struct __vpiEnumTypespec {
|
||||
struct __vpiHandle base;
|
||||
std::vector<enumconst_s> names;
|
||||
int base_type_code;
|
||||
bool is_signed;
|
||||
};
|
||||
|
||||
|
|
@ -60,6 +64,13 @@ static int enum_type_get(int code, vpiHandle obj)
|
|||
case vpiSize:
|
||||
return ref->names.size();
|
||||
|
||||
/* This is not currently set correctly. We always use vpiReg for
|
||||
* four state variables and vpiBitVar for two state variables.
|
||||
* This minimal functionality is needed to get the next() and
|
||||
* prev() methods to work correctly with invalid values. */
|
||||
case vpiBaseTypespec:
|
||||
return ref->base_type_code;
|
||||
|
||||
case vpiSigned:
|
||||
return ref->is_signed;
|
||||
|
||||
|
|
@ -76,7 +87,7 @@ static vpiHandle enum_type_iterate(int code, vpiHandle obj)
|
|||
struct __vpiEnumTypespec*ref = vpip_enum_typespec_from_handle(obj);
|
||||
assert(ref);
|
||||
|
||||
if (code == vpiMember) {
|
||||
if (code == vpiEnumConst) {
|
||||
vpiHandle*args = (vpiHandle*)
|
||||
calloc(ref->names.size(), sizeof(vpiHandle*));
|
||||
for (size_t idx = 0 ; idx < ref->names.size() ; idx += 1)
|
||||
|
|
@ -160,6 +171,7 @@ void compile_enum2_type(char*label, long width, bool signed_flag,
|
|||
spec->base.vpi_type = &enum_type_rt;
|
||||
spec->names = std::vector<enumconst_s> (names->size());
|
||||
spec->is_signed = signed_flag;
|
||||
spec->base_type_code = vpiBitVar;
|
||||
|
||||
size_t idx = 0;
|
||||
for (list<struct enum_name_s>::iterator cur = names->begin()
|
||||
|
|
@ -172,6 +184,7 @@ void compile_enum2_type(char*label, long width, bool signed_flag,
|
|||
|
||||
assert(idx == spec->names.size());
|
||||
compile_vpi_symbol(label, vpi_handle(spec));
|
||||
vpip_attach_to_current_scope(vpi_handle(spec));
|
||||
|
||||
free(label);
|
||||
delete names;
|
||||
|
|
@ -184,6 +197,7 @@ void compile_enum4_type(char*label, long width, bool signed_flag,
|
|||
spec->base.vpi_type = &enum_type_rt;
|
||||
spec->names = std::vector<enumconst_s> (names->size());
|
||||
spec->is_signed = signed_flag;
|
||||
spec->base_type_code = vpiReg;
|
||||
|
||||
size_t idx = 0;
|
||||
for (list<struct enum_name_s>::iterator cur = names->begin()
|
||||
|
|
@ -198,7 +212,22 @@ void compile_enum4_type(char*label, long width, bool signed_flag,
|
|||
|
||||
assert(idx == spec->names.size());
|
||||
compile_vpi_symbol(label, vpi_handle(spec));
|
||||
vpip_attach_to_current_scope(vpi_handle(spec));
|
||||
|
||||
free(label);
|
||||
delete names;
|
||||
}
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void enum_delete(vpiHandle item)
|
||||
{
|
||||
struct __vpiEnumTypespec*obj = (struct __vpiEnumTypespec*) item;
|
||||
|
||||
for (vector<enumconst_s>::iterator iter = obj->names.begin();
|
||||
iter != obj->names.end(); ++ iter ) {
|
||||
delete [] iter->name;
|
||||
}
|
||||
|
||||
delete obj;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
16
vvp/udp.cc
16
vvp/udp.cc
|
|
@ -82,8 +82,9 @@ ostream& operator <<(ostream&o, const struct udp_levels_table&table)
|
|||
return o;
|
||||
}
|
||||
|
||||
vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init, bool type)
|
||||
: ports_(ports), init_(init), seq_(type)
|
||||
vvp_udp_s::vvp_udp_s(char*label, char*name__, unsigned ports,
|
||||
vvp_bit4_t init, bool type)
|
||||
: name_(name__), ports_(ports), init_(init), seq_(type)
|
||||
{
|
||||
if (!udp_table)
|
||||
udp_table = new_symbol_table();
|
||||
|
|
@ -104,6 +105,7 @@ vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init, bool type)
|
|||
|
||||
vvp_udp_s::~vvp_udp_s()
|
||||
{
|
||||
delete[] name_;
|
||||
}
|
||||
|
||||
unsigned vvp_udp_s::port_count() const
|
||||
|
|
@ -116,10 +118,9 @@ vvp_bit4_t vvp_udp_s::get_init() const
|
|||
return init_;
|
||||
}
|
||||
|
||||
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name, unsigned ports)
|
||||
: vvp_udp_s(label, ports, BIT4_X, false)
|
||||
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name__, unsigned ports)
|
||||
: vvp_udp_s(label, name__, ports, BIT4_X, false)
|
||||
{
|
||||
name_ = name;
|
||||
levels0_ = 0;
|
||||
levels1_ = 0;
|
||||
nlevels0_ = 0;
|
||||
|
|
@ -295,11 +296,10 @@ void vvp_udp_comb_s::compile_table(char**tab)
|
|||
assert(nrows1 == nlevels1_);
|
||||
}
|
||||
|
||||
vvp_udp_seq_s::vvp_udp_seq_s(char*label, char*name,
|
||||
vvp_udp_seq_s::vvp_udp_seq_s(char*label, char*name__,
|
||||
unsigned ports, vvp_bit4_t init)
|
||||
: vvp_udp_s(label, ports, init, true)
|
||||
: vvp_udp_s(label, name__, ports, init, true)
|
||||
{
|
||||
name_ = name;
|
||||
levels0_ = 0;
|
||||
levels1_ = 0;
|
||||
levelsx_ = 0;
|
||||
|
|
|
|||
18
vvp/udp.h
18
vvp/udp.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __udp_H
|
||||
#define __udp_H
|
||||
/*
|
||||
* Copyright (c) 2005-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2005-2011 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* (This is a rewrite of code that was ...
|
||||
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>)
|
||||
|
|
@ -30,15 +30,16 @@ struct udp_levels_table;
|
|||
struct vvp_udp_s {
|
||||
|
||||
public:
|
||||
explicit vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init,
|
||||
bool type);
|
||||
explicit vvp_udp_s(char*label, char*name, unsigned ports,
|
||||
vvp_bit4_t init, bool type);
|
||||
virtual ~vvp_udp_s();
|
||||
|
||||
// Return the number of input ports for the defined UDP. This
|
||||
// does *not* include the current output value for a
|
||||
// sequential UDP.
|
||||
unsigned port_count() const;
|
||||
bool is_sequential() const {return seq_;};
|
||||
bool is_sequential() const { return seq_; };
|
||||
char *name() { return name_; }
|
||||
|
||||
// Return the initial output value.
|
||||
vvp_bit4_t get_init() const;
|
||||
|
|
@ -48,6 +49,7 @@ struct vvp_udp_s {
|
|||
vvp_bit4_t cur_out) =0;
|
||||
|
||||
private:
|
||||
char *name_;
|
||||
unsigned ports_;
|
||||
vvp_bit4_t init_;
|
||||
bool seq_;
|
||||
|
|
@ -112,7 +114,7 @@ extern ostream& operator<< (ostream&o, const struct udp_levels_table&t);
|
|||
class vvp_udp_comb_s : public vvp_udp_s {
|
||||
|
||||
public:
|
||||
vvp_udp_comb_s(char*label, char*name, unsigned ports);
|
||||
vvp_udp_comb_s(char*label, char*name__, unsigned ports);
|
||||
~vvp_udp_comb_s();
|
||||
void compile_table(char**tab);
|
||||
|
||||
|
|
@ -125,8 +127,6 @@ class vvp_udp_comb_s : public vvp_udp_s {
|
|||
vvp_bit4_t cur_out);
|
||||
|
||||
private:
|
||||
char*name_;
|
||||
|
||||
// Level sensitive rows of the device.
|
||||
struct udp_levels_table*levels0_;
|
||||
struct udp_levels_table*levels1_;
|
||||
|
|
@ -180,7 +180,7 @@ struct udp_edges_table {
|
|||
class vvp_udp_seq_s : public vvp_udp_s {
|
||||
|
||||
public:
|
||||
vvp_udp_seq_s(char*label, char*name, unsigned ports, vvp_bit4_t init);
|
||||
vvp_udp_seq_s(char*label, char*name__, unsigned ports, vvp_bit4_t init);
|
||||
~vvp_udp_seq_s();
|
||||
|
||||
void compile_table(char**tab);
|
||||
|
|
@ -190,8 +190,6 @@ class vvp_udp_seq_s : public vvp_udp_s {
|
|||
vvp_bit4_t cur_out);
|
||||
|
||||
private:
|
||||
char*name_;
|
||||
|
||||
vvp_bit4_t test_levels_(const udp_levels_table&cur);
|
||||
|
||||
// Level sensitive rows of the device.
|
||||
|
|
|
|||
|
|
@ -262,6 +262,8 @@ static const char* vpi_type_values(PLI_INT32 code)
|
|||
return "vpiByteVar";
|
||||
case vpiConstant:
|
||||
return "vpiConstant";
|
||||
case vpiEnumTypespec:
|
||||
return "vpiEnumTypespec";
|
||||
case vpiFunction:
|
||||
return "vpiFunction";
|
||||
case vpiIntVar:
|
||||
|
|
@ -473,7 +475,7 @@ int vpip_time_precision_from_handle(vpiHandle obj)
|
|||
|
||||
void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
|
||||
{
|
||||
int units;
|
||||
int scale;
|
||||
vvp_time64_t time;
|
||||
|
||||
assert(vp);
|
||||
|
|
@ -487,9 +489,10 @@ void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
|
|||
break;
|
||||
|
||||
case vpiScaledRealTime:
|
||||
units = vpip_time_units_from_handle(obj);
|
||||
vp->real = pow(10.0L, vpip_get_time_precision() - units);
|
||||
vp->real *= time;
|
||||
scale = vpip_get_time_precision() -
|
||||
vpip_time_units_from_handle(obj);
|
||||
if (scale >= 0) vp->real = (double)time * pow(10.0, scale);
|
||||
else vp->real = (double)time / pow(10.0, -scale);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -951,6 +954,7 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
|||
|
||||
if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
|
||||
vvp_time64_t dly;
|
||||
int scale;
|
||||
|
||||
if (vpi_get(vpiAutomatic, obj)) {
|
||||
fprintf(stderr, "vpi error: cannot put a value with "
|
||||
|
|
@ -964,10 +968,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
|||
|
||||
switch (when->type) {
|
||||
case vpiScaledRealTime:
|
||||
dly = (vvp_time64_t)(when->real *
|
||||
(pow(10.0L,
|
||||
vpip_time_units_from_handle(obj) -
|
||||
vpip_get_time_precision())));
|
||||
scale = vpip_time_units_from_handle(obj) -
|
||||
vpip_get_time_precision();
|
||||
if (scale >= 0) {
|
||||
dly = (vvp_time64_t)(when->real * pow(10.0, scale));
|
||||
} else {
|
||||
dly = (vvp_time64_t)(when->real / pow(10.0, -scale));
|
||||
}
|
||||
break;
|
||||
case vpiSimTime:
|
||||
dly = vpip_timestruct_to_time(when);
|
||||
|
|
@ -1047,6 +1054,13 @@ vpiHandle vpi_handle(PLI_INT32 type, vpiHandle ref)
|
|||
return res;
|
||||
}
|
||||
|
||||
static vpiHandle vpip_make_udp_iterator()
|
||||
{
|
||||
// HERE: Add support for iterating over UDP definitions.
|
||||
// See 26.6.16 (page 400 in 1364-2005).
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function asks the object to return an iterator for
|
||||
* the specified reference. It is up to the iterate_ method to
|
||||
|
|
@ -1058,6 +1072,9 @@ static vpiHandle vpi_iterate_global(int type)
|
|||
case vpiModule:
|
||||
return vpip_make_root_iterator();
|
||||
|
||||
case vpiUdpDefn:
|
||||
return vpip_make_udp_iterator();
|
||||
|
||||
case vpiUserSystf:
|
||||
return vpip_make_systf_iterator();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,9 @@ static void delete_sub_scopes(struct __vpiScope *scope)
|
|||
case vpiRealVar:
|
||||
real_delete((scope->intern)[idx]);
|
||||
break;
|
||||
case vpiEnumTypespec:
|
||||
enum_delete((scope->intern)[idx]);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Need support for type: %d\n",
|
||||
scope->intern[idx]->vpi_type->type_code);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2011 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
|
||||
|
|
@ -55,14 +55,12 @@ vvp_time64_t vpip_timestruct_to_time(const struct t_vpi_time*ts)
|
|||
|
||||
double vpip_time_to_scaled_real(vvp_time64_t ti, struct __vpiScope*scope)
|
||||
{
|
||||
int units;
|
||||
if (scope)
|
||||
units = scope->time_units;
|
||||
else
|
||||
units = vpi_time_precision;
|
||||
double val;
|
||||
int scale = 0;
|
||||
if (scope) scale = vpi_time_precision - scope->time_units;
|
||||
|
||||
double val = pow(10.0L, vpi_time_precision - units);
|
||||
val *= ti;
|
||||
if (scale >= 0) val = (double)ti * pow(10.0, scale);
|
||||
else val = (double)ti / pow(10.0, -scale);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2010 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 2008-2011 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 2002 Larry Doolittle (larry@doolittle.boa.org)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -121,7 +121,7 @@ unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
|
|||
char *buf, unsigned int nbuf,
|
||||
int signed_flag)
|
||||
{
|
||||
unsigned int idx, len, vlen;
|
||||
unsigned int idx, vlen;
|
||||
unsigned int mbits=vec4.size(); /* number of non-sign bits */
|
||||
unsigned count_x = 0, count_z = 0;
|
||||
|
||||
|
|
@ -186,19 +186,15 @@ unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
|
|||
}
|
||||
|
||||
if (count_x == vec4.size()) {
|
||||
len = 1;
|
||||
buf[0] = 'x';
|
||||
buf[1] = 0;
|
||||
} else if (count_x > 0) {
|
||||
len = 1;
|
||||
buf[0] = 'X';
|
||||
buf[1] = 0;
|
||||
} else if (count_z == vec4.size()) {
|
||||
len = 1;
|
||||
buf[0] = 'z';
|
||||
buf[1] = 0;
|
||||
} else if (count_z > 0) {
|
||||
len = 1;
|
||||
buf[0] = 'Z';
|
||||
buf[1] = 0;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __vvp_cleanup_H
|
||||
#define __vvp_cleanup_H
|
||||
/*
|
||||
* Copyright (c) 2009 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (c) 2009-2011 Cary R. (cygcary@yahoo.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
|
||||
|
|
@ -43,6 +43,7 @@ extern void A_delete(struct __vpiHandle *item);
|
|||
extern void PV_delete(struct __vpiHandle *item);
|
||||
extern void constant_delete(struct __vpiHandle *item);
|
||||
extern void contexts_delete(struct __vpiScope *scope);
|
||||
extern void enum_delete(struct __vpiHandle *item);
|
||||
extern void memory_delete(struct __vpiHandle *item);
|
||||
extern void named_event_delete(struct __vpiHandle *item);
|
||||
extern void parameter_delete(struct __vpiHandle *item);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
# include <valgrind/memcheck.h>
|
||||
# include <map>
|
||||
# include "sfunc.h"
|
||||
# include "udp.h"
|
||||
# include "ivl_alloc.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -85,6 +86,7 @@ void* vvp_net_t::operator new (size_t size)
|
|||
#ifdef CHECK_WITH_VALGRIND
|
||||
static map<vvp_net_t*, bool> vvp_net_map;
|
||||
static map<sfunc_core*, bool> sfunc_map;
|
||||
static map<vvp_udp_fun_core*, bool> udp_map;
|
||||
static vvp_net_t **local_net_pool = 0;
|
||||
static unsigned local_net_pool_count = 0;
|
||||
|
||||
|
|
@ -102,6 +104,9 @@ void vvp_net_delete(vvp_net_t *item)
|
|||
if (sfunc_core*tmp = dynamic_cast<sfunc_core*> (item->fun)) {
|
||||
sfunc_map[tmp] = true;
|
||||
}
|
||||
if (vvp_udp_fun_core*tmp = dynamic_cast<vvp_udp_fun_core*> (item->fun)) {
|
||||
udp_map[tmp] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_net_pool_delete()
|
||||
|
|
@ -128,6 +133,12 @@ void vvp_net_pool_delete()
|
|||
}
|
||||
sfunc_map.clear();
|
||||
|
||||
map<vvp_udp_fun_core*, bool>::iterator uiter;
|
||||
for (uiter = udp_map.begin(); uiter != udp_map.end(); ++ uiter ) {
|
||||
delete uiter->first;
|
||||
}
|
||||
udp_map.clear();
|
||||
|
||||
if (RUNNING_ON_VALGRIND && (vvp_nets_del != count_vvp_nets)) {
|
||||
fflush(NULL);
|
||||
VALGRIND_PRINTF("Error: vvp missed deleting %ld of %lu net(s).",
|
||||
|
|
|
|||
Loading…
Reference in New Issue