Merge branch 'master' into work9

This commit is contained in:
Stephen Williams 2011-11-06 10:27:40 -08:00
commit 5e4c0c9783
54 changed files with 2041 additions and 960 deletions

13
aclocal.m4 vendored
View File

@ -64,7 +64,7 @@ fi
# AX_WIN32
# --------
# Combined check for several flavors of Microsoft Windows so
# their "issues" can be dealt with
# their "issues" can be dealt with
AC_DEFUN([AX_WIN32],
[AC_MSG_CHECKING([for Microsoft Windows])
AC_REQUIRE([AC_CANONICAL_HOST]) []dnl
@ -230,6 +230,17 @@ case "${host}" in
esac
])# AX_CPP_PRECOMP
# AX_C99_STRTOD
# -------------
AC_DEFUN([AX_C99_STRTOD],
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
case "${host}" in
*-*-mingw*)
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
;;
esac
])# AX_C99_STRTOD
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp file name are based on the header name.

View File

@ -192,6 +192,9 @@ AX_C_PICFLAG
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# may modify LDFLAGS
AX_C99_STRTOD
# Processor specific compile flags
case "${host}" in
alpha*-*-linux*)

View File

@ -1,6 +1,6 @@
%{
/*
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -24,6 +24,7 @@
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include "ivl_alloc.h"
/*

View File

@ -1268,6 +1268,156 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
return tmp;
}
/*
* Routine to look for and build enumeration method calls.
*/
static NetExpr* check_for_enum_methods(const LineInfo*li,
Design*des, NetScope*scope,
netenum_t*netenum,
pform_name_t use_path,
perm_string method_name,
NetExpr*expr,
unsigned rtn_wid,
PExpr*parg, unsigned args)
{
// The "num()" method returns the number of elements.
if (method_name == "num") {
if (args != 0) {
cerr << li->get_fileline() << ": error: enumeration "
"method " << use_path << ".num() does not "
"take an argument." << endl;
des->errors += 1;
}
NetEConst*tmp = make_const_val(netenum->size());
tmp->set_line(*li);
delete expr; // The elaborated enum variable is not needed.
return tmp;
}
// The "first()" method returns the first enumeration value.
if (method_name == "first") {
if (args != 0) {
cerr << li->get_fileline() << ": error: enumeration "
"method " << use_path << ".first() does not "
"take an argument." << endl;
des->errors += 1;
}
netenum_t::iterator item = netenum->first_name();
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
netenum, item->second);
tmp->set_line(*li);
delete expr; // The elaborated enum variable is not needed.
return tmp;
}
// The "last()" method returns the first enumeration value.
if (method_name == "last") {
if (args != 0) {
cerr << li->get_fileline() << ": error: enumeration "
"method " << use_path << ".last() does not "
"take an argument." << endl;
des->errors += 1;
}
netenum_t::iterator item = netenum->last_name();
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
netenum, item->second);
tmp->set_line(*li);
delete expr; // The elaborated enum variable is not needed.
return tmp;
}
NetESFunc*sys_expr;
// Process the method argument if it is available.
NetExpr* count = 0;
if (args != 0 && parg) {
count = elaborate_rval_expr(des, scope, IVL_VT_BOOL, 32, parg);
if (count == 0) {
cerr << li->get_fileline() << ": error: unable to elaborate "
"enumeration method argument " << use_path << "."
<< method_name << "(" << parg << ")." << endl;
args = 0;
des->errors += 1;
} else if (NetEEvent*evt = dynamic_cast<NetEEvent*> (count)) {
cerr << evt->get_fileline() << ": error: An event '"
<< evt->event()->name() << "' cannot be an enumeration "
"method argument." << endl;
args = 0;
des->errors += 1;
}
}
// The "name()" method returns the name of the current
// enumeration value.
if (method_name == "name") {
if (args != 0) {
cerr << li->get_fileline() << ": error: enumeration "
"method " << use_path << ".name() does not "
"take an argument." << endl;
des->errors += 1;
}
sys_expr = new NetESFunc("$ivl_enum_method$name", IVL_VT_STRING,
rtn_wid, 2);
sys_expr->parm(0, new NetENetenum(netenum));
sys_expr->parm(1, expr);
/* The compiler/code generators need to be fixed to support a
* string return value. In some contexts we could use the
* expression width, but that doesn't always work. */
if (rtn_wid == 0) {
cerr << li->get_fileline() << ": sorry: Enumeration method "
"name() is not currently supported in this context "
"(self-determined)." << endl;
des->errors += 1;
}
// The "next()" method returns the next enumeration value.
} else if (method_name == "next") {
if (args > 1) {
cerr << li->get_fileline() << ": error: enumeration "
"method " << use_path << ".next() take at "
"most one argument." << endl;
des->errors += 1;
}
sys_expr = new NetESFunc("$ivl_enum_method$next", netenum,
2 + (args != 0));
sys_expr->parm(0, new NetENetenum(netenum));
sys_expr->parm(1, expr);
if (args != 0) sys_expr->parm(2, count);
// The "prev()" method returns the previous enumeration value.
} else if (method_name == "prev") {
if (args > 1) {
cerr << li->get_fileline() << ": error: enumeration "
"method " << use_path << ".prev() take at "
"most one argument." << endl;
des->errors += 1;
}
sys_expr = new NetESFunc("$ivl_enum_method$prev", netenum,
2 + (args != 0));
sys_expr->parm(0, new NetENetenum(netenum));
sys_expr->parm(1, expr);
if (args != 0) sys_expr->parm(2, count);
// This is an unknown enumeration method.
} else {
cerr << li->get_fileline() << ": error: Unknown enumeration "
"method " << use_path << "." << method_name << "()."
<< endl;
des->errors += 1;
return expr;
}
sys_expr->set_line(*li);
if (debug_elaborate) {
cerr << li->get_fileline() << ": debug: Generate "
<< sys_expr->name() << "(" << use_path << ")" << endl;
}
return sys_expr;
}
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const
{
@ -1286,6 +1436,46 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return elaborate_access_func_(des, scope, access_nature,
expr_wid);
// Maybe this is a method attached to an enumeration name? If
// this is system verilog, then test to see if the name is
// really a method attached to an object.
if (gn_system_verilog() && path_.size() >= 2) {
pform_name_t use_path = path_;
perm_string method_name = peek_tail_name(use_path);
use_path.pop_back();
NetNet *net;
const NetExpr *par;
NetEvent *eve;
const NetExpr *ex1, *ex2;
symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
// Check to see if we have a net and if so is it an
// enumeration? If so then check to see if this is an
// enumeration method call.
if (net != 0) {
netenum_t*netenum = net->enumeration();
if (netenum) {
// We may need the net expression for the
// enumeration variable so get it.
NetESignal*expr = new NetESignal(net);
expr->set_line(*this);
// This expression cannot be a select!
assert(use_path.back().index.empty());
PExpr*tmp = parms_.size() ? parms_[0] : 0;
return check_for_enum_methods(this, des, scope,
netenum, use_path,
method_name, expr,
expr_wid, tmp,
parms_.size());
}
}
}
// Nothing was found so report this as an error.
cerr << get_fileline() << ": error: No function named `" << path_
<< "' found in this context (" << scope_path(scope) << ")."
<< endl;
@ -2087,73 +2277,32 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// Maybe this is a method attached to an enumeration name? If
// this is system verilog, then test to see if the name is
// really a method attached to an object.
if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
pform_name_t use_path = path_;
perm_string method_name = peek_tail_name(use_path);
use_path.pop_back();
found_in = symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
net, par, eve, ex1, ex2);
// Check to see if we have a net and if so is it an
// enumeration? If so then check to see if this is an
// enumeration method call.
if (net != 0) {
// Special case: The net is an enum, and the
// method name is "num".
netenum_t*netenum = net->enumeration();
if (netenum && method_name == "num") {
NetEConst*tmp = make_const_val(netenum->size());
tmp->set_line(*this);
return tmp;
if (netenum) {
// We may need the net expression for the
// enumeration variable so get it.
NetESignal*expr = new NetESignal(net);
expr->set_line(*this);
// This expression cannot be a select!
assert(use_path.back().index.empty());
return check_for_enum_methods(this, des, scope,
netenum,
use_path, method_name,
expr, expr_wid, NULL, 0);
}
// Special case: The net is an enum, and the
// method name is "first" or "last". These
// evaluate to constant values.
if (netenum && method_name == "first") {
netenum_t::iterator item = netenum->first_name();
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
netenum, item->second);
tmp->set_line(*this);
return tmp;
}
if (netenum && method_name == "last") {
netenum_t::iterator item = netenum->last_name();
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
netenum, item->second);
tmp->set_line(*this);
return tmp;
}
NetExpr*expr = elaborate_expr_net(des, scope, net, found_in,
expr_wid, NO_FLAGS);
NetESFunc*sys_expr = 0;
if (method_name == "name") {
sys_expr = new NetESFunc("$ivl_method$name", IVL_VT_STRING,0, 1);
sys_expr->parm(0, expr);
} else if (method_name == "next") {
sys_expr = new NetESFunc("$ivl_method$next", netenum, 2);
sys_expr->parm(0, new NetENetenum(netenum));
sys_expr->parm(1, expr);
} else if (method_name == "prev") {
sys_expr = new NetESFunc("$ivl_method$prev", netenum, 2);
sys_expr->parm(0, new NetENetenum(netenum));
sys_expr->parm(1, expr);
} else {
cerr << get_fileline() << ": error: "
<< "Unknown method name `" << method_name << "'"
<< " attached to " << use_path << "." << endl;
des->errors += 1;
return elaborate_expr_net(des, scope, net, found_in,
expr_wid, NO_FLAGS);
}
sys_expr->set_line(*this);
if (debug_elaborate)
cerr << get_fileline() << ": debug: Generate "
<< sys_expr->name() << "(" << use_path << ")" << endl;
return sys_expr;
}
}

View File

@ -3500,7 +3500,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
/* Elaborate wait expression. Don't eval yet, we will do that
shortly, after we apply a reduction or. */
PExpr::width_mode_t mode;
PExpr::width_mode_t mode = PExpr::SIZED;
pe->test_width(des, scope, mode);
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(),
PExpr::NO_FLAGS);

View File

@ -364,7 +364,6 @@ NetEConst* NetEBComp::eval_leeq_()
left_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(left_, right_, true);
// assert(expr_type() == IVL_VT_LOGIC);
// HERE
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@ -1090,7 +1089,6 @@ NetEConst* NetEBShift::eval_tree()
NetEConst* NetEConcat::eval_tree()
{
// HERE
unsigned repeat_val = repeat();
unsigned local_errors = 0;
@ -1182,7 +1180,6 @@ NetEConst* NetEConcat::eval_tree()
NetEConst* NetESelect::eval_tree()
{
// HERE
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluating expression:"
<< *this << endl;
@ -1846,7 +1843,6 @@ static NetExpr* evaluate_min_max(NetExpr*&arg0_, NetExpr*&arg1_,
NetExpr* NetESFunc::eval_tree()
{
// HERE
/* If we are not targeting at least Verilog-2005, Verilog-AMS
* or using the Icarus misc flag then we do not support these
* functions as constant. */

View File

@ -48,7 +48,7 @@ modules, then exit. It is a convenience for makefiles or automated
plug-in installers.
.TP 8
.B --cflags, --ldflags and -ldlibs
.B --cflags, --ldflags and --ldlibs
These flags provide compile time information.
.SH "PC-ONLY OPTIONS"

View File

@ -1795,14 +1795,14 @@ static void open_input_file(struct include_stack_t*isp)
for (idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1) {
size_t next_len = 6 + strlen(vhdlpp_libdir[idx]);
libs = realloc(libs, liblen+next_len);
snprintf(libs+liblen-1, next_len, " -L'%s'", vhdlpp_libdir[idx]);
snprintf(libs+liblen-1, next_len, " -L\"%s\"", vhdlpp_libdir[idx]);
liblen = strlen(libs) + 1;
}
cmdlen += liblen;
char*cmd = malloc(cmdlen);
snprintf(cmd, cmdlen, "%s -w'%s'%s %s", vhdlpp_path, vhdlpp_work, libs, isp->path);
snprintf(cmd, cmdlen, "%s -w\"%s\"%s %s", vhdlpp_path, vhdlpp_work, libs, isp->path);
if (verbose_flag)
fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);

View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)";
"Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)";
/*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -457,6 +457,14 @@ int main(int argc, char*argv[])
}
free(include_dir);
/* Free the VHDL library directories, the path and work directory. */
for (lp = 0; lp < vhdlpp_libdir_cnt; lp += 1) {
free(vhdlpp_libdir[lp]);
}
free(vhdlpp_libdir);
free(vhdlpp_path);
free(vhdlpp_work);
free_macros();
return error_count;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2010 Michael Ruff (mruff at chiaro.com)
* Copyright (c) 2002-2011 Michael Ruff (mruff at chiaro.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -83,9 +83,24 @@ PLI_INT32 tf_getlongtime(PLI_INT32 *high)
return tf_igetlongtime(high, 0);
}
/* Alias for commercial simulators */
PLI_INT32 tf_getlongsimtime(PLI_INT32 *high) \
__attribute__ ((weak, alias ("tf_getlongtime")));
/*
* This function is not defined in the IEE standard, but is provided for
* compatibility with other simulators. On platforms that support this,
* make it a weak symbol just in case the user has defined their own
* function for this.
*/
#if !defined(__CYGWIN__) && !defined(__MINGW32__)
PLI_INT32 tf_getlongsimtime(PLI_INT32 *high) __attribute__ ((weak));
#endif
PLI_INT32 tf_getlongsimtime(PLI_INT32 *high)
{
s_vpi_time timerec;
timerec.type = vpiSimTime;
vpi_get_time (0, &timerec);
*high = timerec.high;
return timerec.low;
}
void tf_scale_longdelay(void*obj, PLI_INT32 low, PLI_INT32 high,
PLI_INT32 *alow, PLI_INT32 *ahigh)

View File

@ -737,7 +737,7 @@ static double cycles_diff(struct tms *a, struct tms *b)
// Provide dummies
struct tms { int x; };
inline static void times(struct tms *) { }
inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; }
inline static double cycles_diff(struct tms *, struct tms *) { return 0; }
#endif // ! defined(HAVE_TIMES)
static void EOC_cleanup(void)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2010-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -62,7 +62,7 @@ perm_string netenum_t::find_value(const verinum&val) const
{
perm_string res;
for(netenum_t::iterator cur = names_map_.begin();
cur != names_map_.end(); cur++) {
cur != names_map_.end(); ++ cur) {
if (cur->second == val) {
res = cur->first;
break;

View File

@ -589,8 +589,7 @@ void eval_expr(NetExpr*&expr, int context_width)
// The expression is a constant, so resize it if needed.
if (ce->expr_width() < (unsigned)context_width) {
expr = pad_to_width(expr, context_width, *expr);
}
if (ce->expr_width() > (unsigned)context_width) {
} else if (ce->expr_width() > (unsigned)context_width) {
verinum value(ce->value(), context_width);
ce = new NetEConst(value);
ce->set_line(*expr);

View File

@ -1,7 +1,7 @@
#ifndef __sv_vpi_user_H
#define __sv_vpi_user_H
/*
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2010-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -54,6 +54,9 @@ EXTERN_C_START
#define vpiEnumTypespec 633
#define vpiEnumConst 634
/********* One-to-One ***********/
#define vpiBaseTypespec 703
/********* Many-to-One ***********/
#define vpiMember 742

View File

@ -1045,6 +1045,7 @@ bool dll_target::ureduce(const NetUReduce*net)
switch (net->type()) {
case NetUReduce::NONE:
assert(0);
delete obj;
return false;
case NetUReduce::AND:
obj->type = IVL_LPM_RE_AND;

View File

@ -229,7 +229,7 @@ static void show_lpm_arithmetic_pins(ivl_lpm_t net)
{
ivl_nexus_t nex;
nex = ivl_lpm_q(net);
fprintf(out, " Q: %p\n", ivl_lpm_q(net));
fprintf(out, " Q: %p\n", nex);
nex = ivl_lpm_data(net, 0);
fprintf(out, " DataA: %p\n", nex);
@ -247,7 +247,7 @@ static void show_lpm_abs(ivl_lpm_t net)
ivl_lpm_basename(net), width);
nex = ivl_lpm_q(net);
fprintf(out, " Q: %p\n", ivl_lpm_q(net));
fprintf(out, " Q: %p\n", nex);
nex = ivl_lpm_data(net, 0);
fprintf(out, " D: %p\n", nex);
@ -690,6 +690,7 @@ static void show_lpm_re(ivl_lpm_t net)
break;
case IVL_LPM_RE_NOR:
type = "NOR";
break;
case IVL_LPM_RE_XOR:
type = "XOR";
break;

View File

@ -1,7 +1,7 @@
/*
* VHDL code generation for statements.
*
* Copyright (C) 2008-2010 Nick Gasson (nick@nickg.me.uk)
* Copyright (C) 2008-2011 Nick Gasson (nick@nickg.me.uk)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -1312,6 +1312,15 @@ static bool process_signal(vhdl_binop_expr *all, vhdl_var_ref *test,
}
unsigned ewid = ivl_expr_width(expr);
if (sizeof(unsigned) >= sizeof(long)) {
// Since we will be casting i (constrained by swid) to a long make sure
// it will fit into a long. This is actually off by one, but this is the
// best we can do since on 32 bit machines an unsigned and long are the
// same size.
assert(swid <= static_cast<unsigned>(numeric_limits<long>::max()));
// We are also going to cast ewid to long so check it as well.
assert(ewid <= static_cast<unsigned>(numeric_limits<long>::max()));
}
for (unsigned i = 0; i < swid; i++) {
// Generate a comparison for this bit position
vhdl_binop_expr *cmp;
@ -1321,7 +1330,8 @@ static bool process_signal(vhdl_binop_expr *all, vhdl_var_ref *test,
// Check if this is an out of bounds access. If this is a casez
// then check against a constant 'x' for the out of bound bits
// otherwise skip the check (casex).
if (i + sbase >= ewid || i + sbase < 0) {
if (static_cast<long>(i) + sbase >= static_cast<long>(ewid) ||
static_cast<long>(i) + sbase < 0) {
if (is_casez) {
// Get the current test bit.
type = vhdl_type::nunsigned(width);

View File

@ -1015,7 +1015,6 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
emit_nexus_as_ca(scope, nex);
if (have_data | have_sset) fprintf(vlog_out, " & ");
if (have_data & have_sset) fprintf(vlog_out, "(");
emitted = 1;
}
nex = ivl_lpm_sync_set(lpm);
if (nex) {

View File

@ -20,6 +20,7 @@
# include <string.h>
# include "config.h"
# include "vlog95_priv.h"
# include "ivl_alloc.h"
static void emit_entry(ivl_udp_t udp, char entry, unsigned *rerun)
{

View File

@ -1276,10 +1276,31 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
}
if (ivl_signal_width(lsig) > ivl_signal_width(rsig) ||
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s signal to "
"a bit/part select.\n", ivl_expr_file(rval),
ivl_expr_lineno(rval), command_name);
exit(1);
/* Normalize the bit/part select. */
long real_msb = ivl_signal_msb(lsig);
long real_lsb = ivl_signal_lsb(lsig);
long use_wid = ivl_signal_width(rsig);
long use_lsb, use_msb;
if (real_msb >= real_lsb) {
use_lsb = get_number_immediate(part_off_ex);
use_lsb += real_lsb;
use_msb = use_lsb + use_wid - 1;
} else {
use_lsb = real_lsb;
use_lsb -= get_number_immediate(part_off_ex);
use_msb = use_lsb;
use_msb -= use_wid - 1;
}
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s signal to a ",
ivl_stmt_file(net), ivl_stmt_lineno(net), command_name);
if (use_wid > 1) {
fprintf(stderr, "part select (%s[%lu:%lu]).\n",
ivl_signal_basename(lsig), use_msb, use_lsb);
} else {
fprintf(stderr, "bit select (%s[%lu]).\n",
ivl_signal_basename(lsig), use_lsb);
}
vvp_errors += 1;
}
/* At least for now, only handle force to fixed words of an array. */
@ -1287,17 +1308,42 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
assert(number_is_immediate(lword_idx, IMM_WID, 0));
assert(! number_is_unknown(lword_idx));
use_lword = get_number_immediate(lword_idx);
/* We do not currently support using a word from a variable
* array as the L-value (Icarus extension). */
if (ivl_signal_type(lsig) == IVL_SIT_REG) {
/* Normalize the array access. */
long real_word = use_lword;
real_word += ivl_signal_array_base(lsig);
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s to the "
"word of a variable array (%s[%ld]).\n",
ivl_stmt_file(net), ivl_stmt_lineno(net),
command_name, ivl_signal_basename(lsig), real_word);
vvp_errors += 1;
}
}
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
assert(ivl_signal_dimensions(rsig) != 0);
assert(number_is_immediate(rword_idx, IMM_WID, 0));
assert(! number_is_unknown(rword_idx));
use_rword = get_number_immediate(rword_idx);
/* We do not currently support using a word from a variable
* array as the R-value. */
if (ivl_signal_type(rsig) == IVL_SIT_REG) {
/* Normalize the array access. */
long real_word = use_rword;
real_word += ivl_signal_array_base(rsig);
fprintf(stderr, "%s:%u: tgt-vvp sorry: cannot %s from the "
"word of a variable array (%s[%ld]).\n",
ivl_expr_file(rval), ivl_expr_lineno(rval),
command_name, ivl_signal_basename(rsig), real_word);
vvp_errors += 1;
}
} else {
assert(ivl_signal_dimensions(rsig) == 0);
use_rword = 0;
}
assert(ivl_signal_dimensions(rsig) == 0);
use_rword = 0;
fprintf(vvp_out, " %s/link", command_name);
fprintf(vvp_out, " v%p_%lu", lsig, use_lword);
fprintf(vvp_out, ", v%p_%lu;\n", rsig, use_rword);

View File

@ -162,8 +162,8 @@ Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag)
ExpAggregate::element_t::element_t(list<choice_t*>*fields, Expression*val)
: fields_(fields? fields->size() : 0), val_(val)
{
size_t idx = 0;
if (fields) {
size_t idx = 0;
while (! fields->empty()) {
assert(idx < fields_.size());
fields_[idx++] = fields->front();

View File

@ -278,7 +278,7 @@ static bool is_based_correct(char* text)
if(base == 0)
return 0;
}
bool point = 0;
bool point = false;
set<char> allowed_chars;
unsigned c;
@ -299,12 +299,12 @@ static bool is_based_correct(char* text)
if(*ptr == '.')
{
//we found a dot and another one was already found
if(point == 1)
if(point)
return 0;
else
{
//notice the fact of finding a point and continue, without increasing the length
point = 1;
point = true;
continue;
}
}

View File

@ -81,6 +81,10 @@ const char NOTICE[] =
# include <getopt.h>
#endif
# include <sys/stat.h>
#if defined(__MINGW32__)
# include <io.h>
# define mkdir(path, mode) _mkdir(path)
#endif
bool verbose_flag = false;

View File

@ -118,7 +118,7 @@ class Scope : public ScopeBase {
class ActiveScope : public ScopeBase {
public:
ActiveScope() { }
ActiveScope() : context_entity_(0) { }
ActiveScope(ActiveScope*par) : ScopeBase(*par), context_entity_(0) { }
~ActiveScope() { }

View File

@ -151,7 +151,7 @@ va_math.vpi: $V ../vvp/libvpi.a
$(CC) @shared@ -o $@ $V -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS)
vhdl_sys.vpi: $(VHDL_SYS) ../vvp/libvpi.a
$(CXX) @shared@ -o $@ $(VHDL_SYS) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
$(CC) @shared@ -o $@ $(VHDL_SYS) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
stamp-vpi_config-h: $(srcdir)/vpi_config.h.in ../config.status
@rm -f $@

View File

@ -3,22 +3,23 @@
// problems will not be fixed.
// fstapi.c from GTKWave
variableScope:fstapi.c:1689
variableScope:fstapi.c:1817
variableScope:fstapi.c:1911
variableScope:fstapi.c:1912
variableScope:fstapi.c:2617
variableScope:fstapi.c:2937
variableScope:fstapi.c:2941
variableScope:fstapi.c:2942
variableScope:fstapi.c:1713
variableScope:fstapi.c:1841
variableScope:fstapi.c:1935
variableScope:fstapi.c:1936
variableScope:fstapi.c:2642
variableScope:fstapi.c:2962
variableScope:fstapi.c:2966
variableScope:fstapi.c:2967
variableScope:fstapi.c:4641
// lxt2_write.c from GTKWave
variableScope:lxt2_write.c:63
variableScope:lxt2_write.c:523
variableScope:lxt2_write.c:581
variableScope:lxt2_write.c:587
variableScope:lxt2_write.c:1602
variableScope:lxt2_write.c:2049
variableScope:lxt2_write.c:1600
variableScope:lxt2_write.c:2047
// lxt_write.c from GTKWave
variableScope:lxt_write.c:31

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2010 Tony Bybell.
* Copyright (c) 2009-2011 Tony Bybell.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -505,6 +505,7 @@ unsigned repack_on_close : 1;
unsigned skip_writing_section_hdr : 1;
unsigned size_limit_locked : 1;
unsigned section_header_only : 1;
unsigned flush_context_pending : 1;
/* should really be semaphores, but are bytes to cut down on read-modify-write window size */
unsigned char already_in_flush; /* in case control-c handlers interrupt */
@ -758,272 +759,6 @@ return(xc);
}
void fstWriterClose(void *ctx)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if(xc && !xc->already_in_close && !xc->already_in_flush)
{
unsigned char *tmem;
off_t fixup_offs, tlen, hlen;
xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */
if(xc->section_header_only && xc->section_header_truncpos && (xc->vchg_siz <= 1) && (!xc->is_initial_time))
{
fstFtruncate(fileno(xc->handle), xc->section_header_truncpos);
fseeko(xc->handle, xc->section_header_truncpos, SEEK_SET);
xc->section_header_only = 0;
}
else
{
xc->skip_writing_section_hdr = 1;
if(!xc->size_limit_locked)
{
if(xc->is_initial_time) /* simulation time never advanced so mock up the changes as time zero ones */
{
fstHandle dupe_idx;
fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */
for(dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */
{
fstWriterEmitValueChange(xc, dupe_idx+1, xc->curval_mem + xc->valpos_mem[4*dupe_idx]);
}
}
fstWriterFlushContext(xc);
}
}
fstDestroyMmaps(xc, 1);
/* write out geom section */
fflush(xc->geom_handle);
tlen = ftello(xc->geom_handle);
tmem = fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0);
if(tmem)
{
unsigned long destlen = tlen;
unsigned char *dmem = malloc(destlen);
int rc = compress2(dmem, &destlen, tmem, tlen, 9);
if((rc != Z_OK) || (destlen > tlen))
{
destlen = tlen;
}
fixup_offs = ftello(xc->handle);
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
fstWriterUint64(xc->handle, destlen + 24); /* section length */
fstWriterUint64(xc->handle, tlen); /* uncompressed */
/* compressed len is section length - 24 */
fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */
fstFwrite((destlen != tlen) ? dmem : tmem, destlen, 1, xc->handle);
fflush(xc->handle);
fseeko(xc->handle, fixup_offs, SEEK_SET);
fputc(FST_BL_GEOM, xc->handle); /* actual tag */
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
fflush(xc->handle);
free(dmem);
fstMunmap(tmem, tlen);
}
if(xc->num_blackouts)
{
uint64_t cur_bl = 0;
off_t bpos, eos;
uint32_t i;
fixup_offs = ftello(xc->handle);
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
bpos = fixup_offs + 1;
fstWriterUint64(xc->handle, 0); /* section length */
fstWriterVarint(xc->handle, xc->num_blackouts);
for(i=0;i<xc->num_blackouts;i++)
{
fputc(xc->blackout_head->active, xc->handle);
fstWriterVarint(xc->handle, xc->blackout_head->tim - cur_bl);
cur_bl = xc->blackout_head->tim;
xc->blackout_curr = xc->blackout_head->next;
free(xc->blackout_head);
xc->blackout_head = xc->blackout_curr;
}
eos = ftello(xc->handle);
fseeko(xc->handle, bpos, SEEK_SET);
fstWriterUint64(xc->handle, eos - bpos);
fflush(xc->handle);
fseeko(xc->handle, fixup_offs, SEEK_SET);
fputc(FST_BL_BLACKOUT, xc->handle); /* actual tag */
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
fflush(xc->handle);
}
if(xc->compress_hier)
{
unsigned char *mem = malloc(FST_GZIO_LEN);
off_t hl, eos;
gzFile zhandle;
int zfd;
#ifndef __MINGW32__
char *fnam = malloc(strlen(xc->filename) + 5 + 1);
#endif
fixup_offs = ftello(xc->handle);
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
hlen = ftello(xc->handle);
fstWriterUint64(xc->handle, 0); /* section length */
fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */
fflush(xc->handle);
zfd = dup(fileno(xc->handle));
zhandle = gzdopen(zfd, "wb4");
if(zhandle)
{
fseeko(xc->hier_handle, 0, SEEK_SET);
for(hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN)
{
unsigned len = ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl);
fstFread(mem, len, 1, xc->hier_handle);
gzwrite(zhandle, mem, len);
}
gzclose(zhandle);
}
else
{
close(zfd);
}
free(mem);
fseeko(xc->handle, 0, SEEK_END);
eos = ftello(xc->handle);
fseeko(xc->handle, hlen, SEEK_SET);
fstWriterUint64(xc->handle, eos - hlen);
fflush(xc->handle);
fseeko(xc->handle, fixup_offs, SEEK_SET);
fputc(FST_BL_HIER, xc->handle); /* actual tag */
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
fflush(xc->handle);
#ifndef __MINGW32__
sprintf(fnam, "%s.hier", xc->filename);
unlink(fnam);
free(fnam);
#endif
}
/* finalize out header */
fseeko(xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET);
fstWriterUint64(xc->handle, xc->firsttime);
fstWriterUint64(xc->handle, xc->curtime);
fseeko(xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET);
fstWriterUint64(xc->handle, xc->numscopes);
fstWriterUint64(xc->handle, xc->numsigs);
fstWriterUint64(xc->handle, xc->maxhandle);
fstWriterUint64(xc->handle, xc->secnum);
fflush(xc->handle);
if(xc->tchn_handle) { fclose(xc->tchn_handle); xc->tchn_handle = NULL; }
free(xc->vchg_mem); xc->vchg_mem = NULL;
if(xc->curval_handle) { fclose(xc->curval_handle); xc->curval_handle = NULL; }
if(xc->valpos_handle) { fclose(xc->valpos_handle); xc->valpos_handle = NULL; }
if(xc->geom_handle) { fclose(xc->geom_handle); xc->geom_handle = NULL; }
if(xc->hier_handle) { fclose(xc->hier_handle); xc->hier_handle = NULL; }
if(xc->handle)
{
if(xc->repack_on_close)
{
FILE *fp;
off_t offpnt, uclen;
int flen = strlen(xc->filename);
char *hf = calloc(1, flen + 5);
strcpy(hf, xc->filename);
strcpy(hf+flen, ".pak");
fp = fopen(hf, "wb");
if(fp)
{
void *dsth;
int zfd;
char gz_membuf[FST_GZIO_LEN];
fseeko(xc->handle, 0, SEEK_END);
uclen = ftello(xc->handle);
fputc(FST_BL_ZWRAPPER, fp);
fstWriterUint64(fp, 0);
fstWriterUint64(fp, uclen);
fflush(fp);
fseeko(xc->handle, 0, SEEK_SET);
zfd = dup(fileno(fp));
dsth = gzdopen(zfd, "wb4");
if(dsth)
{
for(offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN)
{
size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt);
fstFread(gz_membuf, this_len, 1, xc->handle);
gzwrite(dsth, gz_membuf, this_len);
}
gzclose(dsth);
}
else
{
close(zfd);
}
fseeko(fp, 0, SEEK_END);
offpnt = ftello(fp);
fseeko(fp, 1, SEEK_SET);
fstWriterUint64(fp, offpnt - 1);
fclose(fp);
fclose(xc->handle); xc->handle = NULL;
unlink(xc->filename);
rename(hf, xc->filename);
}
else
{
xc->repack_on_close = 0;
fclose(xc->handle); xc->handle = NULL;
}
free(hf);
}
else
{
fclose(xc->handle); xc->handle = NULL;
}
}
#ifdef __MINGW32__
{
int flen = strlen(xc->filename);
char *hf = calloc(1, flen + 6);
strcpy(hf, xc->filename);
if(xc->compress_hier)
{
strcpy(hf + flen, ".hier");
unlink(hf); /* no longer needed as a section now exists for this */
}
free(hf);
}
#endif
free(xc->filename); xc->filename = NULL;
free(xc);
}
}
/*
* generation and writing out of value change data sections
*/
@ -1074,7 +809,11 @@ if(xc)
}
void fstWriterFlushContext(void *ctx)
/*
* only to be called directly by fst code...otherwise must
* be synced up with time changes
*/
static void fstWriterFlushContextPrivate(void *ctx)
{
#ifdef FST_DEBUG
int cnt = 0;
@ -1409,7 +1148,7 @@ for(i=0;i<xc->maxhandle;i++)
JudyHSFreeArray(&PJHSArray, NULL);
#endif
free(packmem); packmem = NULL; packmemlen = 0;
free(packmem); packmem = NULL; /* packmemlen = 0; */ /* scan-build */
prevpos = 0; zerocnt = 0;
free(scratchpad); scratchpad = NULL;
@ -1449,7 +1188,7 @@ for(i=0;i<xc->maxhandle;i++)
}
if(zerocnt)
{
fpos += fstWriterVarint(f, (zerocnt << 1));
/* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */
}
#ifdef FST_DEBUG
printf("value chains: %d\n", cnt);
@ -1538,6 +1277,291 @@ xc->already_in_flush = 0;
}
/*
* queues up a flush context operation
*/
void fstWriterFlushContext(void *ctx)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if(xc)
{
if(xc->tchn_idx > 1)
{
xc->flush_context_pending = 1;
}
}
}
/*
* close out FST file
*/
void fstWriterClose(void *ctx)
{
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
if(xc && !xc->already_in_close && !xc->already_in_flush)
{
unsigned char *tmem;
off_t fixup_offs, tlen, hlen;
xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */
if(xc->section_header_only && xc->section_header_truncpos && (xc->vchg_siz <= 1) && (!xc->is_initial_time))
{
fstFtruncate(fileno(xc->handle), xc->section_header_truncpos);
fseeko(xc->handle, xc->section_header_truncpos, SEEK_SET);
xc->section_header_only = 0;
}
else
{
xc->skip_writing_section_hdr = 1;
if(!xc->size_limit_locked)
{
if(xc->is_initial_time) /* simulation time never advanced so mock up the changes as time zero ones */
{
fstHandle dupe_idx;
fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */
for(dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */
{
fstWriterEmitValueChange(xc, dupe_idx+1, xc->curval_mem + xc->valpos_mem[4*dupe_idx]);
}
}
fstWriterFlushContextPrivate(xc);
}
}
fstDestroyMmaps(xc, 1);
/* write out geom section */
fflush(xc->geom_handle);
tlen = ftello(xc->geom_handle);
tmem = fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0);
if(tmem)
{
unsigned long destlen = tlen;
unsigned char *dmem = malloc(destlen);
int rc = compress2(dmem, &destlen, tmem, tlen, 9);
if((rc != Z_OK) || (destlen > tlen))
{
destlen = tlen;
}
fixup_offs = ftello(xc->handle);
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
fstWriterUint64(xc->handle, destlen + 24); /* section length */
fstWriterUint64(xc->handle, tlen); /* uncompressed */
/* compressed len is section length - 24 */
fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */
fstFwrite((destlen != tlen) ? dmem : tmem, destlen, 1, xc->handle);
fflush(xc->handle);
fseeko(xc->handle, fixup_offs, SEEK_SET);
fputc(FST_BL_GEOM, xc->handle); /* actual tag */
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
fflush(xc->handle);
free(dmem);
fstMunmap(tmem, tlen);
}
if(xc->num_blackouts)
{
uint64_t cur_bl = 0;
off_t bpos, eos;
uint32_t i;
fixup_offs = ftello(xc->handle);
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
bpos = fixup_offs + 1;
fstWriterUint64(xc->handle, 0); /* section length */
fstWriterVarint(xc->handle, xc->num_blackouts);
for(i=0;i<xc->num_blackouts;i++)
{
fputc(xc->blackout_head->active, xc->handle);
fstWriterVarint(xc->handle, xc->blackout_head->tim - cur_bl);
cur_bl = xc->blackout_head->tim;
xc->blackout_curr = xc->blackout_head->next;
free(xc->blackout_head);
xc->blackout_head = xc->blackout_curr;
}
eos = ftello(xc->handle);
fseeko(xc->handle, bpos, SEEK_SET);
fstWriterUint64(xc->handle, eos - bpos);
fflush(xc->handle);
fseeko(xc->handle, fixup_offs, SEEK_SET);
fputc(FST_BL_BLACKOUT, xc->handle); /* actual tag */
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
fflush(xc->handle);
}
if(xc->compress_hier)
{
unsigned char *mem = malloc(FST_GZIO_LEN);
off_t hl, eos;
gzFile zhandle;
int zfd;
#ifndef __MINGW32__
char *fnam = malloc(strlen(xc->filename) + 5 + 1);
#endif
fixup_offs = ftello(xc->handle);
fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
hlen = ftello(xc->handle);
fstWriterUint64(xc->handle, 0); /* section length */
fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */
fflush(xc->handle);
zfd = dup(fileno(xc->handle));
zhandle = gzdopen(zfd, "wb4");
if(zhandle)
{
fseeko(xc->hier_handle, 0, SEEK_SET);
for(hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN)
{
unsigned len = ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl);
fstFread(mem, len, 1, xc->hier_handle);
gzwrite(zhandle, mem, len);
}
gzclose(zhandle);
}
else
{
close(zfd);
}
free(mem);
fseeko(xc->handle, 0, SEEK_END);
eos = ftello(xc->handle);
fseeko(xc->handle, hlen, SEEK_SET);
fstWriterUint64(xc->handle, eos - hlen);
fflush(xc->handle);
fseeko(xc->handle, fixup_offs, SEEK_SET);
fputc(FST_BL_HIER, xc->handle); /* actual tag */
fseeko(xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
fflush(xc->handle);
#ifndef __MINGW32__
sprintf(fnam, "%s.hier", xc->filename);
unlink(fnam);
free(fnam);
#endif
}
/* finalize out header */
fseeko(xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET);
fstWriterUint64(xc->handle, xc->firsttime);
fstWriterUint64(xc->handle, xc->curtime);
fseeko(xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET);
fstWriterUint64(xc->handle, xc->numscopes);
fstWriterUint64(xc->handle, xc->numsigs);
fstWriterUint64(xc->handle, xc->maxhandle);
fstWriterUint64(xc->handle, xc->secnum);
fflush(xc->handle);
if(xc->tchn_handle) { fclose(xc->tchn_handle); xc->tchn_handle = NULL; }
free(xc->vchg_mem); xc->vchg_mem = NULL;
if(xc->curval_handle) { fclose(xc->curval_handle); xc->curval_handle = NULL; }
if(xc->valpos_handle) { fclose(xc->valpos_handle); xc->valpos_handle = NULL; }
if(xc->geom_handle) { fclose(xc->geom_handle); xc->geom_handle = NULL; }
if(xc->hier_handle) { fclose(xc->hier_handle); xc->hier_handle = NULL; }
if(xc->handle)
{
if(xc->repack_on_close)
{
FILE *fp;
off_t offpnt, uclen;
int flen = strlen(xc->filename);
char *hf = calloc(1, flen + 5);
strcpy(hf, xc->filename);
strcpy(hf+flen, ".pak");
fp = fopen(hf, "wb");
if(fp)
{
void *dsth;
int zfd;
char gz_membuf[FST_GZIO_LEN];
fseeko(xc->handle, 0, SEEK_END);
uclen = ftello(xc->handle);
fputc(FST_BL_ZWRAPPER, fp);
fstWriterUint64(fp, 0);
fstWriterUint64(fp, uclen);
fflush(fp);
fseeko(xc->handle, 0, SEEK_SET);
zfd = dup(fileno(fp));
dsth = gzdopen(zfd, "wb4");
if(dsth)
{
for(offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN)
{
size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt);
fstFread(gz_membuf, this_len, 1, xc->handle);
gzwrite(dsth, gz_membuf, this_len);
}
gzclose(dsth);
}
else
{
close(zfd);
}
fseeko(fp, 0, SEEK_END);
offpnt = ftello(fp);
fseeko(fp, 1, SEEK_SET);
fstWriterUint64(fp, offpnt - 1);
fclose(fp);
fclose(xc->handle); xc->handle = NULL;
unlink(xc->filename);
rename(hf, xc->filename);
}
else
{
xc->repack_on_close = 0;
fclose(xc->handle); xc->handle = NULL;
}
free(hf);
}
else
{
fclose(xc->handle); xc->handle = NULL;
}
}
#ifdef __MINGW32__
{
int flen = strlen(xc->filename);
char *hf = calloc(1, flen + 6);
strcpy(hf, xc->filename);
if(xc->compress_hier)
{
strcpy(hf + flen, ".hier");
unlink(hf); /* no longer needed as a section now exists for this */
}
free(hf);
}
#endif
free(xc->filename); xc->filename = NULL;
free(xc);
}
}
/*
* functions to set miscellaneous header/block information
*/
@ -1940,9 +1964,10 @@ if(xc)
}
else
{
if(xc->vchg_siz >= FST_BREAK_SIZE)
if((xc->vchg_siz >= FST_BREAK_SIZE) || (xc->flush_context_pending))
{
fstWriterFlushContext(xc);
xc->flush_context_pending = 0;
fstWriterFlushContextPrivate(xc);
xc->tchn_cnt++;
fstWriterVarint(xc->tchn_handle, xc->curtime);
}
@ -3359,7 +3384,10 @@ uint64_t tsec_nitems;
int secnum = 0;
int blocks_skipped = 0;
off_t blkpos = 0;
uint64_t seclen, beg_tim, end_tim;
uint64_t seclen, beg_tim;
#ifdef FST_DEBUG
uint64_t end_tim;
#endif
uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle;
off_t vc_start;
off_t indx_pntr, indx_pos;
@ -3414,7 +3442,10 @@ for(;;)
if(!seclen) break;
beg_tim = fstReaderUint64(xc->f);
end_tim = fstReaderUint64(xc->f);
#ifdef FST_DEBUG
end_tim =
#endif
fstReaderUint64(xc->f);
if(xc->limit_range_valid)
{
@ -3443,8 +3474,8 @@ for(;;)
{
unsigned char *ucdata;
unsigned char *cdata;
unsigned long destlen = tsec_uclen;
unsigned long sourcelen = tsec_clen;
unsigned long destlen /* = tsec_uclen */; /* scan-build */
unsigned long sourcelen /*= tsec_clen */; /* scan-build */
int rc;
unsigned char *tpnt;
uint64_t tpval;
@ -3896,12 +3927,12 @@ for(;;)
unsigned char val;
if(!(vli & 1))
{
tdelta = vli >> 2;
/* tdelta = vli >> 2; */ /* scan-build */
val = ((vli >> 1) & 1) | '0';
}
else
{
tdelta = vli >> 4;
/* tdelta = vli >> 4; */ /* scan-build */
val = FST_RCV_STR[((vli >> 1) & 7)];
}
@ -3946,7 +3977,7 @@ for(;;)
vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
len = fstGetVarint32(mem_for_traversal + headptr[idx] + skiplen, &skiplen2);
tdelta = vli >> 1;
/* tdelta = vli >> 1; */ /* scan-build */
skiplen += skiplen2;
vdata = mem_for_traversal + headptr[idx] + skiplen;
@ -4002,7 +4033,7 @@ for(;;)
unsigned char *vdata;
vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
tdelta = vli >> 1;
/* tdelta = vli >> 1; */ /* scan-build */
vdata = mem_for_traversal + headptr[idx] + skiplen;
if(xc->signal_typs[idx] != FST_VT_VCD_REAL)
@ -4058,7 +4089,7 @@ for(;;)
else
{
double d;
unsigned char *clone_d = (unsigned char *)&d;
unsigned char *clone_d /*= (unsigned char *)&d */; /* scan-build */
unsigned char buf[8];
unsigned char *srcdata;
@ -4261,7 +4292,9 @@ uint64_t seclen;
uint64_t tsec_uclen = 0, tsec_clen = 0;
uint64_t tsec_nitems;
uint64_t frame_uclen, frame_clen;
#ifdef FST_DEBUG
uint64_t mem_required_for_traversal;
#endif
off_t indx_pntr, indx_pos;
long chain_clen;
unsigned char *chain_cmem;
@ -4352,7 +4385,11 @@ for(;;)
xc->rvat_beg_tim = beg_tim;
xc->rvat_end_tim = end_tim;
mem_required_for_traversal = fstReaderUint64(xc->f);
#ifdef FST_DEBUG
mem_required_for_traversal =
#endif
fstReaderUint64(xc->f);
#ifdef FST_DEBUG
printf("rvat sec: %d seclen: %d begtim: %d endtim: %d\n",
secnum, (int)seclen, (int)beg_tim, (int)end_tim);
@ -4363,8 +4400,8 @@ printf("\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
{
unsigned char *ucdata;
unsigned char *cdata;
unsigned long destlen = tsec_uclen;
unsigned long sourcelen = tsec_clen;
unsigned long destlen /* = tsec_uclen */; /* scan-build */
unsigned long sourcelen /* = tsec_clen */; /* scan-build */
int rc;
unsigned char *tpnt;
uint64_t tpval;
@ -4628,7 +4665,7 @@ if(xc->signal_lens[facidx] == 1)
iprev = i;
pvli = vli;
ptidx = tidx;
pskip = skiplen;
/* pskip = skiplen; */ /* scan-build */
tidx += tdelta;
i+=skiplen;

View File

@ -1144,7 +1144,7 @@ unsigned int total_chgs;
unsigned int partial_length;
total_chgs = 0;
partial_length = 0;
/* partial_length = 0; */ /* scan-build : never read */
iter_hi = iter + partial_iter;
if(iter_hi > lt->numfacs) iter_hi = lt->numfacs;
@ -1491,8 +1491,6 @@ if(lt)
if( (!lt->timepos) && (!lt->timegranule) && ((!lt->numblock)||(!lt->no_checkpoint)) )
{
struct lxt2_wr_symbol *s = lt->symchain;
/* fprintf(stderr, "initial value burst timepos==0, timegranule==0\n"); */
if(lt->blackout)
{
@ -1501,7 +1499,7 @@ if(lt)
}
else
{
s = lt->symchain;
struct lxt2_wr_symbol *s = lt->symchain;
while(s)
{
if((!(s->flags&LXT2_WR_SYM_F_ALIAS))&&(s->rows<2))

View File

@ -248,9 +248,11 @@ static void get_time(char *rtn, const char *value, int prec,
static void get_time_real(char *rtn, double value, int prec,
PLI_INT32 time_units)
{
/* Scale the value if its time units differ from the format units. */
if (time_units != timeformat_info.units) {
/* Scale the value from its time units to the format time units. */
if (time_units >= timeformat_info.units) {
value *= pow(10.0, time_units - timeformat_info.units);
} else {
value /= pow(10.0, timeformat_info.units - time_units);
}
sprintf(rtn, "%0.*f%s", prec, value, timeformat_info.suff);
}
@ -444,7 +446,9 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
strcpy(cpb+pad, cp);
/* If a width was not given, use the default, unless we have a
* leading zero (width of zero). */
* leading zero (width of zero). Because the width of a real in
* Icarus is 1 the string length will set the width of a real
* displayed using %d. */
if (width == -1) {
width = (ld_zero == 1) ? 0 : vpi_get_dec_size(info->items[*idx]);
}
@ -856,7 +860,7 @@ static unsigned int get_format(char **rtn, char *fmt,
static unsigned int get_numeric(char **rtn, const struct strobe_cb_info *info,
vpiHandle item)
{
int size;
int size, min;
s_vpi_value val;
val.format = info->default_format;
@ -865,6 +869,11 @@ static unsigned int get_numeric(char **rtn, const struct strobe_cb_info *info,
switch(info->default_format){
case vpiDecStrVal:
size = vpi_get_dec_size(item);
/* -1 can be represented as a one bit signed value. This returns
* a size of 1 which is too small for the -1 string value so make
* the string width the minimum display width. */
min = strlen(val.value.str);
if (size < min) size = min;
*rtn = malloc((size+1)*sizeof(char));
sprintf(*rtn, "%*s", size, val.value.str);
break;

View File

@ -45,7 +45,7 @@ static PLI_INT32 task_not_implemented_compiletf(ICARUS_VPI_CONST PLI_BYTE8* name
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpi_printf("%s:%d: SORRY: task %s() is not currently implemented.\n",
vpi_printf("SORRY: %s:%d: task %s() is not currently implemented.\n",
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
name);
vpi_control(vpiFinish, 1);
@ -60,7 +60,7 @@ static PLI_INT32 missing_optional_compiletf(ICARUS_VPI_CONST PLI_BYTE8* name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpi_printf("%s:%d: SORRY: %s() is not available in Icarus verilog.\n",
vpi_printf("SORRY: %s:%d: %s() is not available in Icarus verilog.\n",
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
name);
vpi_control(vpiFinish, 1);

View File

@ -524,7 +524,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
struct t_cb_data cb;
struct vcd_info* info;
const char* type;
const char* name;
const char* ident;
int nexus_id;
@ -547,7 +546,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
switch (vpi_get(vpiType, item)) {
case vpiNet: type = "wire"; if(0){
case vpiMemoryWord:
if (vpi_get(vpiConstantSelect, item) == 0) {
/* Turn a non-constant array word select into a
@ -563,7 +561,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiIntVar:
case vpiLongIntVar:
case vpiTimeVar:
case vpiReg: type = "reg"; }
case vpiReg:
case vpiNet:
/* An array word is implicitly escaped so look for an
* escaped identifier that this could conflict with. */
@ -656,11 +655,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
break;
case vpiModule: type = "module"; if(0){
case vpiNamedBegin: type = "begin"; }if(0){
case vpiTask: type = "task"; }if(0){
case vpiFunction: type = "function"; }if(0){
case vpiNamedFork: type = "fork"; }
case vpiModule:
case vpiNamedBegin:
case vpiTask:
case vpiFunction:
case vpiNamedFork:
if (depth > 0) {
int nskip;
@ -683,7 +682,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
name = vpi_get_str(vpiName, item);
push_scope(name); /* keep in type info determination for possible future usage */
push_scope(name);
for (i=0; types[i]>0; i++) {
vpiHandle hand;

View File

@ -587,7 +587,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
struct t_cb_data cb;
struct vcd_info* info;
const char* type;
const char* name;
const char* ident;
int nexus_id;
@ -610,7 +609,6 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
switch (vpi_get(vpiType, item)) {
case vpiNet: type = "wire"; if(0){
case vpiMemoryWord:
if (vpi_get(vpiConstantSelect, item) == 0) {
/* Turn a non-constant array word select into a
@ -626,7 +624,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
case vpiIntVar:
case vpiLongIntVar:
case vpiTimeVar:
case vpiReg: type = "reg"; }
case vpiReg:
case vpiNet:
/* An array word is implicitly escaped so look for an
* escaped identifier that this could conflict with. */
@ -711,11 +710,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
break;
case vpiModule: type = "module"; if(0){
case vpiNamedBegin: type = "begin"; }if(0){
case vpiTask: type = "task"; }if(0){
case vpiFunction: type = "function"; }if(0){
case vpiNamedFork: type = "fork"; }
case vpiModule:
case vpiNamedBegin:
case vpiTask:
case vpiFunction:
case vpiNamedFork:
if (depth > 0) {
int nskip;
@ -738,7 +737,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
name = vpi_get_str(vpiName, item);
push_scope(name); /* keep in type info determination for possible future usage */
push_scope(name);
for (i=0; types[i]>0; i++) {
vpiHandle hand;

View File

@ -567,6 +567,7 @@ static PLI_INT32 sys_urandom_range_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
/* Check that there are at least two arguments. */
arg = vpi_scan(argv); /* This should never be zero. */
assert(arg);
arg = vpi_scan(argv);
if (arg == 0) {
vpi_printf("ERROR: %s requires two arguments.\n", name);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -95,7 +95,9 @@ static PLI_INT32 sys_realtime_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
/* For $abstime() we return the time in second. */
if (strcmp(name, "$abstime") == 0) {
now.real *= pow(10.0, vpi_get(vpiTimeUnit, mod));
PLI_INT32 scale = vpi_get(vpiTimeUnit, mod);
if (scale >= 0) now.real *= pow(10.0, scale);
else now.real /= pow(10.0, -scale);
}
val.format = vpiRealVal;

View File

@ -2,7 +2,7 @@
* Verilog-2005 math library for Icarus Verilog
* http://www.icarus.com/eda/verilog/
*
* Copyright (C) 2007-2010 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2007-2011 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -191,6 +191,7 @@ static PLI_INT32 va_single_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
arg = vpi_scan(argv);
if (arg != 0) {
va_error_message(callh, "%s takes only one argument.\n", name);
vpi_free_object(argv);
}
/* Get the function that is to be used by the calltf routine. */
@ -274,6 +275,7 @@ static PLI_INT32 va_double_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
arg = vpi_scan(argv);
if (arg != 0) {
va_error_message(callh, "%s takes only two arguments.\n", name);
vpi_free_object(argv);
}
/* Get the function that is to be used by the calltf routine. */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2010-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -20,243 +20,514 @@
# include "vpi_config.h"
# include "sv_vpi_user.h"
# include <stdlib.h>
# include <string.h>
# include <assert.h>
static void missing_arguments(vpiHandle sys)
{
vpi_printf("%s:%d: error: Invalid/missing arguments next/prev method\n",
vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo,sys));
vpi_control(vpiFinish, 1);
}
static PLI_INT32 ivl_method_next_prev_compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
/*
* The compiletf routine for the enumeration next() and prev() methods.
*/
static PLI_INT32 ivl_enum_method_next_prev_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle arg_enum, arg_item, arg_extra;
vpiHandle arg_enum, arg_var, arg_count;
/* These routines must have arguments. */
if (argv == 0) {
missing_arguments(sys);
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("No arguments given for enum method %s().\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* Check for the enumeration type argument. */
arg_enum = vpi_scan(argv);
if (arg_enum == 0) {
missing_arguments(sys);
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("No enumeration type argument given for enum "
"method %s().\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
arg_item = vpi_scan(argv);
if (arg_item == 0) {
missing_arguments(sys);
return 0;
}
/* Make sure there are no excess arguments */
arg_extra = vpi_scan(argv);
if (arg_extra != 0) {
missing_arguments(sys);
vpi_free_object(argv);
return 0;
}
/* The first argument must be an enum typespec */
if (vpi_get(vpiType, arg_enum) != vpiEnumTypespec) {
missing_arguments(sys);
return 0;
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("The first argument to enum method %s() must be an "
"enumeration type, found a %s.\n", name,
vpi_get_str(vpiType, arg_enum));
vpi_control(vpiFinish, 1);
}
/* The return value and input value must be the same size */
if (vpi_get(vpiSize,sys) != vpi_get(vpiSize,arg_item)) {
missing_arguments(sys);
/* Check for the enumeration variable. */
arg_var = vpi_scan(argv);
if (arg_var == 0) {
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("No enumeration variable argument given for enum "
"method %s().\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
switch(vpi_get(vpiType, arg_var)) {
case vpiBitVar:
case vpiByteVar:
case vpiIntegerVar:
case vpiIntVar:
case vpiLongIntVar:
case vpiReg:
case vpiShortIntVar:
break;
default:
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("The second argument to enum method %s() must be an "
"enumeration variable, found a %s.\n", name,
vpi_get_str(vpiType, arg_var));
vpi_control(vpiFinish, 1);
}
/* We can have an optional numeric count value. */
arg_count = vpi_scan(argv);
if (arg_count) {
switch(vpi_get(vpiType, arg_count)) {
case vpiBitVar:
case vpiByteVar:
case vpiIntegerVar:
case vpiIntVar:
case vpiLongIntVar:
case vpiMemoryWord:
case vpiNet:
case vpiPartSelect:
case vpiRealVar:
case vpiReg:
case vpiShortIntVar:
case vpiTimeVar:
break;
case vpiConstant:
case vpiParameter:
if (vpi_get(vpiConstType, arg_count) != vpiStringConst) break;
default:
vpi_printf("%s:%d: compiler error: ",
vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("The second argument to enum method %s() must be "
"numeric, found a %s.\n", name,
vpi_get_str(vpiType, arg_count));
vpi_control(vpiFinish, 1);
}
}
/* If we have a count argument then check to see if any extra
* arguments were given. */
if (arg_count && (vpi_scan(argv) != 0)) {
vpi_free_object(argv);
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("Extra argument(s) given to enum method %s().\n", name);
vpi_control(vpiFinish, 1);
}
/* The method return value and the enum variable must be the
* same size */
if (vpi_get(vpiSize, sys) != vpi_get(vpiSize, arg_var)) {
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("The enum method %s() return width (%d) must match "
"the enum variable width (%d).\n", name,
(int) vpi_get(vpiSize, sys),
(int) vpi_get(vpiSize, arg_var));
vpi_control(vpiFinish, 1);
}
return 0;
}
static int compare_value_eequal(s_vpi_value*ref1, s_vpi_value*ref2, long wid)
/*
* Compare it two values are equal to each other.
*/
static int compare_value_eequal(s_vpi_value*ref1, s_vpi_value*ref2,
PLI_INT32 wid)
{
/* Two integer values are easy. */
if (ref1->format == vpiIntVal && ref2->format == vpiIntVal)
return ref1->value.integer == ref2->value.integer;
/* For two vectors compare them word by word. */
if (ref1->format == vpiVectorVal && ref2->format == vpiVectorVal) {
int words = (wid-1)/32 + 1;
int idx;
PLI_INT32 words = (wid-1)/32 + 1;
PLI_INT32 idx;
for (idx = 0 ; idx < words ; idx += 1) {
if (ref1->value.vector[idx].aval != ref2->value.vector[idx].aval)
return 0;
if (ref1->value.vector[idx].bval != ref2->value.vector[idx].bval)
return 0;
if (ref1->value.vector[idx].aval !=
ref2->value.vector[idx].aval) return 0;
if (ref1->value.vector[idx].bval !=
ref2->value.vector[idx].bval) return 0;
}
return 1;
}
/* Swap the order so the code below can be used. */
if (ref1->format == vpiVectorVal && ref2->format == vpiIntVal) {
s_vpi_value*tmp = ref1;
ref1 = ref2;
ref2 = tmp;
}
/* Compare an integer to a vector. */
if (ref1->format == vpiIntVal && ref2->format == vpiVectorVal) {
int use_aval = ref1->value.integer;
int words = (wid-1)/32 + 1;
int idx;
PLI_INT32 aval = ref1->value.integer;
PLI_INT32 words = (wid-1)/32 + 1;
PLI_INT32 idx;
for (idx = 0 ; idx < words ; idx += 1) {
if (use_aval != ref2->value.vector[idx].aval)
return 0;
if (0 != ref2->value.vector[idx].bval)
return 0;
if (aval != ref2->value.vector[idx].aval) return 0;
if (ref2->value.vector[idx].bval) return 0;
use_aval = 0;
aval = 0;
}
return 1;
}
/* Unsupported types. */
vpi_printf("XXXX formats are: %d vs %d\n", ref1->format, ref2->format);
assert(0);
return 0;
}
static PLI_INT32 ivl_method_next_calltf(PLI_BYTE8*data)
/*
* If the current value is not found in the enumeration. Then we need to
* return X/0 for the next()/prev() value.
*/
static void fill_handle_with_init(vpiHandle arg, int is_two_state)
{
s_vpi_value val;
PLI_INT32 words = ((vpi_get(vpiSize, arg) - 1) / 32) + 1;
PLI_INT32 idx;
p_vpi_vecval val_ptr = (p_vpi_vecval) malloc(words*sizeof(s_vpi_vecval));
PLI_INT32 fill = (is_two_state) ? 0x0 : 0xffffffff;
assert(val_ptr);
/* Fill the vector with X. */
for (idx=0; idx < words; idx += 1) {
val_ptr[idx].aval = fill;
val_ptr[idx].bval = fill;
}
/* Put the vector to the argument. */
val.format = vpiVectorVal;
val.value.vector = val_ptr;
vpi_put_value(arg, &val, 0, vpiNoDelay);
free(val_ptr);
}
/*
* Implement the next()/prev() enumeration methods.
*/
static PLI_INT32 ivl_enum_method_next_prev_calltf(PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle arg_enum = vpi_scan(argv);
vpiHandle arg_item = vpi_scan(argv);
vpiHandle arg_extra = vpi_scan(argv);
vpiHandle arg_var = vpi_scan(argv);
vpiHandle arg_count = vpi_scan(argv);
vpiHandle enum_list = 0;
vpiHandle memb = 0, first_memb = 0;
long use_width = 0;
long item_width = vpi_get(vpiSize, arg_item);
vpiHandle enum_list;
vpiHandle cur;
PLI_INT32 var_width = vpi_get(vpiSize, arg_var);
PLI_UINT32 enum_size = vpi_get(vpiSize, arg_enum);
PLI_UINT32 count = 1;
PLI_UINT32 loc = 0;
s_vpi_value memb_value, item_value;
s_vpi_value cur_val, var_val;
assert(arg_extra == 0);
/* Get the count value if one was given. */
if (arg_count) {
s_vpi_value count_val;
item_value.format = vpiObjTypeVal;
vpi_get_value(arg_item, &item_value);
/* If this value is a vector value, then make a safe copy of
the vector so that other vpi functions don't trash it. */
if (item_value.format == vpiVectorVal) {
unsigned idx;
unsigned hwid = (item_width - 1)/32 + 1;
s_vpi_vecval*op = calloc(hwid, sizeof(s_vpi_vecval));
for (idx = 0 ; idx < hwid ; idx += 1) {
op[idx].aval = item_value.value.vector[idx].aval;
op[idx].bval = item_value.value.vector[idx].bval;
}
item_value.value.vector = op;
/* Get the count value. */
count_val.format = vpiIntVal;
vpi_get_value(arg_count, &count_val);
count = count_val.value.integer;
/* Remove any multiple loops around the enumeration. */
count %= enum_size;
/* Free the argument iterator. */
vpi_free_object(argv);
}
enum_list = vpi_iterate(vpiMember, arg_enum);
assert(enum_list);
/* Get the current value. */
var_val.format = vpiObjTypeVal;
vpi_get_value(arg_var, &var_val);
/* Search for the current value in the member list. */
do {
memb = vpi_scan(enum_list);
if (first_memb == 0) {
first_memb = memb;
use_width = vpi_get(vpiSize, first_memb);
assert(use_width == vpi_get(vpiSize, arg_item));
/* If the count is zero then just return the current value. */
if (count == 0) {
vpi_put_value(sys, &var_val, 0, vpiNoDelay);
return 0;
}
/* If the current value is a vector, then make a safe copy of
it so that other vpi_get_value() calls don't trash the value. */
if (var_val.format == vpiVectorVal) {
PLI_INT32 idx;
PLI_INT32 words = (var_width - 1)/32 + 1;
p_vpi_vecval nvec = malloc(words*sizeof(s_vpi_vecval));
for (idx = 0 ; idx < words ; idx += 1) {
nvec[idx].aval = var_val.value.vector[idx].aval;
nvec[idx].bval = var_val.value.vector[idx].bval;
}
if (memb == 0) break;
var_val.value.vector = nvec;
}
memb_value.format = vpiObjTypeVal;
vpi_get_value(memb, &memb_value);
/* Search for the current value in the enumeration list. */
enum_list = vpi_iterate(vpiEnumConst, arg_enum);
assert(enum_list);
do {
cur = vpi_scan(enum_list);
if (cur == 0) break;
} while (! compare_value_eequal(&item_value, &memb_value, use_width));
cur_val.format = vpiObjTypeVal;
vpi_get_value(cur, &cur_val);
assert(var_width == vpi_get(vpiSize, cur));
loc += 1;
} while (! compare_value_eequal(&cur_val, &var_val, var_width));
if (memb != 0)
memb = vpi_scan(enum_list);
/* If the variable is a vector then free the copy we created above. */
if (var_val.format == vpiVectorVal) free(var_val.value.vector);
if (memb != 0)
/* The current value was not found in the list so return X/0. */
if (cur == 0) {
/* This only works correctly since we don't really define the
* the correct base typespec. */
int is_two_state = vpi_get(vpiBaseTypespec, arg_enum) != vpiReg;
fill_handle_with_init(sys, is_two_state);
} else {
if (strcmp(name, "$ivl_enum_method$next") == 0) {
/* Check to see if we need to wrap to the beginning. */
if (loc + count > enum_size) {
/* Free the current iterator before creating a new
* one that is at the beginning of the list. */
vpi_free_object(enum_list);
enum_list = vpi_iterate(vpiEnumConst, arg_enum);
assert(enum_list);
count -= (enum_size - loc);
}
} else if (strcmp(name, "$ivl_enum_method$prev") == 0) {
/* Because of wrapping the count could be either before
* or after the current element. */
if (loc <= count ) {
/* The element we want is after the current
* element. */
count = enum_size - count;
} else {
/* The element we want is before the current
* element (at the beginning of the list). Free
* the current iterator before creating a new
* one that is at the beginning of the list. */
vpi_free_object(enum_list);
enum_list = vpi_iterate(vpiEnumConst, arg_enum);
assert(enum_list);
count = loc - count;
}
} else assert(0);
/* Find the correct element. */
while (count) {
cur = vpi_scan(enum_list);
count -= 1;
}
assert(cur != 0);
/* Free the iterator. */
vpi_free_object(enum_list);
if (memb == 0) {
memb = first_memb;
memb_value.format = vpiIntVal;
/* Get the value and return it. */
cur_val.format = vpiObjTypeVal;
vpi_get_value(cur, &cur_val);
vpi_put_value(sys, &cur_val, 0, vpiNoDelay);
}
/* Free any stached copy of the vector. */
if (item_value.format == vpiVectorVal)
free(item_value.value.vector);
vpi_get_value(memb, &memb_value);
vpi_put_value(sys, &memb_value, 0, vpiNoDelay);
return 0;
}
static PLI_INT32 ivl_method_prev_calltf(PLI_BYTE8*data)
/*
* The compiletf routine for the enumeration name() method.
*/
static PLI_INT32 ivl_enum_method_name_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle arg_enum, arg_var;
/* This routine must have arguments. */
if (argv == 0) {
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("No arguments given for enum method %s().\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
/* Check for the enumeration type argument. */
arg_enum = vpi_scan(argv);
if (arg_enum == 0) {
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("No enumeration type argument given for enum "
"method %s().\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
if (vpi_get(vpiType, arg_enum) != vpiEnumTypespec) {
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("The first argument to enum method %s() must be an "
"enumeration type, found a %s.\n", name,
vpi_get_str(vpiType, arg_enum));
vpi_control(vpiFinish, 1);
}
/* Check for the enumeration variable. */
arg_var = vpi_scan(argv);
if (arg_var == 0) {
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("No enumeration variable argument given for enum "
"method %s().\n", name);
vpi_control(vpiFinish, 1);
return 0;
}
switch(vpi_get(vpiType, arg_var)) {
case vpiBitVar:
case vpiByteVar:
case vpiIntegerVar:
case vpiIntVar:
case vpiLongIntVar:
case vpiReg:
case vpiShortIntVar:
break;
default:
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("The second argument to enum method %s() must be an "
"enumeration variable, found a %s.\n", name,
vpi_get_str(vpiType, arg_var));
vpi_control(vpiFinish, 1);
}
/* Only two arguments are supported. */
if (vpi_scan(argv) != 0) {
vpi_free_object(argv);
vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys),
(int) vpi_get(vpiLineNo,sys));
vpi_printf("Extra argument(s) given to enum method %s().\n", name);
vpi_control(vpiFinish, 1);
}
return 0;
}
/*
* Implement the name() enumeration method.
*/
static PLI_INT32 ivl_enum_method_name_calltf(PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle arg_enum = vpi_scan(argv);
vpiHandle arg_item = vpi_scan(argv);
vpiHandle arg_extra = vpi_scan(argv);
vpiHandle arg_var = vpi_scan(argv);
vpiHandle enum_list = 0;
vpiHandle memb = 0, prev = 0, last_memb = 0;
int use_wid = 0;
vpiHandle enum_list;
vpiHandle cur;
PLI_INT32 var_width = vpi_get(vpiSize, arg_var);
s_vpi_value memb_value, item_value;
s_vpi_value cur_val, var_val;
assert(arg_extra == 0);
/* Free the argument iterator. */
vpi_free_object(argv);
item_value.format = vpiIntVal;
vpi_get_value(arg_item, &item_value);
/* Get the current value. */
var_val.format = vpiObjTypeVal;
vpi_get_value(arg_var, &var_val);
enum_list = vpi_iterate(vpiMember, arg_enum);
assert(enum_list);
/* Search for the current value in the member list. */
do {
prev = memb;
memb = vpi_scan(enum_list);
if (memb == 0) break;
if (use_wid == 0)
use_wid = vpi_get(vpiSize, memb);
last_memb = memb;
memb_value.format = vpiIntVal;
vpi_get_value(memb, &memb_value);
} while (! compare_value_eequal(&memb_value, &item_value, use_wid));
while (memb) {
last_memb = memb;
memb = vpi_scan(enum_list);
/* If the current value is a vector, then make a safe copy of
it so that other vpi_get_value() calls don't trash the value. */
if (var_val.format == vpiVectorVal) {
PLI_INT32 idx;
PLI_INT32 words = (var_width - 1)/32 + 1;
p_vpi_vecval nvec = malloc(words*sizeof(s_vpi_vecval));
for (idx = 0 ; idx < words ; idx += 1) {
nvec[idx].aval = var_val.value.vector[idx].aval;
nvec[idx].bval = var_val.value.vector[idx].bval;
}
var_val.value.vector = nvec;
}
if (prev == 0)
prev = last_memb;
/* Search for the current value in the enumeration list. */
enum_list = vpi_iterate(vpiEnumConst, arg_enum);
assert(enum_list);
do {
cur = vpi_scan(enum_list);
if (cur == 0) break;
vpi_get_value(prev, &memb_value);
vpi_put_value(sys, &memb_value, 0, vpiNoDelay);
cur_val.format = vpiObjTypeVal;
vpi_get_value(cur, &cur_val);
assert(var_width == vpi_get(vpiSize, cur));
} while (! compare_value_eequal(&cur_val, &var_val, var_width));
/* If the variable is a vector then free the copy we created above. */
if (var_val.format == vpiVectorVal) free(var_val.value.vector);
/* The current value was not found in the list so return an empty
* string. */
cur_val.format = vpiStringVal;
if (cur == 0) {
cur_val.value.str = "";
} else {
cur_val.value.str = vpi_get_str(vpiName, cur);
/* Free the iterator. */
vpi_free_object(enum_list);
}
/* Return the appropriate string value. */
vpi_put_value(sys, &cur_val, 0, vpiNoDelay);
return 0;
}
void v2009_enum_register(void)
{
s_vpi_systf_data tf_data;
vpiHandle res;
tf_data.type = vpiSysFunc;
tf_data.calltf = ivl_method_next_calltf;
tf_data.compiletf = ivl_method_next_prev_compiletf;
tf_data.calltf = ivl_enum_method_name_calltf;
tf_data.compiletf = ivl_enum_method_name_compiletf;
tf_data.sizetf = 0;
tf_data.tfname = "$ivl_method$next";
tf_data.user_data = "$ivl_method$next";
vpi_register_systf(&tf_data);
tf_data.tfname = "$ivl_enum_method$name";
tf_data.user_data = "$ivl_enum_method$name";
res = vpi_register_systf(&tf_data);
/* This is not a user defined system function so hide it. */
vpip_make_systf_system_defined(res);
tf_data.type = vpiSysFunc;
tf_data.calltf = ivl_method_prev_calltf;
tf_data.compiletf = 0;
tf_data.calltf = ivl_enum_method_next_prev_calltf;
tf_data.compiletf = ivl_enum_method_next_prev_compiletf;
tf_data.sizetf = 0;
tf_data.tfname = "$ivl_method$prev";
tf_data.user_data = "$ivl_method$prev";
vpi_register_systf(&tf_data);
tf_data.tfname = "$ivl_enum_method$next";
tf_data.user_data = "$ivl_enum_method$next";
res = vpi_register_systf(&tf_data);
/* This is not a user defined system function so hide it. */
vpip_make_systf_system_defined(res);
tf_data.type = vpiSysFunc;
tf_data.calltf = ivl_enum_method_next_prev_calltf;
tf_data.compiletf = ivl_enum_method_next_prev_compiletf;
tf_data.sizetf = 0;
tf_data.tfname = "$ivl_enum_method$prev";
tf_data.user_data = "$ivl_enum_method$prev";
res = vpi_register_systf(&tf_data);
/* This is not a user defined system function so hide it. */
vpip_make_systf_system_defined(res);
}

View File

@ -2,7 +2,7 @@
* Verilog-A math library for Icarus Verilog
* http://www.icarus.com/eda/verilog/
*
* Copyright (C) 2007-2010 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2007-2011 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -218,6 +218,7 @@ static PLI_INT32 va_single_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
arg = vpi_scan(argv);
if (arg != 0) {
va_error_message(callh, "%s takes only one argument.\n", name);
vpi_free_object(argv);
}
/* Get the function that is to be used by the calltf routine. */
@ -301,6 +302,7 @@ static PLI_INT32 va_double_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
arg = vpi_scan(argv);
if (arg != 0) {
va_error_message(callh, "%s takes only two arguments.\n", name);
vpi_free_object(argv);
}
/* Get the function that is to be used by the calltf routine. */

View File

@ -214,8 +214,7 @@ static PLI_INT32 simparam_str_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name_ext)
char path [MAX_STRING_RESULT];
char *ptr = getcwd(path, MAX_STRING_RESULT);
if (ptr == NULL) {
ptr = strcpy(path, "<error getting the cwd, "
"is it too long?>");
strcpy(path, "<error getting the cwd, is it too long?>");
}
retval = strdup(path);
} else if (strcmp(param, "module") == 0) {

View File

@ -19,7 +19,8 @@
# include "vpi_config.h"
# include "vpi_user.h"
# include <cassert>
# include <assert.h>
# include "ivl_alloc.h"
/*
* The $ivlh_attribute_event implements the VHDL <varname>'event
@ -32,14 +33,28 @@ struct monitor_data {
struct t_vpi_time last_event;
};
/*
* All the following are called from C so define them for C linkage.
*/
extern "C" {
static struct monitor_data **mdata = 0;
static unsigned mdata_count = 0;
/* To keep valgrind happy free the allocated memory. */
static PLI_INT32 cleanup_mdata(p_cb_data cause)
{
unsigned idx;
(void) cause; /* Unused argument. */
for (idx= 0; idx < mdata_count; idx += 1) {
free(mdata[idx]);
}
free(mdata);
mdata = 0;
mdata_count = 0;
return 0;
}
static PLI_INT32 monitor_events(struct t_cb_data*cb)
{
struct monitor_data*mon = reinterpret_cast<monitor_data*> (cb->user_data);
struct monitor_data*mon = (struct monitor_data*)(cb->user_data);
assert(cb->time);
assert(cb->time->type == vpiSimTime);
@ -48,56 +63,71 @@ static PLI_INT32 monitor_events(struct t_cb_data*cb)
return 0;
}
static PLI_INT32 ivlh_attribute_event_compiletf(ICARUS_VPI_CONST PLI_BYTE8*)
static PLI_INT32 ivlh_attribute_event_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle arg;
struct monitor_data*mon;
struct t_cb_data cb;
struct t_vpi_time tb;
// Check that there is at least 1 argument...
/* Check that there are arguments. */
if (argv == 0) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
vpi_printf("Call to %s missing its argument\n", vpi_get_str(vpiName,sys));
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
(int)vpi_get(vpiLineNo, sys));
vpi_printf("(compiler error) %s requires a single argument.\n",
name);
vpi_control(vpiFinish, 1);
return 0;
}
/* Icarus either returns 0 above or has one argument. */
arg = vpi_scan(argv);
assert(arg);
struct monitor_data*monitor_handle = new struct monitor_data;
mon = malloc(sizeof(struct monitor_data));
/* Add this to the list of data. */
mdata_count += 1;
mdata = (struct monitor_data **) realloc(mdata,
sizeof(struct monitor_data **) *
mdata_count);
mdata[mdata_count-1] = mon;
struct t_cb_data cb;
struct t_vpi_time tb;
tb.type = vpiSimTime;
cb.reason = cbValueChange;
cb.cb_rtn = monitor_events;
cb.obj = arg;
cb.time = &tb;
cb.value = 0;
cb.user_data = reinterpret_cast<char*>(monitor_handle);
cb.user_data = (char*) (mon);
vpi_register_cb(&cb);
vpi_put_userdata(sys, monitor_handle);
vpi_put_userdata(sys, mon);
// check that there is no more then 1 argument
/* Check that there are no more then one argument. */
arg = vpi_scan(argv);
if (arg != 0) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
vpi_printf("Too many arguments for call to %s.\n", vpi_get_str(vpiName,sys));
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
(int)vpi_get(vpiLineNo, sys));
vpi_printf("(compiler error) %s only takes a single argument.\n",
name);
vpi_free_object(argv);
vpi_control(vpiFinish, 1);
}
return 0;
}
static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
struct t_vpi_value rval;
struct monitor_data*mon;
(void) name;
rval.format = vpiScalarVal;
struct monitor_data*mon = reinterpret_cast<monitor_data*>(vpi_get_userdata(sys));
mon = (struct monitor_data*) (vpi_get_userdata(sys));
if (mon->last_event.type == 0) {
rval.value.scalar = vpi0;
@ -105,7 +135,7 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
} else {
struct t_vpi_time tnow;
tnow.type = vpiSimTime;
vpi_get_time(0,&tnow);
vpi_get_time(0, &tnow);
rval.value.scalar = vpi1;
if (mon->last_event.high != tnow.high)
@ -119,14 +149,16 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
return 0;
}
static PLI_INT32 ivlh_attribute_event_sizetf(ICARUS_VPI_CONST PLI_BYTE8*)
static PLI_INT32 ivlh_attribute_event_sizetf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
(void) name;
return 1;
}
static void vhdl_register(void)
{
s_vpi_systf_data tf_data;
s_cb_data cb;
vpiHandle res;
tf_data.type = vpiSysFunc;
@ -138,11 +170,19 @@ static void vhdl_register(void)
tf_data.user_data = (PLI_BYTE8 *) "$ivlh_attribute_event";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
/* Create a callback to clear the monitor data memory when the
* simulator finishes. */
cb.time = NULL;
cb.reason = cbEndOfSimulation;
cb.cb_rtn = cleanup_mdata;
cb.user_data = NULL;
cb.obj = NULL;
vpi_register_cb(&cb);
}
void (*vlog_startup_routines[])() = {
vhdl_register,
0
};
} /* extern "C" */

View File

@ -27,24 +27,3 @@
#define wave_alloca alloca
#endif
/*
* $Id: wavealloca.h,v 1.3 2009/12/06 00:10:17 gtkwave Exp $
* $Log: wavealloca.h,v $
* Revision 1.3 2009/12/06 00:10:17 gtkwave
* mingw compatibility fix from icarus
*
* Revision 1.2 2007/08/26 21:35:50 gtkwave
* integrated global context management from SystemOfCode2007 branch
*
* Revision 1.1.1.1.2.1 2007/08/06 03:50:50 gtkwave
* globals support for ae2, gtk1, cygwin, mingw. also cleaned up some machine
* generated structs, etc.
*
* Revision 1.1.1.1 2007/05/30 04:27:29 gtkwave
* Imported sources
*
* Revision 1.2 2007/04/20 02:08:18 gtkwave
* initial release
*
*/

View File

@ -288,6 +288,7 @@ typedef struct t_vpi_delay {
#define vpiSysTaskCall 57
#define vpiTask 59
#define vpiTimeVar 63
#define vpiUdpDefn 66
#define vpiUserSystf 67
#define vpiNetArray 114
#define vpiIndex 78
@ -362,7 +363,7 @@ typedef struct t_vpi_delay {
# define vpiSysFuncReal vpiRealFunc
# define vpiSysFuncTime vpiTimeFunc
# define vpiSysFuncSized vpiSizedFunc
#define vpiUserDefn 49
#define vpiUserDefn 45
#define vpiAutomatic 50
#define vpiConstantSelect 53
#define vpiSigned 65

View File

@ -101,6 +101,12 @@ void codespace_delete(void)
{
vvp_code_t cur = first_chunk;
/* If there are no opcodes then just delete the code space. */
if (count_opcodes == 0) {
delete [] cur;
return;
}
do {
vvp_code_t next = cur[code_chunk_size-1].cptr;
for (unsigned idx = 0 ; idx < code_chunk_size; idx += 1) {

View File

@ -1512,7 +1512,6 @@ void compile_udp_def(int sequ, char *label, char *name,
u->compile_table(table);
}
free(label);
delete[] name;
}
char **compile_udp_table(char **table, char *row)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005-2010 Stephen Williams <steve@icarus.com>
* Copyright (c) 2005-2011 Stephen Williams <steve@icarus.com>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -771,6 +771,11 @@ static vpiHandle modpath_src_get_handle(int code, vpiHandle ref)
return vpi_handle(scope);
}
// Handles to path term objects should really be obtained via
// the vpi_iterate and vpi_scan functions. Continue to allow
// them to be obtained here for backwards compatibility with
// older versions of Icarus Verilog.
case vpiModPathIn:
return vpi_handle(&rfp->path_term_in);
@ -780,6 +785,30 @@ static vpiHandle modpath_src_get_handle(int code, vpiHandle ref)
return 0;
}
static vpiHandle modpath_src_iterate(int code, vpiHandle ref)
{
struct __vpiModPathSrc*rfp = vpip_modpath_src_from_handle(ref);
assert(rfp);
// Module paths with multiple sources or destinations are
// currently represented by a separate modpath object for
// each source/destination combination, so there is only
// ever one input path term and one output path term.
switch (code) {
case vpiModPathIn: {
vpiHandle*args = (vpiHandle*)calloc(1, sizeof(vpiHandle*));
args[0] = vpi_handle(&rfp->path_term_in);
return vpip_make_iterator(1, args, true);
}
case vpiModPathOut: {
vpiHandle*args = (vpiHandle*)calloc(1, sizeof(vpiHandle*));
args[0] = vpi_handle(&rfp->dest->path_term_out);
return vpip_make_iterator(1, args, true);
}
}
return 0;
}
static vpiHandle modpath_src_index ( vpiHandle ref, int)
{
assert(ref->vpi_type->type_code == vpiModPathIn);
@ -946,7 +975,7 @@ static const struct __vpirt vpip_modpath_src_rt = {
modpath_src_get_value,
modpath_src_put_value,
modpath_src_get_handle,
0, /* modpath_src_iterate,*/
modpath_src_iterate,
modpath_src_index,
modpath_src_free_object,
modpath_src_get_delays,

View File

@ -19,6 +19,9 @@
# include "compile.h"
# include "enum_type.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <iostream>
# include <cassert>
@ -40,6 +43,7 @@ static struct enumconst_s* enumconst_from_handle(vpiHandle obj)
struct __vpiEnumTypespec {
struct __vpiHandle base;
std::vector<enumconst_s> names;
int base_type_code;
bool is_signed;
};
@ -60,6 +64,13 @@ static int enum_type_get(int code, vpiHandle obj)
case vpiSize:
return ref->names.size();
/* This is not currently set correctly. We always use vpiReg for
* four state variables and vpiBitVar for two state variables.
* This minimal functionality is needed to get the next() and
* prev() methods to work correctly with invalid values. */
case vpiBaseTypespec:
return ref->base_type_code;
case vpiSigned:
return ref->is_signed;
@ -76,7 +87,7 @@ static vpiHandle enum_type_iterate(int code, vpiHandle obj)
struct __vpiEnumTypespec*ref = vpip_enum_typespec_from_handle(obj);
assert(ref);
if (code == vpiMember) {
if (code == vpiEnumConst) {
vpiHandle*args = (vpiHandle*)
calloc(ref->names.size(), sizeof(vpiHandle*));
for (size_t idx = 0 ; idx < ref->names.size() ; idx += 1)
@ -160,6 +171,7 @@ void compile_enum2_type(char*label, long width, bool signed_flag,
spec->base.vpi_type = &enum_type_rt;
spec->names = std::vector<enumconst_s> (names->size());
spec->is_signed = signed_flag;
spec->base_type_code = vpiBitVar;
size_t idx = 0;
for (list<struct enum_name_s>::iterator cur = names->begin()
@ -172,6 +184,7 @@ void compile_enum2_type(char*label, long width, bool signed_flag,
assert(idx == spec->names.size());
compile_vpi_symbol(label, vpi_handle(spec));
vpip_attach_to_current_scope(vpi_handle(spec));
free(label);
delete names;
@ -184,6 +197,7 @@ void compile_enum4_type(char*label, long width, bool signed_flag,
spec->base.vpi_type = &enum_type_rt;
spec->names = std::vector<enumconst_s> (names->size());
spec->is_signed = signed_flag;
spec->base_type_code = vpiReg;
size_t idx = 0;
for (list<struct enum_name_s>::iterator cur = names->begin()
@ -198,7 +212,22 @@ void compile_enum4_type(char*label, long width, bool signed_flag,
assert(idx == spec->names.size());
compile_vpi_symbol(label, vpi_handle(spec));
vpip_attach_to_current_scope(vpi_handle(spec));
free(label);
delete names;
}
#ifdef CHECK_WITH_VALGRIND
void enum_delete(vpiHandle item)
{
struct __vpiEnumTypespec*obj = (struct __vpiEnumTypespec*) item;
for (vector<enumconst_s>::iterator iter = obj->names.begin();
iter != obj->names.end(); ++ iter ) {
delete [] iter->name;
}
delete obj;
}
#endif

View File

@ -82,8 +82,9 @@ ostream& operator <<(ostream&o, const struct udp_levels_table&table)
return o;
}
vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init, bool type)
: ports_(ports), init_(init), seq_(type)
vvp_udp_s::vvp_udp_s(char*label, char*name__, unsigned ports,
vvp_bit4_t init, bool type)
: name_(name__), ports_(ports), init_(init), seq_(type)
{
if (!udp_table)
udp_table = new_symbol_table();
@ -104,6 +105,7 @@ vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init, bool type)
vvp_udp_s::~vvp_udp_s()
{
delete[] name_;
}
unsigned vvp_udp_s::port_count() const
@ -116,10 +118,9 @@ vvp_bit4_t vvp_udp_s::get_init() const
return init_;
}
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name, unsigned ports)
: vvp_udp_s(label, ports, BIT4_X, false)
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name__, unsigned ports)
: vvp_udp_s(label, name__, ports, BIT4_X, false)
{
name_ = name;
levels0_ = 0;
levels1_ = 0;
nlevels0_ = 0;
@ -295,11 +296,10 @@ void vvp_udp_comb_s::compile_table(char**tab)
assert(nrows1 == nlevels1_);
}
vvp_udp_seq_s::vvp_udp_seq_s(char*label, char*name,
vvp_udp_seq_s::vvp_udp_seq_s(char*label, char*name__,
unsigned ports, vvp_bit4_t init)
: vvp_udp_s(label, ports, init, true)
: vvp_udp_s(label, name__, ports, init, true)
{
name_ = name;
levels0_ = 0;
levels1_ = 0;
levelsx_ = 0;

View File

@ -1,7 +1,7 @@
#ifndef __udp_H
#define __udp_H
/*
* Copyright (c) 2005-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2011 Stephen Williams (steve@icarus.com)
*
* (This is a rewrite of code that was ...
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>)
@ -30,15 +30,16 @@ struct udp_levels_table;
struct vvp_udp_s {
public:
explicit vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init,
bool type);
explicit vvp_udp_s(char*label, char*name, unsigned ports,
vvp_bit4_t init, bool type);
virtual ~vvp_udp_s();
// Return the number of input ports for the defined UDP. This
// does *not* include the current output value for a
// sequential UDP.
unsigned port_count() const;
bool is_sequential() const {return seq_;};
bool is_sequential() const { return seq_; };
char *name() { return name_; }
// Return the initial output value.
vvp_bit4_t get_init() const;
@ -48,6 +49,7 @@ struct vvp_udp_s {
vvp_bit4_t cur_out) =0;
private:
char *name_;
unsigned ports_;
vvp_bit4_t init_;
bool seq_;
@ -112,7 +114,7 @@ extern ostream& operator<< (ostream&o, const struct udp_levels_table&t);
class vvp_udp_comb_s : public vvp_udp_s {
public:
vvp_udp_comb_s(char*label, char*name, unsigned ports);
vvp_udp_comb_s(char*label, char*name__, unsigned ports);
~vvp_udp_comb_s();
void compile_table(char**tab);
@ -125,8 +127,6 @@ class vvp_udp_comb_s : public vvp_udp_s {
vvp_bit4_t cur_out);
private:
char*name_;
// Level sensitive rows of the device.
struct udp_levels_table*levels0_;
struct udp_levels_table*levels1_;
@ -180,7 +180,7 @@ struct udp_edges_table {
class vvp_udp_seq_s : public vvp_udp_s {
public:
vvp_udp_seq_s(char*label, char*name, unsigned ports, vvp_bit4_t init);
vvp_udp_seq_s(char*label, char*name__, unsigned ports, vvp_bit4_t init);
~vvp_udp_seq_s();
void compile_table(char**tab);
@ -190,8 +190,6 @@ class vvp_udp_seq_s : public vvp_udp_s {
vvp_bit4_t cur_out);
private:
char*name_;
vvp_bit4_t test_levels_(const udp_levels_table&cur);
// Level sensitive rows of the device.

View File

@ -262,6 +262,8 @@ static const char* vpi_type_values(PLI_INT32 code)
return "vpiByteVar";
case vpiConstant:
return "vpiConstant";
case vpiEnumTypespec:
return "vpiEnumTypespec";
case vpiFunction:
return "vpiFunction";
case vpiIntVar:
@ -473,7 +475,7 @@ int vpip_time_precision_from_handle(vpiHandle obj)
void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
{
int units;
int scale;
vvp_time64_t time;
assert(vp);
@ -487,9 +489,10 @@ void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
break;
case vpiScaledRealTime:
units = vpip_time_units_from_handle(obj);
vp->real = pow(10.0L, vpip_get_time_precision() - units);
vp->real *= time;
scale = vpip_get_time_precision() -
vpip_time_units_from_handle(obj);
if (scale >= 0) vp->real = (double)time * pow(10.0, scale);
else vp->real = (double)time / pow(10.0, -scale);
break;
default:
@ -951,6 +954,7 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
vvp_time64_t dly;
int scale;
if (vpi_get(vpiAutomatic, obj)) {
fprintf(stderr, "vpi error: cannot put a value with "
@ -964,10 +968,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
switch (when->type) {
case vpiScaledRealTime:
dly = (vvp_time64_t)(when->real *
(pow(10.0L,
vpip_time_units_from_handle(obj) -
vpip_get_time_precision())));
scale = vpip_time_units_from_handle(obj) -
vpip_get_time_precision();
if (scale >= 0) {
dly = (vvp_time64_t)(when->real * pow(10.0, scale));
} else {
dly = (vvp_time64_t)(when->real / pow(10.0, -scale));
}
break;
case vpiSimTime:
dly = vpip_timestruct_to_time(when);
@ -1047,6 +1054,13 @@ vpiHandle vpi_handle(PLI_INT32 type, vpiHandle ref)
return res;
}
static vpiHandle vpip_make_udp_iterator()
{
// HERE: Add support for iterating over UDP definitions.
// See 26.6.16 (page 400 in 1364-2005).
return 0;
}
/*
* This function asks the object to return an iterator for
* the specified reference. It is up to the iterate_ method to
@ -1058,6 +1072,9 @@ static vpiHandle vpi_iterate_global(int type)
case vpiModule:
return vpip_make_root_iterator();
case vpiUdpDefn:
return vpip_make_udp_iterator();
case vpiUserSystf:
return vpip_make_systf_iterator();
}

View File

@ -90,6 +90,9 @@ static void delete_sub_scopes(struct __vpiScope *scope)
case vpiRealVar:
real_delete((scope->intern)[idx]);
break;
case vpiEnumTypespec:
enum_delete((scope->intern)[idx]);
break;
default:
fprintf(stderr, "Need support for type: %d\n",
scope->intern[idx]->vpi_type->type_code);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -55,14 +55,12 @@ vvp_time64_t vpip_timestruct_to_time(const struct t_vpi_time*ts)
double vpip_time_to_scaled_real(vvp_time64_t ti, struct __vpiScope*scope)
{
int units;
if (scope)
units = scope->time_units;
else
units = vpi_time_precision;
double val;
int scale = 0;
if (scope) scale = vpi_time_precision - scope->time_units;
double val = pow(10.0L, vpi_time_precision - units);
val *= ti;
if (scale >= 0) val = (double)ti * pow(10.0, scale);
else val = (double)ti / pow(10.0, -scale);
return val;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2010 Stephen Williams <steve@icarus.com>
* Copyright (c) 2008-2011 Stephen Williams <steve@icarus.com>
* Copyright (c) 2002 Larry Doolittle (larry@doolittle.boa.org)
*
* This source code is free software; you can redistribute it
@ -121,7 +121,7 @@ unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
char *buf, unsigned int nbuf,
int signed_flag)
{
unsigned int idx, len, vlen;
unsigned int idx, vlen;
unsigned int mbits=vec4.size(); /* number of non-sign bits */
unsigned count_x = 0, count_z = 0;
@ -186,19 +186,15 @@ unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
}
if (count_x == vec4.size()) {
len = 1;
buf[0] = 'x';
buf[1] = 0;
} else if (count_x > 0) {
len = 1;
buf[0] = 'X';
buf[1] = 0;
} else if (count_z == vec4.size()) {
len = 1;
buf[0] = 'z';
buf[1] = 0;
} else if (count_z > 0) {
len = 1;
buf[0] = 'Z';
buf[1] = 0;
} else {

View File

@ -1,7 +1,7 @@
#ifndef __vvp_cleanup_H
#define __vvp_cleanup_H
/*
* Copyright (c) 2009 Cary R. (cygcary@yahoo.com)
* Copyright (c) 2009-2011 Cary R. (cygcary@yahoo.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -43,6 +43,7 @@ extern void A_delete(struct __vpiHandle *item);
extern void PV_delete(struct __vpiHandle *item);
extern void constant_delete(struct __vpiHandle *item);
extern void contexts_delete(struct __vpiScope *scope);
extern void enum_delete(struct __vpiHandle *item);
extern void memory_delete(struct __vpiHandle *item);
extern void named_event_delete(struct __vpiHandle *item);
extern void parameter_delete(struct __vpiHandle *item);

View File

@ -34,6 +34,7 @@
# include <valgrind/memcheck.h>
# include <map>
# include "sfunc.h"
# include "udp.h"
# include "ivl_alloc.h"
#endif
@ -85,6 +86,7 @@ void* vvp_net_t::operator new (size_t size)
#ifdef CHECK_WITH_VALGRIND
static map<vvp_net_t*, bool> vvp_net_map;
static map<sfunc_core*, bool> sfunc_map;
static map<vvp_udp_fun_core*, bool> udp_map;
static vvp_net_t **local_net_pool = 0;
static unsigned local_net_pool_count = 0;
@ -102,6 +104,9 @@ void vvp_net_delete(vvp_net_t *item)
if (sfunc_core*tmp = dynamic_cast<sfunc_core*> (item->fun)) {
sfunc_map[tmp] = true;
}
if (vvp_udp_fun_core*tmp = dynamic_cast<vvp_udp_fun_core*> (item->fun)) {
udp_map[tmp] = true;
}
}
void vvp_net_pool_delete()
@ -128,6 +133,12 @@ void vvp_net_pool_delete()
}
sfunc_map.clear();
map<vvp_udp_fun_core*, bool>::iterator uiter;
for (uiter = udp_map.begin(); uiter != udp_map.end(); ++ uiter ) {
delete uiter->first;
}
udp_map.clear();
if (RUNNING_ON_VALGRIND && (vvp_nets_del != count_vvp_nets)) {
fflush(NULL);
VALGRIND_PRINTF("Error: vvp missed deleting %ld of %lu net(s).",