Merge branch 'master' into work9
This commit is contained in:
commit
5e4c0c9783
|
|
@ -64,7 +64,7 @@ fi
|
||||||
# AX_WIN32
|
# AX_WIN32
|
||||||
# --------
|
# --------
|
||||||
# Combined check for several flavors of Microsoft Windows so
|
# 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_DEFUN([AX_WIN32],
|
||||||
[AC_MSG_CHECKING([for Microsoft Windows])
|
[AC_MSG_CHECKING([for Microsoft Windows])
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST]) []dnl
|
AC_REQUIRE([AC_CANONICAL_HOST]) []dnl
|
||||||
|
|
@ -230,6 +230,17 @@ case "${host}" in
|
||||||
esac
|
esac
|
||||||
])# AX_CPP_PRECOMP
|
])# 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.
|
# When config.status generates a header, we must update the stamp-h file.
|
||||||
# This file resides in the same directory as the config header
|
# This file resides in the same directory as the config header
|
||||||
# that is generated. The stamp file name are based on the header name.
|
# 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
|
# may modify CPPFLAGS and CFLAGS
|
||||||
AX_CPP_PRECOMP
|
AX_CPP_PRECOMP
|
||||||
|
|
||||||
|
# may modify LDFLAGS
|
||||||
|
AX_C99_STRTOD
|
||||||
|
|
||||||
# Processor specific compile flags
|
# Processor specific compile flags
|
||||||
case "${host}" in
|
case "${host}" in
|
||||||
alpha*-*-linux*)
|
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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <string.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;
|
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,
|
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid, unsigned flags) const
|
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,
|
return elaborate_access_func_(des, scope, access_nature,
|
||||||
expr_wid);
|
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_
|
cerr << get_fileline() << ": error: No function named `" << path_
|
||||||
<< "' found in this context (" << scope_path(scope) << ")."
|
<< "' found in this context (" << scope_path(scope) << ")."
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
@ -2087,73 +2277,32 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
// Maybe this is a method attached to an enumeration name? If
|
// Maybe this is a method attached to an enumeration name? If
|
||||||
// this is system verilog, then test to see if the name is
|
// this is system verilog, then test to see if the name is
|
||||||
// really a method attached to an object.
|
// really a method attached to an object.
|
||||||
|
|
||||||
if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
|
if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
|
||||||
pform_name_t use_path = path_;
|
pform_name_t use_path = path_;
|
||||||
perm_string method_name = peek_tail_name(use_path);
|
perm_string method_name = peek_tail_name(use_path);
|
||||||
use_path.pop_back();
|
use_path.pop_back();
|
||||||
|
|
||||||
found_in = symbol_search(this, des, scope, use_path,
|
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) {
|
if (net != 0) {
|
||||||
// Special case: The net is an enum, and the
|
|
||||||
// method name is "num".
|
|
||||||
netenum_t*netenum = net->enumeration();
|
netenum_t*netenum = net->enumeration();
|
||||||
if (netenum && method_name == "num") {
|
if (netenum) {
|
||||||
NetEConst*tmp = make_const_val(netenum->size());
|
// We may need the net expression for the
|
||||||
tmp->set_line(*this);
|
// enumeration variable so get it.
|
||||||
return tmp;
|
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
|
/* Elaborate wait expression. Don't eval yet, we will do that
|
||||||
shortly, after we apply a reduction or. */
|
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);
|
pe->test_width(des, scope, mode);
|
||||||
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(),
|
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(),
|
||||||
PExpr::NO_FLAGS);
|
PExpr::NO_FLAGS);
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,6 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||||
left_->expr_type() == IVL_VT_REAL)
|
left_->expr_type() == IVL_VT_REAL)
|
||||||
return eval_leeq_real_(left_, right_, true);
|
return eval_leeq_real_(left_, right_, true);
|
||||||
// assert(expr_type() == IVL_VT_LOGIC);
|
// assert(expr_type() == IVL_VT_LOGIC);
|
||||||
// HERE
|
|
||||||
|
|
||||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||||
if (r == 0) return 0;
|
if (r == 0) return 0;
|
||||||
|
|
@ -1090,7 +1089,6 @@ NetEConst* NetEBShift::eval_tree()
|
||||||
|
|
||||||
NetEConst* NetEConcat::eval_tree()
|
NetEConst* NetEConcat::eval_tree()
|
||||||
{
|
{
|
||||||
// HERE
|
|
||||||
unsigned repeat_val = repeat();
|
unsigned repeat_val = repeat();
|
||||||
unsigned local_errors = 0;
|
unsigned local_errors = 0;
|
||||||
|
|
||||||
|
|
@ -1182,7 +1180,6 @@ NetEConst* NetEConcat::eval_tree()
|
||||||
|
|
||||||
NetEConst* NetESelect::eval_tree()
|
NetEConst* NetESelect::eval_tree()
|
||||||
{
|
{
|
||||||
// HERE
|
|
||||||
if (debug_eval_tree) {
|
if (debug_eval_tree) {
|
||||||
cerr << get_fileline() << ": debug: Evaluating expression:"
|
cerr << get_fileline() << ": debug: Evaluating expression:"
|
||||||
<< *this << endl;
|
<< *this << endl;
|
||||||
|
|
@ -1846,7 +1843,6 @@ static NetExpr* evaluate_min_max(NetExpr*&arg0_, NetExpr*&arg1_,
|
||||||
|
|
||||||
NetExpr* NetESFunc::eval_tree()
|
NetExpr* NetESFunc::eval_tree()
|
||||||
{
|
{
|
||||||
// HERE
|
|
||||||
/* If we are not targeting at least Verilog-2005, Verilog-AMS
|
/* If we are not targeting at least Verilog-2005, Verilog-AMS
|
||||||
* or using the Icarus misc flag then we do not support these
|
* or using the Icarus misc flag then we do not support these
|
||||||
* functions as constant. */
|
* functions as constant. */
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ modules, then exit. It is a convenience for makefiles or automated
|
||||||
plug-in installers.
|
plug-in installers.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B --cflags, --ldflags and -ldlibs
|
.B --cflags, --ldflags and --ldlibs
|
||||||
These flags provide compile time information.
|
These flags provide compile time information.
|
||||||
|
|
||||||
.SH "PC-ONLY OPTIONS"
|
.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) {
|
for (idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1) {
|
||||||
size_t next_len = 6 + strlen(vhdlpp_libdir[idx]);
|
size_t next_len = 6 + strlen(vhdlpp_libdir[idx]);
|
||||||
libs = realloc(libs, liblen+next_len);
|
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;
|
liblen = strlen(libs) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdlen += liblen;
|
cmdlen += liblen;
|
||||||
|
|
||||||
char*cmd = malloc(cmdlen);
|
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)
|
if (verbose_flag)
|
||||||
fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
|
fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
|
||||||
|
|
|
||||||
10
ivlpp/main.c
10
ivlpp/main.c
|
|
@ -1,5 +1,5 @@
|
||||||
const char COPYRIGHT[] =
|
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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -457,6 +457,14 @@ int main(int argc, char*argv[])
|
||||||
}
|
}
|
||||||
free(include_dir);
|
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();
|
free_macros();
|
||||||
|
|
||||||
return error_count;
|
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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -83,9 +83,24 @@ PLI_INT32 tf_getlongtime(PLI_INT32 *high)
|
||||||
return tf_igetlongtime(high, 0);
|
return tf_igetlongtime(high, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Alias for commercial simulators */
|
/*
|
||||||
PLI_INT32 tf_getlongsimtime(PLI_INT32 *high) \
|
* This function is not defined in the IEE standard, but is provided for
|
||||||
__attribute__ ((weak, alias ("tf_getlongtime")));
|
* 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,
|
void tf_scale_longdelay(void*obj, PLI_INT32 low, PLI_INT32 high,
|
||||||
PLI_INT32 *alow, PLI_INT32 *ahigh)
|
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
|
// Provide dummies
|
||||||
struct tms { int x; };
|
struct tms { int x; };
|
||||||
inline static void times(struct tms *) { }
|
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)
|
#endif // ! defined(HAVE_TIMES)
|
||||||
|
|
||||||
static void EOC_cleanup(void)
|
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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -62,7 +62,7 @@ perm_string netenum_t::find_value(const verinum&val) const
|
||||||
{
|
{
|
||||||
perm_string res;
|
perm_string res;
|
||||||
for(netenum_t::iterator cur = names_map_.begin();
|
for(netenum_t::iterator cur = names_map_.begin();
|
||||||
cur != names_map_.end(); cur++) {
|
cur != names_map_.end(); ++ cur) {
|
||||||
if (cur->second == val) {
|
if (cur->second == val) {
|
||||||
res = cur->first;
|
res = cur->first;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -589,8 +589,7 @@ void eval_expr(NetExpr*&expr, int context_width)
|
||||||
// The expression is a constant, so resize it if needed.
|
// The expression is a constant, so resize it if needed.
|
||||||
if (ce->expr_width() < (unsigned)context_width) {
|
if (ce->expr_width() < (unsigned)context_width) {
|
||||||
expr = pad_to_width(expr, context_width, *expr);
|
expr = pad_to_width(expr, context_width, *expr);
|
||||||
}
|
} else if (ce->expr_width() > (unsigned)context_width) {
|
||||||
if (ce->expr_width() > (unsigned)context_width) {
|
|
||||||
verinum value(ce->value(), context_width);
|
verinum value(ce->value(), context_width);
|
||||||
ce = new NetEConst(value);
|
ce = new NetEConst(value);
|
||||||
ce->set_line(*expr);
|
ce->set_line(*expr);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __sv_vpi_user_H
|
#ifndef __sv_vpi_user_H
|
||||||
#define __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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -54,6 +54,9 @@ EXTERN_C_START
|
||||||
#define vpiEnumTypespec 633
|
#define vpiEnumTypespec 633
|
||||||
#define vpiEnumConst 634
|
#define vpiEnumConst 634
|
||||||
|
|
||||||
|
/********* One-to-One ***********/
|
||||||
|
#define vpiBaseTypespec 703
|
||||||
|
|
||||||
/********* Many-to-One ***********/
|
/********* Many-to-One ***********/
|
||||||
#define vpiMember 742
|
#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()) {
|
switch (net->type()) {
|
||||||
case NetUReduce::NONE:
|
case NetUReduce::NONE:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
delete obj;
|
||||||
return false;
|
return false;
|
||||||
case NetUReduce::AND:
|
case NetUReduce::AND:
|
||||||
obj->type = IVL_LPM_RE_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;
|
ivl_nexus_t nex;
|
||||||
nex = ivl_lpm_q(net);
|
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);
|
nex = ivl_lpm_data(net, 0);
|
||||||
fprintf(out, " DataA: %p\n", nex);
|
fprintf(out, " DataA: %p\n", nex);
|
||||||
|
|
@ -247,7 +247,7 @@ static void show_lpm_abs(ivl_lpm_t net)
|
||||||
ivl_lpm_basename(net), width);
|
ivl_lpm_basename(net), width);
|
||||||
|
|
||||||
nex = ivl_lpm_q(net);
|
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);
|
nex = ivl_lpm_data(net, 0);
|
||||||
fprintf(out, " D: %p\n", nex);
|
fprintf(out, " D: %p\n", nex);
|
||||||
|
|
@ -690,6 +690,7 @@ static void show_lpm_re(ivl_lpm_t net)
|
||||||
break;
|
break;
|
||||||
case IVL_LPM_RE_NOR:
|
case IVL_LPM_RE_NOR:
|
||||||
type = "NOR";
|
type = "NOR";
|
||||||
|
break;
|
||||||
case IVL_LPM_RE_XOR:
|
case IVL_LPM_RE_XOR:
|
||||||
type = "XOR";
|
type = "XOR";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* VHDL code generation for statements.
|
* 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
|
* 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
|
* 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);
|
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++) {
|
for (unsigned i = 0; i < swid; i++) {
|
||||||
// Generate a comparison for this bit position
|
// Generate a comparison for this bit position
|
||||||
vhdl_binop_expr *cmp;
|
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
|
// 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
|
// then check against a constant 'x' for the out of bound bits
|
||||||
// otherwise skip the check (casex).
|
// 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) {
|
if (is_casez) {
|
||||||
// Get the current test bit.
|
// Get the current test bit.
|
||||||
type = vhdl_type::nunsigned(width);
|
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);
|
emit_nexus_as_ca(scope, nex);
|
||||||
if (have_data | have_sset) fprintf(vlog_out, " & ");
|
if (have_data | have_sset) fprintf(vlog_out, " & ");
|
||||||
if (have_data & have_sset) fprintf(vlog_out, "(");
|
if (have_data & have_sset) fprintf(vlog_out, "(");
|
||||||
emitted = 1;
|
|
||||||
}
|
}
|
||||||
nex = ivl_lpm_sync_set(lpm);
|
nex = ivl_lpm_sync_set(lpm);
|
||||||
if (nex) {
|
if (nex) {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
# include "vlog95_priv.h"
|
# include "vlog95_priv.h"
|
||||||
|
# include "ivl_alloc.h"
|
||||||
|
|
||||||
static void emit_entry(ivl_udp_t udp, char entry, unsigned *rerun)
|
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) ||
|
if (ivl_signal_width(lsig) > ivl_signal_width(rsig) ||
|
||||||
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
|
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
|
||||||
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s signal to "
|
/* Normalize the bit/part select. */
|
||||||
"a bit/part select.\n", ivl_expr_file(rval),
|
long real_msb = ivl_signal_msb(lsig);
|
||||||
ivl_expr_lineno(rval), command_name);
|
long real_lsb = ivl_signal_lsb(lsig);
|
||||||
exit(1);
|
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. */
|
/* 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_immediate(lword_idx, IMM_WID, 0));
|
||||||
assert(! number_is_unknown(lword_idx));
|
assert(! number_is_unknown(lword_idx));
|
||||||
use_lword = get_number_immediate(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) {
|
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_immediate(rword_idx, IMM_WID, 0));
|
||||||
assert(! number_is_unknown(rword_idx));
|
assert(! number_is_unknown(rword_idx));
|
||||||
use_rword = get_number_immediate(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, " %s/link", command_name);
|
||||||
fprintf(vvp_out, " v%p_%lu", lsig, use_lword);
|
fprintf(vvp_out, " v%p_%lu", lsig, use_lword);
|
||||||
fprintf(vvp_out, ", v%p_%lu;\n", rsig, use_rword);
|
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)
|
ExpAggregate::element_t::element_t(list<choice_t*>*fields, Expression*val)
|
||||||
: fields_(fields? fields->size() : 0), val_(val)
|
: fields_(fields? fields->size() : 0), val_(val)
|
||||||
{
|
{
|
||||||
size_t idx = 0;
|
|
||||||
if (fields) {
|
if (fields) {
|
||||||
|
size_t idx = 0;
|
||||||
while (! fields->empty()) {
|
while (! fields->empty()) {
|
||||||
assert(idx < fields_.size());
|
assert(idx < fields_.size());
|
||||||
fields_[idx++] = fields->front();
|
fields_[idx++] = fields->front();
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ static bool is_based_correct(char* text)
|
||||||
if(base == 0)
|
if(base == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bool point = 0;
|
bool point = false;
|
||||||
set<char> allowed_chars;
|
set<char> allowed_chars;
|
||||||
|
|
||||||
unsigned c;
|
unsigned c;
|
||||||
|
|
@ -299,12 +299,12 @@ static bool is_based_correct(char* text)
|
||||||
if(*ptr == '.')
|
if(*ptr == '.')
|
||||||
{
|
{
|
||||||
//we found a dot and another one was already found
|
//we found a dot and another one was already found
|
||||||
if(point == 1)
|
if(point)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//notice the fact of finding a point and continue, without increasing the length
|
//notice the fact of finding a point and continue, without increasing the length
|
||||||
point = 1;
|
point = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,10 @@ const char NOTICE[] =
|
||||||
# include <getopt.h>
|
# include <getopt.h>
|
||||||
#endif
|
#endif
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
# include <io.h>
|
||||||
|
# define mkdir(path, mode) _mkdir(path)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool verbose_flag = false;
|
bool verbose_flag = false;
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ class Scope : public ScopeBase {
|
||||||
class ActiveScope : public ScopeBase {
|
class ActiveScope : public ScopeBase {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ActiveScope() { }
|
ActiveScope() : context_entity_(0) { }
|
||||||
ActiveScope(ActiveScope*par) : ScopeBase(*par), context_entity_(0) { }
|
ActiveScope(ActiveScope*par) : ScopeBase(*par), context_entity_(0) { }
|
||||||
|
|
||||||
~ActiveScope() { }
|
~ActiveScope() { }
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ va_math.vpi: $V ../vvp/libvpi.a
|
||||||
$(CC) @shared@ -o $@ $V -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS)
|
$(CC) @shared@ -o $@ $V -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS)
|
||||||
|
|
||||||
vhdl_sys.vpi: $(VHDL_SYS) ../vvp/libvpi.a
|
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
|
stamp-vpi_config-h: $(srcdir)/vpi_config.h.in ../config.status
|
||||||
@rm -f $@
|
@rm -f $@
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,23 @@
|
||||||
// problems will not be fixed.
|
// problems will not be fixed.
|
||||||
|
|
||||||
// fstapi.c from GTKWave
|
// fstapi.c from GTKWave
|
||||||
variableScope:fstapi.c:1689
|
variableScope:fstapi.c:1713
|
||||||
variableScope:fstapi.c:1817
|
variableScope:fstapi.c:1841
|
||||||
variableScope:fstapi.c:1911
|
variableScope:fstapi.c:1935
|
||||||
variableScope:fstapi.c:1912
|
variableScope:fstapi.c:1936
|
||||||
variableScope:fstapi.c:2617
|
variableScope:fstapi.c:2642
|
||||||
variableScope:fstapi.c:2937
|
variableScope:fstapi.c:2962
|
||||||
variableScope:fstapi.c:2941
|
variableScope:fstapi.c:2966
|
||||||
variableScope:fstapi.c:2942
|
variableScope:fstapi.c:2967
|
||||||
|
variableScope:fstapi.c:4641
|
||||||
|
|
||||||
// lxt2_write.c from GTKWave
|
// lxt2_write.c from GTKWave
|
||||||
variableScope:lxt2_write.c:63
|
variableScope:lxt2_write.c:63
|
||||||
variableScope:lxt2_write.c:523
|
variableScope:lxt2_write.c:523
|
||||||
variableScope:lxt2_write.c:581
|
variableScope:lxt2_write.c:581
|
||||||
variableScope:lxt2_write.c:587
|
variableScope:lxt2_write.c:587
|
||||||
variableScope:lxt2_write.c:1602
|
variableScope:lxt2_write.c:1600
|
||||||
variableScope:lxt2_write.c:2049
|
variableScope:lxt2_write.c:2047
|
||||||
|
|
||||||
// lxt_write.c from GTKWave
|
// lxt_write.c from GTKWave
|
||||||
variableScope:lxt_write.c:31
|
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
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* 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 skip_writing_section_hdr : 1;
|
||||||
unsigned size_limit_locked : 1;
|
unsigned size_limit_locked : 1;
|
||||||
unsigned section_header_only : 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 */
|
/* 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 */
|
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
|
* 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
|
#ifdef FST_DEBUG
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
@ -1409,7 +1148,7 @@ for(i=0;i<xc->maxhandle;i++)
|
||||||
JudyHSFreeArray(&PJHSArray, NULL);
|
JudyHSFreeArray(&PJHSArray, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free(packmem); packmem = NULL; packmemlen = 0;
|
free(packmem); packmem = NULL; /* packmemlen = 0; */ /* scan-build */
|
||||||
|
|
||||||
prevpos = 0; zerocnt = 0;
|
prevpos = 0; zerocnt = 0;
|
||||||
free(scratchpad); scratchpad = NULL;
|
free(scratchpad); scratchpad = NULL;
|
||||||
|
|
@ -1449,7 +1188,7 @@ for(i=0;i<xc->maxhandle;i++)
|
||||||
}
|
}
|
||||||
if(zerocnt)
|
if(zerocnt)
|
||||||
{
|
{
|
||||||
fpos += fstWriterVarint(f, (zerocnt << 1));
|
/* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */
|
||||||
}
|
}
|
||||||
#ifdef FST_DEBUG
|
#ifdef FST_DEBUG
|
||||||
printf("value chains: %d\n", cnt);
|
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
|
* functions to set miscellaneous header/block information
|
||||||
*/
|
*/
|
||||||
|
|
@ -1940,9 +1964,10 @@ if(xc)
|
||||||
}
|
}
|
||||||
else
|
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++;
|
xc->tchn_cnt++;
|
||||||
fstWriterVarint(xc->tchn_handle, xc->curtime);
|
fstWriterVarint(xc->tchn_handle, xc->curtime);
|
||||||
}
|
}
|
||||||
|
|
@ -3359,7 +3384,10 @@ uint64_t tsec_nitems;
|
||||||
int secnum = 0;
|
int secnum = 0;
|
||||||
int blocks_skipped = 0;
|
int blocks_skipped = 0;
|
||||||
off_t blkpos = 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;
|
uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle;
|
||||||
off_t vc_start;
|
off_t vc_start;
|
||||||
off_t indx_pntr, indx_pos;
|
off_t indx_pntr, indx_pos;
|
||||||
|
|
@ -3414,7 +3442,10 @@ for(;;)
|
||||||
if(!seclen) break;
|
if(!seclen) break;
|
||||||
|
|
||||||
beg_tim = fstReaderUint64(xc->f);
|
beg_tim = fstReaderUint64(xc->f);
|
||||||
end_tim = fstReaderUint64(xc->f);
|
#ifdef FST_DEBUG
|
||||||
|
end_tim =
|
||||||
|
#endif
|
||||||
|
fstReaderUint64(xc->f);
|
||||||
|
|
||||||
if(xc->limit_range_valid)
|
if(xc->limit_range_valid)
|
||||||
{
|
{
|
||||||
|
|
@ -3443,8 +3474,8 @@ for(;;)
|
||||||
{
|
{
|
||||||
unsigned char *ucdata;
|
unsigned char *ucdata;
|
||||||
unsigned char *cdata;
|
unsigned char *cdata;
|
||||||
unsigned long destlen = tsec_uclen;
|
unsigned long destlen /* = tsec_uclen */; /* scan-build */
|
||||||
unsigned long sourcelen = tsec_clen;
|
unsigned long sourcelen /*= tsec_clen */; /* scan-build */
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char *tpnt;
|
unsigned char *tpnt;
|
||||||
uint64_t tpval;
|
uint64_t tpval;
|
||||||
|
|
@ -3896,12 +3927,12 @@ for(;;)
|
||||||
unsigned char val;
|
unsigned char val;
|
||||||
if(!(vli & 1))
|
if(!(vli & 1))
|
||||||
{
|
{
|
||||||
tdelta = vli >> 2;
|
/* tdelta = vli >> 2; */ /* scan-build */
|
||||||
val = ((vli >> 1) & 1) | '0';
|
val = ((vli >> 1) & 1) | '0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tdelta = vli >> 4;
|
/* tdelta = vli >> 4; */ /* scan-build */
|
||||||
val = FST_RCV_STR[((vli >> 1) & 7)];
|
val = FST_RCV_STR[((vli >> 1) & 7)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3946,7 +3977,7 @@ for(;;)
|
||||||
|
|
||||||
vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
|
vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
|
||||||
len = fstGetVarint32(mem_for_traversal + headptr[idx] + skiplen, &skiplen2);
|
len = fstGetVarint32(mem_for_traversal + headptr[idx] + skiplen, &skiplen2);
|
||||||
tdelta = vli >> 1;
|
/* tdelta = vli >> 1; */ /* scan-build */
|
||||||
skiplen += skiplen2;
|
skiplen += skiplen2;
|
||||||
vdata = mem_for_traversal + headptr[idx] + skiplen;
|
vdata = mem_for_traversal + headptr[idx] + skiplen;
|
||||||
|
|
||||||
|
|
@ -4002,7 +4033,7 @@ for(;;)
|
||||||
unsigned char *vdata;
|
unsigned char *vdata;
|
||||||
|
|
||||||
vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
|
vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
|
||||||
tdelta = vli >> 1;
|
/* tdelta = vli >> 1; */ /* scan-build */
|
||||||
vdata = mem_for_traversal + headptr[idx] + skiplen;
|
vdata = mem_for_traversal + headptr[idx] + skiplen;
|
||||||
|
|
||||||
if(xc->signal_typs[idx] != FST_VT_VCD_REAL)
|
if(xc->signal_typs[idx] != FST_VT_VCD_REAL)
|
||||||
|
|
@ -4058,7 +4089,7 @@ for(;;)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double d;
|
double d;
|
||||||
unsigned char *clone_d = (unsigned char *)&d;
|
unsigned char *clone_d /*= (unsigned char *)&d */; /* scan-build */
|
||||||
unsigned char buf[8];
|
unsigned char buf[8];
|
||||||
unsigned char *srcdata;
|
unsigned char *srcdata;
|
||||||
|
|
||||||
|
|
@ -4261,7 +4292,9 @@ uint64_t seclen;
|
||||||
uint64_t tsec_uclen = 0, tsec_clen = 0;
|
uint64_t tsec_uclen = 0, tsec_clen = 0;
|
||||||
uint64_t tsec_nitems;
|
uint64_t tsec_nitems;
|
||||||
uint64_t frame_uclen, frame_clen;
|
uint64_t frame_uclen, frame_clen;
|
||||||
|
#ifdef FST_DEBUG
|
||||||
uint64_t mem_required_for_traversal;
|
uint64_t mem_required_for_traversal;
|
||||||
|
#endif
|
||||||
off_t indx_pntr, indx_pos;
|
off_t indx_pntr, indx_pos;
|
||||||
long chain_clen;
|
long chain_clen;
|
||||||
unsigned char *chain_cmem;
|
unsigned char *chain_cmem;
|
||||||
|
|
@ -4352,7 +4385,11 @@ for(;;)
|
||||||
xc->rvat_beg_tim = beg_tim;
|
xc->rvat_beg_tim = beg_tim;
|
||||||
xc->rvat_end_tim = end_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
|
#ifdef FST_DEBUG
|
||||||
printf("rvat sec: %d seclen: %d begtim: %d endtim: %d\n",
|
printf("rvat sec: %d seclen: %d begtim: %d endtim: %d\n",
|
||||||
secnum, (int)seclen, (int)beg_tim, (int)end_tim);
|
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 *ucdata;
|
||||||
unsigned char *cdata;
|
unsigned char *cdata;
|
||||||
unsigned long destlen = tsec_uclen;
|
unsigned long destlen /* = tsec_uclen */; /* scan-build */
|
||||||
unsigned long sourcelen = tsec_clen;
|
unsigned long sourcelen /* = tsec_clen */; /* scan-build */
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char *tpnt;
|
unsigned char *tpnt;
|
||||||
uint64_t tpval;
|
uint64_t tpval;
|
||||||
|
|
@ -4628,7 +4665,7 @@ if(xc->signal_lens[facidx] == 1)
|
||||||
iprev = i;
|
iprev = i;
|
||||||
pvli = vli;
|
pvli = vli;
|
||||||
ptidx = tidx;
|
ptidx = tidx;
|
||||||
pskip = skiplen;
|
/* pskip = skiplen; */ /* scan-build */
|
||||||
|
|
||||||
tidx += tdelta;
|
tidx += tdelta;
|
||||||
i+=skiplen;
|
i+=skiplen;
|
||||||
|
|
|
||||||
|
|
@ -1144,7 +1144,7 @@ unsigned int total_chgs;
|
||||||
unsigned int partial_length;
|
unsigned int partial_length;
|
||||||
|
|
||||||
total_chgs = 0;
|
total_chgs = 0;
|
||||||
partial_length = 0;
|
/* partial_length = 0; */ /* scan-build : never read */
|
||||||
|
|
||||||
iter_hi = iter + partial_iter;
|
iter_hi = iter + partial_iter;
|
||||||
if(iter_hi > lt->numfacs) iter_hi = lt->numfacs;
|
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)) )
|
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"); */
|
/* fprintf(stderr, "initial value burst timepos==0, timegranule==0\n"); */
|
||||||
if(lt->blackout)
|
if(lt->blackout)
|
||||||
{
|
{
|
||||||
|
|
@ -1501,7 +1499,7 @@ if(lt)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s = lt->symchain;
|
struct lxt2_wr_symbol *s = lt->symchain;
|
||||||
while(s)
|
while(s)
|
||||||
{
|
{
|
||||||
if((!(s->flags&LXT2_WR_SYM_F_ALIAS))&&(s->rows<2))
|
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,
|
static void get_time_real(char *rtn, double value, int prec,
|
||||||
PLI_INT32 time_units)
|
PLI_INT32 time_units)
|
||||||
{
|
{
|
||||||
/* Scale the value if its time units differ from the format units. */
|
/* Scale the value from its time units to the format time units. */
|
||||||
if (time_units != timeformat_info.units) {
|
if (time_units >= timeformat_info.units) {
|
||||||
value *= pow(10.0, 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);
|
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);
|
strcpy(cpb+pad, cp);
|
||||||
|
|
||||||
/* If a width was not given, use the default, unless we have a
|
/* 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) {
|
if (width == -1) {
|
||||||
width = (ld_zero == 1) ? 0 : vpi_get_dec_size(info->items[*idx]);
|
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,
|
static unsigned int get_numeric(char **rtn, const struct strobe_cb_info *info,
|
||||||
vpiHandle item)
|
vpiHandle item)
|
||||||
{
|
{
|
||||||
int size;
|
int size, min;
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
|
|
||||||
val.format = info->default_format;
|
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){
|
switch(info->default_format){
|
||||||
case vpiDecStrVal:
|
case vpiDecStrVal:
|
||||||
size = vpi_get_dec_size(item);
|
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));
|
*rtn = malloc((size+1)*sizeof(char));
|
||||||
sprintf(*rtn, "%*s", size, val.value.str);
|
sprintf(*rtn, "%*s", size, val.value.str);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ static PLI_INT32 task_not_implemented_compiletf(ICARUS_VPI_CONST PLI_BYTE8* name
|
||||||
{
|
{
|
||||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
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),
|
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
||||||
name);
|
name);
|
||||||
vpi_control(vpiFinish, 1);
|
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);
|
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),
|
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
||||||
name);
|
name);
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
|
|
|
||||||
|
|
@ -524,7 +524,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
struct t_cb_data cb;
|
struct t_cb_data cb;
|
||||||
struct vcd_info* info;
|
struct vcd_info* info;
|
||||||
|
|
||||||
const char* type;
|
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* ident;
|
const char* ident;
|
||||||
int nexus_id;
|
int nexus_id;
|
||||||
|
|
@ -547,7 +546,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
switch (vpi_get(vpiType, item)) {
|
switch (vpi_get(vpiType, item)) {
|
||||||
|
|
||||||
case vpiNet: type = "wire"; if(0){
|
|
||||||
case vpiMemoryWord:
|
case vpiMemoryWord:
|
||||||
if (vpi_get(vpiConstantSelect, item) == 0) {
|
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||||
/* Turn a non-constant array word select into a
|
/* Turn a non-constant array word select into a
|
||||||
|
|
@ -563,7 +561,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
case vpiIntVar:
|
case vpiIntVar:
|
||||||
case vpiLongIntVar:
|
case vpiLongIntVar:
|
||||||
case vpiTimeVar:
|
case vpiTimeVar:
|
||||||
case vpiReg: type = "reg"; }
|
case vpiReg:
|
||||||
|
case vpiNet:
|
||||||
|
|
||||||
/* An array word is implicitly escaped so look for an
|
/* An array word is implicitly escaped so look for an
|
||||||
* escaped identifier that this could conflict with. */
|
* escaped identifier that this could conflict with. */
|
||||||
|
|
@ -656,11 +655,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiModule: type = "module"; if(0){
|
case vpiModule:
|
||||||
case vpiNamedBegin: type = "begin"; }if(0){
|
case vpiNamedBegin:
|
||||||
case vpiTask: type = "task"; }if(0){
|
case vpiTask:
|
||||||
case vpiFunction: type = "function"; }if(0){
|
case vpiFunction:
|
||||||
case vpiNamedFork: type = "fork"; }
|
case vpiNamedFork:
|
||||||
|
|
||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
int nskip;
|
int nskip;
|
||||||
|
|
@ -683,7 +682,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
name = vpi_get_str(vpiName, item);
|
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++) {
|
for (i=0; types[i]>0; i++) {
|
||||||
vpiHandle hand;
|
vpiHandle hand;
|
||||||
|
|
|
||||||
|
|
@ -587,7 +587,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
struct t_cb_data cb;
|
struct t_cb_data cb;
|
||||||
struct vcd_info* info;
|
struct vcd_info* info;
|
||||||
|
|
||||||
const char* type;
|
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* ident;
|
const char* ident;
|
||||||
int nexus_id;
|
int nexus_id;
|
||||||
|
|
@ -610,7 +609,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
switch (vpi_get(vpiType, item)) {
|
switch (vpi_get(vpiType, item)) {
|
||||||
|
|
||||||
case vpiNet: type = "wire"; if(0){
|
|
||||||
case vpiMemoryWord:
|
case vpiMemoryWord:
|
||||||
if (vpi_get(vpiConstantSelect, item) == 0) {
|
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||||
/* Turn a non-constant array word select into a
|
/* Turn a non-constant array word select into a
|
||||||
|
|
@ -626,7 +624,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
case vpiIntVar:
|
case vpiIntVar:
|
||||||
case vpiLongIntVar:
|
case vpiLongIntVar:
|
||||||
case vpiTimeVar:
|
case vpiTimeVar:
|
||||||
case vpiReg: type = "reg"; }
|
case vpiReg:
|
||||||
|
case vpiNet:
|
||||||
|
|
||||||
/* An array word is implicitly escaped so look for an
|
/* An array word is implicitly escaped so look for an
|
||||||
* escaped identifier that this could conflict with. */
|
* escaped identifier that this could conflict with. */
|
||||||
|
|
@ -711,11 +710,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiModule: type = "module"; if(0){
|
case vpiModule:
|
||||||
case vpiNamedBegin: type = "begin"; }if(0){
|
case vpiNamedBegin:
|
||||||
case vpiTask: type = "task"; }if(0){
|
case vpiTask:
|
||||||
case vpiFunction: type = "function"; }if(0){
|
case vpiFunction:
|
||||||
case vpiNamedFork: type = "fork"; }
|
case vpiNamedFork:
|
||||||
|
|
||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
int nskip;
|
int nskip;
|
||||||
|
|
@ -738,7 +737,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
|
|
||||||
name = vpi_get_str(vpiName, item);
|
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++) {
|
for (i=0; types[i]>0; i++) {
|
||||||
vpiHandle hand;
|
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. */
|
/* Check that there are at least two arguments. */
|
||||||
arg = vpi_scan(argv); /* This should never be zero. */
|
arg = vpi_scan(argv); /* This should never be zero. */
|
||||||
|
assert(arg);
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
if (arg == 0) {
|
if (arg == 0) {
|
||||||
vpi_printf("ERROR: %s requires two arguments.\n", name);
|
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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -95,7 +95,9 @@ static PLI_INT32 sys_realtime_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
|
|
||||||
/* For $abstime() we return the time in second. */
|
/* For $abstime() we return the time in second. */
|
||||||
if (strcmp(name, "$abstime") == 0) {
|
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;
|
val.format = vpiRealVal;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* Verilog-2005 math library for Icarus Verilog
|
* Verilog-2005 math library for Icarus Verilog
|
||||||
* http://www.icarus.com/eda/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
|
* 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
|
* 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);
|
arg = vpi_scan(argv);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
va_error_message(callh, "%s takes only one argument.\n", name);
|
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. */
|
/* 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);
|
arg = vpi_scan(argv);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
va_error_message(callh, "%s takes only two arguments.\n", name);
|
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. */
|
/* 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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -20,243 +20,514 @@
|
||||||
# include "vpi_config.h"
|
# include "vpi_config.h"
|
||||||
# include "sv_vpi_user.h"
|
# include "sv_vpi_user.h"
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
||||||
static void missing_arguments(vpiHandle sys)
|
/*
|
||||||
{
|
* The compiletf routine for the enumeration next() and prev() methods.
|
||||||
vpi_printf("%s:%d: error: Invalid/missing arguments next/prev method\n",
|
*/
|
||||||
vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo,sys));
|
static PLI_INT32 ivl_enum_method_next_prev_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
vpi_control(vpiFinish, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PLI_INT32 ivl_method_next_prev_compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
|
||||||
{
|
{
|
||||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
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) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for the enumeration type argument. */
|
||||||
arg_enum = vpi_scan(argv);
|
arg_enum = vpi_scan(argv);
|
||||||
if (arg_enum == 0) {
|
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;
|
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) {
|
if (vpi_get(vpiType, arg_enum) != vpiEnumTypespec) {
|
||||||
missing_arguments(sys);
|
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
|
||||||
return 0;
|
(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 */
|
/* Check for the enumeration variable. */
|
||||||
if (vpi_get(vpiSize,sys) != vpi_get(vpiSize,arg_item)) {
|
arg_var = vpi_scan(argv);
|
||||||
missing_arguments(sys);
|
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;
|
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;
|
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)
|
if (ref1->format == vpiIntVal && ref2->format == vpiIntVal)
|
||||||
return ref1->value.integer == ref2->value.integer;
|
return ref1->value.integer == ref2->value.integer;
|
||||||
|
|
||||||
|
/* For two vectors compare them word by word. */
|
||||||
if (ref1->format == vpiVectorVal && ref2->format == vpiVectorVal) {
|
if (ref1->format == vpiVectorVal && ref2->format == vpiVectorVal) {
|
||||||
int words = (wid-1)/32 + 1;
|
PLI_INT32 words = (wid-1)/32 + 1;
|
||||||
int idx;
|
PLI_INT32 idx;
|
||||||
|
|
||||||
for (idx = 0 ; idx < words ; idx += 1) {
|
for (idx = 0 ; idx < words ; idx += 1) {
|
||||||
if (ref1->value.vector[idx].aval != ref2->value.vector[idx].aval)
|
if (ref1->value.vector[idx].aval !=
|
||||||
return 0;
|
ref2->value.vector[idx].aval) return 0;
|
||||||
if (ref1->value.vector[idx].bval != ref2->value.vector[idx].bval)
|
if (ref1->value.vector[idx].bval !=
|
||||||
return 0;
|
ref2->value.vector[idx].bval) return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Swap the order so the code below can be used. */
|
||||||
if (ref1->format == vpiVectorVal && ref2->format == vpiIntVal) {
|
if (ref1->format == vpiVectorVal && ref2->format == vpiIntVal) {
|
||||||
s_vpi_value*tmp = ref1;
|
s_vpi_value*tmp = ref1;
|
||||||
ref1 = ref2;
|
ref1 = ref2;
|
||||||
ref2 = tmp;
|
ref2 = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compare an integer to a vector. */
|
||||||
if (ref1->format == vpiIntVal && ref2->format == vpiVectorVal) {
|
if (ref1->format == vpiIntVal && ref2->format == vpiVectorVal) {
|
||||||
int use_aval = ref1->value.integer;
|
PLI_INT32 aval = ref1->value.integer;
|
||||||
int words = (wid-1)/32 + 1;
|
PLI_INT32 words = (wid-1)/32 + 1;
|
||||||
int idx;
|
PLI_INT32 idx;
|
||||||
|
|
||||||
for (idx = 0 ; idx < words ; idx += 1) {
|
for (idx = 0 ; idx < words ; idx += 1) {
|
||||||
if (use_aval != ref2->value.vector[idx].aval)
|
if (aval != ref2->value.vector[idx].aval) return 0;
|
||||||
return 0;
|
if (ref2->value.vector[idx].bval) return 0;
|
||||||
if (0 != ref2->value.vector[idx].bval)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
use_aval = 0;
|
aval = 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unsupported types. */
|
||||||
vpi_printf("XXXX formats are: %d vs %d\n", ref1->format, ref2->format);
|
vpi_printf("XXXX formats are: %d vs %d\n", ref1->format, ref2->format);
|
||||||
assert(0);
|
assert(0);
|
||||||
return 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 sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||||
vpiHandle arg_enum = vpi_scan(argv);
|
vpiHandle arg_enum = vpi_scan(argv);
|
||||||
vpiHandle arg_item = vpi_scan(argv);
|
vpiHandle arg_var = vpi_scan(argv);
|
||||||
vpiHandle arg_extra = vpi_scan(argv);
|
vpiHandle arg_count = vpi_scan(argv);
|
||||||
|
|
||||||
vpiHandle enum_list = 0;
|
vpiHandle enum_list;
|
||||||
vpiHandle memb = 0, first_memb = 0;
|
vpiHandle cur;
|
||||||
long use_width = 0;
|
PLI_INT32 var_width = vpi_get(vpiSize, arg_var);
|
||||||
long item_width = vpi_get(vpiSize, arg_item);
|
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;
|
/* Get the count value. */
|
||||||
vpi_get_value(arg_item, &item_value);
|
count_val.format = vpiIntVal;
|
||||||
|
vpi_get_value(arg_count, &count_val);
|
||||||
/* If this value is a vector value, then make a safe copy of
|
count = count_val.value.integer;
|
||||||
the vector so that other vpi functions don't trash it. */
|
/* Remove any multiple loops around the enumeration. */
|
||||||
if (item_value.format == vpiVectorVal) {
|
count %= enum_size;
|
||||||
unsigned idx;
|
/* Free the argument iterator. */
|
||||||
unsigned hwid = (item_width - 1)/32 + 1;
|
vpi_free_object(argv);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum_list = vpi_iterate(vpiMember, arg_enum);
|
/* Get the current value. */
|
||||||
assert(enum_list);
|
var_val.format = vpiObjTypeVal;
|
||||||
|
vpi_get_value(arg_var, &var_val);
|
||||||
|
|
||||||
/* Search for the current value in the member list. */
|
/* If the count is zero then just return the current value. */
|
||||||
do {
|
if (count == 0) {
|
||||||
memb = vpi_scan(enum_list);
|
vpi_put_value(sys, &var_val, 0, vpiNoDelay);
|
||||||
if (first_memb == 0) {
|
return 0;
|
||||||
first_memb = memb;
|
}
|
||||||
use_width = vpi_get(vpiSize, first_memb);
|
|
||||||
assert(use_width == vpi_get(vpiSize, arg_item));
|
/* 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;
|
/* Search for the current value in the enumeration list. */
|
||||||
vpi_get_value(memb, &memb_value);
|
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)
|
/* If the variable is a vector then free the copy we created above. */
|
||||||
memb = vpi_scan(enum_list);
|
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);
|
vpi_free_object(enum_list);
|
||||||
|
|
||||||
if (memb == 0) {
|
/* Get the value and return it. */
|
||||||
memb = first_memb;
|
cur_val.format = vpiObjTypeVal;
|
||||||
memb_value.format = vpiIntVal;
|
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;
|
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 sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||||
vpiHandle arg_enum = vpi_scan(argv);
|
vpiHandle arg_enum = vpi_scan(argv);
|
||||||
vpiHandle arg_item = vpi_scan(argv);
|
vpiHandle arg_var = vpi_scan(argv);
|
||||||
vpiHandle arg_extra = vpi_scan(argv);
|
|
||||||
|
|
||||||
vpiHandle enum_list = 0;
|
vpiHandle enum_list;
|
||||||
vpiHandle memb = 0, prev = 0, last_memb = 0;
|
vpiHandle cur;
|
||||||
int use_wid = 0;
|
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;
|
/* Get the current value. */
|
||||||
vpi_get_value(arg_item, &item_value);
|
var_val.format = vpiObjTypeVal;
|
||||||
|
vpi_get_value(arg_var, &var_val);
|
||||||
|
|
||||||
enum_list = vpi_iterate(vpiMember, arg_enum);
|
/* If the current value is a vector, then make a safe copy of
|
||||||
assert(enum_list);
|
it so that other vpi_get_value() calls don't trash the value. */
|
||||||
|
if (var_val.format == vpiVectorVal) {
|
||||||
/* Search for the current value in the member list. */
|
PLI_INT32 idx;
|
||||||
do {
|
PLI_INT32 words = (var_width - 1)/32 + 1;
|
||||||
prev = memb;
|
p_vpi_vecval nvec = malloc(words*sizeof(s_vpi_vecval));
|
||||||
memb = vpi_scan(enum_list);
|
for (idx = 0 ; idx < words ; idx += 1) {
|
||||||
if (memb == 0) break;
|
nvec[idx].aval = var_val.value.vector[idx].aval;
|
||||||
if (use_wid == 0)
|
nvec[idx].bval = var_val.value.vector[idx].bval;
|
||||||
use_wid = vpi_get(vpiSize, memb);
|
}
|
||||||
|
var_val.value.vector = nvec;
|
||||||
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 (prev == 0)
|
/* Search for the current value in the enumeration list. */
|
||||||
prev = last_memb;
|
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);
|
cur_val.format = vpiObjTypeVal;
|
||||||
vpi_put_value(sys, &memb_value, 0, vpiNoDelay);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void v2009_enum_register(void)
|
void v2009_enum_register(void)
|
||||||
{
|
{
|
||||||
s_vpi_systf_data tf_data;
|
s_vpi_systf_data tf_data;
|
||||||
|
vpiHandle res;
|
||||||
|
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
tf_data.calltf = ivl_method_next_calltf;
|
tf_data.calltf = ivl_enum_method_name_calltf;
|
||||||
tf_data.compiletf = ivl_method_next_prev_compiletf;
|
tf_data.compiletf = ivl_enum_method_name_compiletf;
|
||||||
tf_data.sizetf = 0;
|
tf_data.sizetf = 0;
|
||||||
tf_data.tfname = "$ivl_method$next";
|
tf_data.tfname = "$ivl_enum_method$name";
|
||||||
tf_data.user_data = "$ivl_method$next";
|
tf_data.user_data = "$ivl_enum_method$name";
|
||||||
vpi_register_systf(&tf_data);
|
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.type = vpiSysFunc;
|
||||||
tf_data.calltf = ivl_method_prev_calltf;
|
tf_data.calltf = ivl_enum_method_next_prev_calltf;
|
||||||
tf_data.compiletf = 0;
|
tf_data.compiletf = ivl_enum_method_next_prev_compiletf;
|
||||||
tf_data.sizetf = 0;
|
tf_data.sizetf = 0;
|
||||||
tf_data.tfname = "$ivl_method$prev";
|
tf_data.tfname = "$ivl_enum_method$next";
|
||||||
tf_data.user_data = "$ivl_method$prev";
|
tf_data.user_data = "$ivl_enum_method$next";
|
||||||
vpi_register_systf(&tf_data);
|
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
|
* Verilog-A math library for Icarus Verilog
|
||||||
* http://www.icarus.com/eda/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
|
* 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
|
* 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);
|
arg = vpi_scan(argv);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
va_error_message(callh, "%s takes only one argument.\n", name);
|
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. */
|
/* 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);
|
arg = vpi_scan(argv);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
va_error_message(callh, "%s takes only two arguments.\n", name);
|
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. */
|
/* 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 path [MAX_STRING_RESULT];
|
||||||
char *ptr = getcwd(path, MAX_STRING_RESULT);
|
char *ptr = getcwd(path, MAX_STRING_RESULT);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
ptr = strcpy(path, "<error getting the cwd, "
|
strcpy(path, "<error getting the cwd, is it too long?>");
|
||||||
"is it too long?>");
|
|
||||||
}
|
}
|
||||||
retval = strdup(path);
|
retval = strdup(path);
|
||||||
} else if (strcmp(param, "module") == 0) {
|
} else if (strcmp(param, "module") == 0) {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@
|
||||||
|
|
||||||
# include "vpi_config.h"
|
# include "vpi_config.h"
|
||||||
# include "vpi_user.h"
|
# include "vpi_user.h"
|
||||||
# include <cassert>
|
# include <assert.h>
|
||||||
|
# include "ivl_alloc.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The $ivlh_attribute_event implements the VHDL <varname>'event
|
* The $ivlh_attribute_event implements the VHDL <varname>'event
|
||||||
|
|
@ -32,14 +33,28 @@ struct monitor_data {
|
||||||
struct t_vpi_time last_event;
|
struct t_vpi_time last_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
static struct monitor_data **mdata = 0;
|
||||||
* All the following are called from C so define them for C linkage.
|
static unsigned mdata_count = 0;
|
||||||
*/
|
|
||||||
extern "C" {
|
/* 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)
|
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);
|
||||||
assert(cb->time->type == vpiSimTime);
|
assert(cb->time->type == vpiSimTime);
|
||||||
|
|
@ -48,56 +63,71 @@ static PLI_INT32 monitor_events(struct t_cb_data*cb)
|
||||||
return 0;
|
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 sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||||
vpiHandle arg;
|
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) {
|
if (argv == 0) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
|
||||||
vpi_printf("Call to %s missing its argument\n", vpi_get_str(vpiName,sys));
|
(int)vpi_get(vpiLineNo, sys));
|
||||||
|
vpi_printf("(compiler error) %s requires a single argument.\n",
|
||||||
|
name);
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Icarus either returns 0 above or has one argument. */
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
assert(arg);
|
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;
|
tb.type = vpiSimTime;
|
||||||
cb.reason = cbValueChange;
|
cb.reason = cbValueChange;
|
||||||
cb.cb_rtn = monitor_events;
|
cb.cb_rtn = monitor_events;
|
||||||
cb.obj = arg;
|
cb.obj = arg;
|
||||||
cb.time = &tb;
|
cb.time = &tb;
|
||||||
cb.value = 0;
|
cb.value = 0;
|
||||||
cb.user_data = reinterpret_cast<char*>(monitor_handle);
|
cb.user_data = (char*) (mon);
|
||||||
vpi_register_cb(&cb);
|
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);
|
arg = vpi_scan(argv);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
|
||||||
vpi_printf("Too many arguments for call to %s.\n", vpi_get_str(vpiName,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);
|
vpi_control(vpiFinish, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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);
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
||||||
struct t_vpi_value rval;
|
struct t_vpi_value rval;
|
||||||
|
struct monitor_data*mon;
|
||||||
|
(void) name;
|
||||||
|
|
||||||
rval.format = vpiScalarVal;
|
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) {
|
if (mon->last_event.type == 0) {
|
||||||
rval.value.scalar = vpi0;
|
rval.value.scalar = vpi0;
|
||||||
|
|
@ -105,7 +135,7 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
|
||||||
} else {
|
} else {
|
||||||
struct t_vpi_time tnow;
|
struct t_vpi_time tnow;
|
||||||
tnow.type = vpiSimTime;
|
tnow.type = vpiSimTime;
|
||||||
vpi_get_time(0,&tnow);
|
vpi_get_time(0, &tnow);
|
||||||
|
|
||||||
rval.value.scalar = vpi1;
|
rval.value.scalar = vpi1;
|
||||||
if (mon->last_event.high != tnow.high)
|
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;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vhdl_register(void)
|
static void vhdl_register(void)
|
||||||
{
|
{
|
||||||
s_vpi_systf_data tf_data;
|
s_vpi_systf_data tf_data;
|
||||||
|
s_cb_data cb;
|
||||||
vpiHandle res;
|
vpiHandle res;
|
||||||
|
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
|
|
@ -138,11 +170,19 @@ static void vhdl_register(void)
|
||||||
tf_data.user_data = (PLI_BYTE8 *) "$ivlh_attribute_event";
|
tf_data.user_data = (PLI_BYTE8 *) "$ivlh_attribute_event";
|
||||||
res = vpi_register_systf(&tf_data);
|
res = vpi_register_systf(&tf_data);
|
||||||
vpip_make_systf_system_defined(res);
|
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[])() = {
|
void (*vlog_startup_routines[])() = {
|
||||||
vhdl_register,
|
vhdl_register,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* extern "C" */
|
|
||||||
|
|
@ -27,24 +27,3 @@
|
||||||
#define wave_alloca alloca
|
#define wave_alloca alloca
|
||||||
#endif
|
#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 vpiSysTaskCall 57
|
||||||
#define vpiTask 59
|
#define vpiTask 59
|
||||||
#define vpiTimeVar 63
|
#define vpiTimeVar 63
|
||||||
|
#define vpiUdpDefn 66
|
||||||
#define vpiUserSystf 67
|
#define vpiUserSystf 67
|
||||||
#define vpiNetArray 114
|
#define vpiNetArray 114
|
||||||
#define vpiIndex 78
|
#define vpiIndex 78
|
||||||
|
|
@ -362,7 +363,7 @@ typedef struct t_vpi_delay {
|
||||||
# define vpiSysFuncReal vpiRealFunc
|
# define vpiSysFuncReal vpiRealFunc
|
||||||
# define vpiSysFuncTime vpiTimeFunc
|
# define vpiSysFuncTime vpiTimeFunc
|
||||||
# define vpiSysFuncSized vpiSizedFunc
|
# define vpiSysFuncSized vpiSizedFunc
|
||||||
#define vpiUserDefn 49
|
#define vpiUserDefn 45
|
||||||
#define vpiAutomatic 50
|
#define vpiAutomatic 50
|
||||||
#define vpiConstantSelect 53
|
#define vpiConstantSelect 53
|
||||||
#define vpiSigned 65
|
#define vpiSigned 65
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,12 @@ void codespace_delete(void)
|
||||||
{
|
{
|
||||||
vvp_code_t cur = first_chunk;
|
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 {
|
do {
|
||||||
vvp_code_t next = cur[code_chunk_size-1].cptr;
|
vvp_code_t next = cur[code_chunk_size-1].cptr;
|
||||||
for (unsigned idx = 0 ; idx < code_chunk_size; idx += 1) {
|
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);
|
u->compile_table(table);
|
||||||
}
|
}
|
||||||
free(label);
|
free(label);
|
||||||
delete[] name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char **compile_udp_table(char **table, char *row)
|
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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -771,6 +771,11 @@ static vpiHandle modpath_src_get_handle(int code, vpiHandle ref)
|
||||||
return vpi_handle(scope);
|
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:
|
case vpiModPathIn:
|
||||||
return vpi_handle(&rfp->path_term_in);
|
return vpi_handle(&rfp->path_term_in);
|
||||||
|
|
||||||
|
|
@ -780,6 +785,30 @@ static vpiHandle modpath_src_get_handle(int code, vpiHandle ref)
|
||||||
return 0;
|
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)
|
static vpiHandle modpath_src_index ( vpiHandle ref, int)
|
||||||
{
|
{
|
||||||
assert(ref->vpi_type->type_code == vpiModPathIn);
|
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_get_value,
|
||||||
modpath_src_put_value,
|
modpath_src_put_value,
|
||||||
modpath_src_get_handle,
|
modpath_src_get_handle,
|
||||||
0, /* modpath_src_iterate,*/
|
modpath_src_iterate,
|
||||||
modpath_src_index,
|
modpath_src_index,
|
||||||
modpath_src_free_object,
|
modpath_src_free_object,
|
||||||
modpath_src_get_delays,
|
modpath_src_get_delays,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
# include "compile.h"
|
# include "compile.h"
|
||||||
# include "enum_type.h"
|
# include "enum_type.h"
|
||||||
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
|
# include "vvp_cleanup.h"
|
||||||
|
#endif
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
|
||||||
|
|
@ -40,6 +43,7 @@ static struct enumconst_s* enumconst_from_handle(vpiHandle obj)
|
||||||
struct __vpiEnumTypespec {
|
struct __vpiEnumTypespec {
|
||||||
struct __vpiHandle base;
|
struct __vpiHandle base;
|
||||||
std::vector<enumconst_s> names;
|
std::vector<enumconst_s> names;
|
||||||
|
int base_type_code;
|
||||||
bool is_signed;
|
bool is_signed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -60,6 +64,13 @@ static int enum_type_get(int code, vpiHandle obj)
|
||||||
case vpiSize:
|
case vpiSize:
|
||||||
return ref->names.size();
|
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:
|
case vpiSigned:
|
||||||
return ref->is_signed;
|
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);
|
struct __vpiEnumTypespec*ref = vpip_enum_typespec_from_handle(obj);
|
||||||
assert(ref);
|
assert(ref);
|
||||||
|
|
||||||
if (code == vpiMember) {
|
if (code == vpiEnumConst) {
|
||||||
vpiHandle*args = (vpiHandle*)
|
vpiHandle*args = (vpiHandle*)
|
||||||
calloc(ref->names.size(), sizeof(vpiHandle*));
|
calloc(ref->names.size(), sizeof(vpiHandle*));
|
||||||
for (size_t idx = 0 ; idx < ref->names.size() ; idx += 1)
|
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->base.vpi_type = &enum_type_rt;
|
||||||
spec->names = std::vector<enumconst_s> (names->size());
|
spec->names = std::vector<enumconst_s> (names->size());
|
||||||
spec->is_signed = signed_flag;
|
spec->is_signed = signed_flag;
|
||||||
|
spec->base_type_code = vpiBitVar;
|
||||||
|
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
for (list<struct enum_name_s>::iterator cur = names->begin()
|
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());
|
assert(idx == spec->names.size());
|
||||||
compile_vpi_symbol(label, vpi_handle(spec));
|
compile_vpi_symbol(label, vpi_handle(spec));
|
||||||
|
vpip_attach_to_current_scope(vpi_handle(spec));
|
||||||
|
|
||||||
free(label);
|
free(label);
|
||||||
delete names;
|
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->base.vpi_type = &enum_type_rt;
|
||||||
spec->names = std::vector<enumconst_s> (names->size());
|
spec->names = std::vector<enumconst_s> (names->size());
|
||||||
spec->is_signed = signed_flag;
|
spec->is_signed = signed_flag;
|
||||||
|
spec->base_type_code = vpiReg;
|
||||||
|
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
for (list<struct enum_name_s>::iterator cur = names->begin()
|
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());
|
assert(idx == spec->names.size());
|
||||||
compile_vpi_symbol(label, vpi_handle(spec));
|
compile_vpi_symbol(label, vpi_handle(spec));
|
||||||
|
vpip_attach_to_current_scope(vpi_handle(spec));
|
||||||
|
|
||||||
free(label);
|
free(label);
|
||||||
delete names;
|
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;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init, bool type)
|
vvp_udp_s::vvp_udp_s(char*label, char*name__, unsigned ports,
|
||||||
: ports_(ports), init_(init), seq_(type)
|
vvp_bit4_t init, bool type)
|
||||||
|
: name_(name__), ports_(ports), init_(init), seq_(type)
|
||||||
{
|
{
|
||||||
if (!udp_table)
|
if (!udp_table)
|
||||||
udp_table = new_symbol_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()
|
vvp_udp_s::~vvp_udp_s()
|
||||||
{
|
{
|
||||||
|
delete[] name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned vvp_udp_s::port_count() const
|
unsigned vvp_udp_s::port_count() const
|
||||||
|
|
@ -116,10 +118,9 @@ vvp_bit4_t vvp_udp_s::get_init() const
|
||||||
return init_;
|
return init_;
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name, unsigned ports)
|
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name__, unsigned ports)
|
||||||
: vvp_udp_s(label, ports, BIT4_X, false)
|
: vvp_udp_s(label, name__, ports, BIT4_X, false)
|
||||||
{
|
{
|
||||||
name_ = name;
|
|
||||||
levels0_ = 0;
|
levels0_ = 0;
|
||||||
levels1_ = 0;
|
levels1_ = 0;
|
||||||
nlevels0_ = 0;
|
nlevels0_ = 0;
|
||||||
|
|
@ -295,11 +296,10 @@ void vvp_udp_comb_s::compile_table(char**tab)
|
||||||
assert(nrows1 == nlevels1_);
|
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)
|
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;
|
levels0_ = 0;
|
||||||
levels1_ = 0;
|
levels1_ = 0;
|
||||||
levelsx_ = 0;
|
levelsx_ = 0;
|
||||||
|
|
|
||||||
18
vvp/udp.h
18
vvp/udp.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __udp_H
|
#ifndef __udp_H
|
||||||
#define __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 ...
|
* (This is a rewrite of code that was ...
|
||||||
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>)
|
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>)
|
||||||
|
|
@ -30,15 +30,16 @@ struct udp_levels_table;
|
||||||
struct vvp_udp_s {
|
struct vvp_udp_s {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init,
|
explicit vvp_udp_s(char*label, char*name, unsigned ports,
|
||||||
bool type);
|
vvp_bit4_t init, bool type);
|
||||||
virtual ~vvp_udp_s();
|
virtual ~vvp_udp_s();
|
||||||
|
|
||||||
// Return the number of input ports for the defined UDP. This
|
// Return the number of input ports for the defined UDP. This
|
||||||
// does *not* include the current output value for a
|
// does *not* include the current output value for a
|
||||||
// sequential UDP.
|
// sequential UDP.
|
||||||
unsigned port_count() const;
|
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.
|
// Return the initial output value.
|
||||||
vvp_bit4_t get_init() const;
|
vvp_bit4_t get_init() const;
|
||||||
|
|
@ -48,6 +49,7 @@ struct vvp_udp_s {
|
||||||
vvp_bit4_t cur_out) =0;
|
vvp_bit4_t cur_out) =0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
char *name_;
|
||||||
unsigned ports_;
|
unsigned ports_;
|
||||||
vvp_bit4_t init_;
|
vvp_bit4_t init_;
|
||||||
bool seq_;
|
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 {
|
class vvp_udp_comb_s : public vvp_udp_s {
|
||||||
|
|
||||||
public:
|
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();
|
~vvp_udp_comb_s();
|
||||||
void compile_table(char**tab);
|
void compile_table(char**tab);
|
||||||
|
|
||||||
|
|
@ -125,8 +127,6 @@ class vvp_udp_comb_s : public vvp_udp_s {
|
||||||
vvp_bit4_t cur_out);
|
vvp_bit4_t cur_out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char*name_;
|
|
||||||
|
|
||||||
// Level sensitive rows of the device.
|
// Level sensitive rows of the device.
|
||||||
struct udp_levels_table*levels0_;
|
struct udp_levels_table*levels0_;
|
||||||
struct udp_levels_table*levels1_;
|
struct udp_levels_table*levels1_;
|
||||||
|
|
@ -180,7 +180,7 @@ struct udp_edges_table {
|
||||||
class vvp_udp_seq_s : public vvp_udp_s {
|
class vvp_udp_seq_s : public vvp_udp_s {
|
||||||
|
|
||||||
public:
|
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();
|
~vvp_udp_seq_s();
|
||||||
|
|
||||||
void compile_table(char**tab);
|
void compile_table(char**tab);
|
||||||
|
|
@ -190,8 +190,6 @@ class vvp_udp_seq_s : public vvp_udp_s {
|
||||||
vvp_bit4_t cur_out);
|
vvp_bit4_t cur_out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char*name_;
|
|
||||||
|
|
||||||
vvp_bit4_t test_levels_(const udp_levels_table&cur);
|
vvp_bit4_t test_levels_(const udp_levels_table&cur);
|
||||||
|
|
||||||
// Level sensitive rows of the device.
|
// Level sensitive rows of the device.
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,8 @@ static const char* vpi_type_values(PLI_INT32 code)
|
||||||
return "vpiByteVar";
|
return "vpiByteVar";
|
||||||
case vpiConstant:
|
case vpiConstant:
|
||||||
return "vpiConstant";
|
return "vpiConstant";
|
||||||
|
case vpiEnumTypespec:
|
||||||
|
return "vpiEnumTypespec";
|
||||||
case vpiFunction:
|
case vpiFunction:
|
||||||
return "vpiFunction";
|
return "vpiFunction";
|
||||||
case vpiIntVar:
|
case vpiIntVar:
|
||||||
|
|
@ -473,7 +475,7 @@ int vpip_time_precision_from_handle(vpiHandle obj)
|
||||||
|
|
||||||
void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
|
void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
|
||||||
{
|
{
|
||||||
int units;
|
int scale;
|
||||||
vvp_time64_t time;
|
vvp_time64_t time;
|
||||||
|
|
||||||
assert(vp);
|
assert(vp);
|
||||||
|
|
@ -487,9 +489,10 @@ void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiScaledRealTime:
|
case vpiScaledRealTime:
|
||||||
units = vpip_time_units_from_handle(obj);
|
scale = vpip_get_time_precision() -
|
||||||
vp->real = pow(10.0L, vpip_get_time_precision() - units);
|
vpip_time_units_from_handle(obj);
|
||||||
vp->real *= time;
|
if (scale >= 0) vp->real = (double)time * pow(10.0, scale);
|
||||||
|
else vp->real = (double)time / pow(10.0, -scale);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -951,6 +954,7 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
||||||
|
|
||||||
if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
|
if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
|
||||||
vvp_time64_t dly;
|
vvp_time64_t dly;
|
||||||
|
int scale;
|
||||||
|
|
||||||
if (vpi_get(vpiAutomatic, obj)) {
|
if (vpi_get(vpiAutomatic, obj)) {
|
||||||
fprintf(stderr, "vpi error: cannot put a value with "
|
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) {
|
switch (when->type) {
|
||||||
case vpiScaledRealTime:
|
case vpiScaledRealTime:
|
||||||
dly = (vvp_time64_t)(when->real *
|
scale = vpip_time_units_from_handle(obj) -
|
||||||
(pow(10.0L,
|
vpip_get_time_precision();
|
||||||
vpip_time_units_from_handle(obj) -
|
if (scale >= 0) {
|
||||||
vpip_get_time_precision())));
|
dly = (vvp_time64_t)(when->real * pow(10.0, scale));
|
||||||
|
} else {
|
||||||
|
dly = (vvp_time64_t)(when->real / pow(10.0, -scale));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case vpiSimTime:
|
case vpiSimTime:
|
||||||
dly = vpip_timestruct_to_time(when);
|
dly = vpip_timestruct_to_time(when);
|
||||||
|
|
@ -1047,6 +1054,13 @@ vpiHandle vpi_handle(PLI_INT32 type, vpiHandle ref)
|
||||||
return res;
|
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
|
* This function asks the object to return an iterator for
|
||||||
* the specified reference. It is up to the iterate_ method to
|
* the specified reference. It is up to the iterate_ method to
|
||||||
|
|
@ -1058,6 +1072,9 @@ static vpiHandle vpi_iterate_global(int type)
|
||||||
case vpiModule:
|
case vpiModule:
|
||||||
return vpip_make_root_iterator();
|
return vpip_make_root_iterator();
|
||||||
|
|
||||||
|
case vpiUdpDefn:
|
||||||
|
return vpip_make_udp_iterator();
|
||||||
|
|
||||||
case vpiUserSystf:
|
case vpiUserSystf:
|
||||||
return vpip_make_systf_iterator();
|
return vpip_make_systf_iterator();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,9 @@ static void delete_sub_scopes(struct __vpiScope *scope)
|
||||||
case vpiRealVar:
|
case vpiRealVar:
|
||||||
real_delete((scope->intern)[idx]);
|
real_delete((scope->intern)[idx]);
|
||||||
break;
|
break;
|
||||||
|
case vpiEnumTypespec:
|
||||||
|
enum_delete((scope->intern)[idx]);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Need support for type: %d\n",
|
fprintf(stderr, "Need support for type: %d\n",
|
||||||
scope->intern[idx]->vpi_type->type_code);
|
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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -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)
|
double vpip_time_to_scaled_real(vvp_time64_t ti, struct __vpiScope*scope)
|
||||||
{
|
{
|
||||||
int units;
|
double val;
|
||||||
if (scope)
|
int scale = 0;
|
||||||
units = scope->time_units;
|
if (scope) scale = vpi_time_precision - scope->time_units;
|
||||||
else
|
|
||||||
units = vpi_time_precision;
|
|
||||||
|
|
||||||
double val = pow(10.0L, vpi_time_precision - units);
|
if (scale >= 0) val = (double)ti * pow(10.0, scale);
|
||||||
val *= ti;
|
else val = (double)ti / pow(10.0, -scale);
|
||||||
|
|
||||||
return val;
|
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)
|
* Copyright (c) 2002 Larry Doolittle (larry@doolittle.boa.org)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* 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,
|
char *buf, unsigned int nbuf,
|
||||||
int signed_flag)
|
int signed_flag)
|
||||||
{
|
{
|
||||||
unsigned int idx, len, vlen;
|
unsigned int idx, vlen;
|
||||||
unsigned int mbits=vec4.size(); /* number of non-sign bits */
|
unsigned int mbits=vec4.size(); /* number of non-sign bits */
|
||||||
unsigned count_x = 0, count_z = 0;
|
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()) {
|
if (count_x == vec4.size()) {
|
||||||
len = 1;
|
|
||||||
buf[0] = 'x';
|
buf[0] = 'x';
|
||||||
buf[1] = 0;
|
buf[1] = 0;
|
||||||
} else if (count_x > 0) {
|
} else if (count_x > 0) {
|
||||||
len = 1;
|
|
||||||
buf[0] = 'X';
|
buf[0] = 'X';
|
||||||
buf[1] = 0;
|
buf[1] = 0;
|
||||||
} else if (count_z == vec4.size()) {
|
} else if (count_z == vec4.size()) {
|
||||||
len = 1;
|
|
||||||
buf[0] = 'z';
|
buf[0] = 'z';
|
||||||
buf[1] = 0;
|
buf[1] = 0;
|
||||||
} else if (count_z > 0) {
|
} else if (count_z > 0) {
|
||||||
len = 1;
|
|
||||||
buf[0] = 'Z';
|
buf[0] = 'Z';
|
||||||
buf[1] = 0;
|
buf[1] = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __vvp_cleanup_H
|
#ifndef __vvp_cleanup_H
|
||||||
#define __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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -43,6 +43,7 @@ extern void A_delete(struct __vpiHandle *item);
|
||||||
extern void PV_delete(struct __vpiHandle *item);
|
extern void PV_delete(struct __vpiHandle *item);
|
||||||
extern void constant_delete(struct __vpiHandle *item);
|
extern void constant_delete(struct __vpiHandle *item);
|
||||||
extern void contexts_delete(struct __vpiScope *scope);
|
extern void contexts_delete(struct __vpiScope *scope);
|
||||||
|
extern void enum_delete(struct __vpiHandle *item);
|
||||||
extern void memory_delete(struct __vpiHandle *item);
|
extern void memory_delete(struct __vpiHandle *item);
|
||||||
extern void named_event_delete(struct __vpiHandle *item);
|
extern void named_event_delete(struct __vpiHandle *item);
|
||||||
extern void parameter_delete(struct __vpiHandle *item);
|
extern void parameter_delete(struct __vpiHandle *item);
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
# include <valgrind/memcheck.h>
|
# include <valgrind/memcheck.h>
|
||||||
# include <map>
|
# include <map>
|
||||||
# include "sfunc.h"
|
# include "sfunc.h"
|
||||||
|
# include "udp.h"
|
||||||
# include "ivl_alloc.h"
|
# include "ivl_alloc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -85,6 +86,7 @@ void* vvp_net_t::operator new (size_t size)
|
||||||
#ifdef CHECK_WITH_VALGRIND
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
static map<vvp_net_t*, bool> vvp_net_map;
|
static map<vvp_net_t*, bool> vvp_net_map;
|
||||||
static map<sfunc_core*, bool> sfunc_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 vvp_net_t **local_net_pool = 0;
|
||||||
static unsigned local_net_pool_count = 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)) {
|
if (sfunc_core*tmp = dynamic_cast<sfunc_core*> (item->fun)) {
|
||||||
sfunc_map[tmp] = true;
|
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()
|
void vvp_net_pool_delete()
|
||||||
|
|
@ -128,6 +133,12 @@ void vvp_net_pool_delete()
|
||||||
}
|
}
|
||||||
sfunc_map.clear();
|
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)) {
|
if (RUNNING_ON_VALGRIND && (vvp_nets_del != count_vvp_nets)) {
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
VALGRIND_PRINTF("Error: vvp missed deleting %ld of %lu net(s).",
|
VALGRIND_PRINTF("Error: vvp missed deleting %ld of %lu net(s).",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue