Merge branch 'master' into work5

Conflicts:
	vhdlpp/architec.h
	vhdlpp/debug.cc
This commit is contained in:
Stephen Williams 2011-04-13 19:09:51 -07:00
commit e017ccb5d2
39 changed files with 2026 additions and 392 deletions

63
PExpr.h
View File

@ -45,6 +45,11 @@ class PExpr : public LineInfo {
public:
enum width_mode_t { SIZED, EXPAND, LOSSLESS, UNSIZED };
// Flag values that can be passed to elaborate_expr.
static const unsigned NO_FLAGS = 0x0;
static const unsigned NEED_CONST = 0x1;
static const unsigned SYS_TASK_ARG = 0x2;
PExpr();
virtual ~PExpr();
@ -122,7 +127,7 @@ class PExpr : public LineInfo {
// be incomplete.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
@ -195,7 +200,7 @@ class PEConcat : public PExpr {
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
@ -261,7 +266,7 @@ class PEFNumber : public PExpr {
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
virtual void dump(ostream&) const;
@ -301,7 +306,7 @@ class PEIdent : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
// Elaborate the PEIdent as a port to a module. This method
// only applies to Ident expressions.
@ -330,7 +335,7 @@ class PEIdent : public PExpr {
// invalid bits (xz) in either expression, then the defined
// flag is set to *false*.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb, bool&defined) const;
NetExpr* calculate_up_do_base_(Design*, NetScope*) const;
NetExpr* calculate_up_do_base_(Design*, NetScope*, bool need_const) const;
bool calculate_param_range_(Design*, NetScope*,
const NetExpr*msb_ex, long&msb,
const NetExpr*lsb_ex, long&lsb,
@ -352,7 +357,8 @@ class PEIdent : public PExpr {
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb,
unsigned expr_wid) const;
unsigned expr_wid,
unsigned flags) const;
NetExpr*elaborate_expr_param_part_(Design*des,
NetScope*scope,
const NetExpr*par,
@ -365,25 +371,27 @@ class PEIdent : public PExpr {
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
const NetExpr*par_lsb,
bool need_const) const;
NetExpr*elaborate_expr_param_idx_do_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
const NetExpr*par_lsb,
bool need_const) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
NetExpr*elaborate_expr_net_word_(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
NetExpr*elaborate_expr_net_part_(Design*des,
NetScope*scope,
NetESignal*net,
@ -392,15 +400,18 @@ class PEIdent : public PExpr {
NetExpr*elaborate_expr_net_idx_up_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetScope*found,
bool need_const) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
@ -423,7 +434,7 @@ class PENumber : public PExpr {
width_mode_t&mode);
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, bool) const;
unsigned expr_wid, unsigned) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
@ -456,7 +467,7 @@ class PEString : public PExpr {
width_mode_t&mode);
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, bool) const;
unsigned expr_wid, unsigned) const;
verinum* eval_const(Design*, NetScope*) const;
private:
@ -480,7 +491,7 @@ class PEUnary : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
private:
@ -508,7 +519,7 @@ class PEBinary : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
protected:
@ -546,7 +557,7 @@ class PEBComp : public PEBinary {
width_mode_t&mode);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool sys_task_arg) const;
unsigned expr_wid, unsigned flags) const;
private:
unsigned l_width_;
@ -566,7 +577,7 @@ class PEBLogic : public PEBinary {
width_mode_t&mode);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool sys_task_arg) const;
unsigned expr_wid, unsigned flags) const;
};
/*
@ -589,7 +600,7 @@ class PEBLeftWidth : public PEBinary {
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
};
class PEBPower : public PEBLeftWidth {
@ -633,12 +644,13 @@ class PETernary : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
private:
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
PExpr*expr, unsigned expr_wid) const;
PExpr*expr, unsigned expr_wid,
unsigned flags) const;
private:
PExpr*expr_;
@ -672,7 +684,7 @@ class PECallFunction : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
@ -686,7 +698,8 @@ class PECallFunction : public PExpr {
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
unsigned expr_wid) const;
unsigned expr_wid,
unsigned flags) const;
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t,
unsigned expr_wid) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
@ -705,7 +718,7 @@ class PEVoid : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
bool sys_task_arg) const;
unsigned flags) const;
};
#endif

View File

@ -1,7 +1,7 @@
#ifndef __PGate_H
#define __PGate_H
/*
* Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -238,6 +238,9 @@ class PGModule : public PGate {
friend class delayed_elaborate_scope_mod_instances;
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
unsigned calculate_instance_count_(Design*, NetScope*,
long&high, long&low,
perm_string name) const;
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const;
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;

View File

@ -42,6 +42,7 @@
# undef HAVE_LIBREADLINE
# undef HAVE_LIBZ
# undef HAVE_LIBBZ2
# undef HAVE_LROUND
# undef HAVE_SYS_WAIT_H
# undef WORDS_BIGENDIAN

View File

@ -38,6 +38,8 @@ CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
YACC = @YACC@
MAN = @MAN@
PS2PDF = @PS2PDF@
@ -78,10 +80,10 @@ iverilog@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o iverilog@EXEEXT@ @EXTRALIBS@
cflexor.c: cflexor.lex
flex -s -Pcf -ocflexor.c $(srcdir)/cflexor.lex
$(LEX) -s -Pcf -ocflexor.c $(srcdir)/cflexor.lex
cfparse.h cfparse.c: cfparse.y
bison --verbose -t -d -o cfparse.c --name-prefix=cf $(srcdir)/cfparse.y
$(YACC) --verbose -t -d -o cfparse.c --name-prefix=cf $(srcdir)/cfparse.y
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o

View File

@ -239,7 +239,8 @@ NetEUFunc* NetEUFunc::dup_expr() const
tmp_parms[idx] = parms_[idx]->dup_expr();
}
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms);
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms,
need_const_);
ivl_assert(*this, tmp);
tmp->set_line(*this);

View File

@ -82,7 +82,7 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t lv_type, unsigned lv_width,
PExpr*expr)
PExpr*expr, bool need_const)
{
int context_wid = -1;
switch (lv_type) {
@ -99,7 +99,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
break;
}
return elab_and_eval(des, scope, expr, context_wid);
return elab_and_eval(des, scope, expr, context_wid, need_const);
}
/*
@ -127,7 +127,7 @@ unsigned PExpr::test_width(Design*des, NetScope*, width_mode_t&)
return 1;
}
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, bool) const
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
{
cerr << get_fileline() << ": internal error: I do not know how to"
<< " elaborate this expression. " << endl;
@ -224,8 +224,10 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
* types.
*/
NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned flags) const
{
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
ivl_assert(*this, left_);
ivl_assert(*this, right_);
@ -249,8 +251,8 @@ NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
left_->cast_signed(signed_flag_);
}
NetExpr*lp = left_->elaborate_expr(des, scope, l_width, false);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
NetExpr*lp = left_->elaborate_expr(des, scope, l_width, flags);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
@ -505,8 +507,10 @@ unsigned PEBComp::test_width(Design*des, NetScope*scope, width_mode_t&)
}
NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned flags) const
{
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
ivl_assert(*this, left_);
ivl_assert(*this, right_);
@ -517,8 +521,8 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
if (type_is_vectorable(right_->expr_type()) && !right_->has_sign())
left_->cast_signed(false);
NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, false);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, false);
NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, flags);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, flags);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
@ -569,13 +573,14 @@ unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
}
NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned flags) const
{
ivl_assert(*this, left_);
ivl_assert(*this, right_);
NetExpr*lp = elab_and_eval(des, scope, left_, -1);
NetExpr*rp = elab_and_eval(des, scope, right_, -1);
bool need_const = NEED_CONST & flags;
NetExpr*lp = elab_and_eval(des, scope, left_, -1, need_const);
NetExpr*rp = elab_and_eval(des, scope, right_, -1, need_const);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
@ -620,13 +625,13 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
long r_val = LONG_MAX;
if (r_width < sizeof(long)*8) {
r_val = (1L << r_width) - 1L;
if (right_->has_sign())
if ((op_ == 'p') && right_->has_sign())
r_val >>= 1;
}
// If the right operand is constant, we can use the
// actual value.
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, NO_FLAGS);
if (rp) {
eval_expr(rp, r_width);
} else {
@ -707,8 +712,10 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
}
NetExpr*PEBLeftWidth::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned flags) const
{
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
ivl_assert(*this, left_);
// The left operand is always context determined, so propagate
@ -717,8 +724,8 @@ NetExpr*PEBLeftWidth::elaborate_expr(Design*des, NetScope*scope,
unsigned r_width = right_->expr_width();
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, false);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, flags);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
if (lp == 0 || rp == 0) {
delete lp;
delete rp;
@ -1074,7 +1081,8 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
* known function names.
*/
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
unsigned expr_wid) const
unsigned expr_wid,
unsigned flags) const
{
perm_string name = peek_tail_name(path_);
@ -1090,7 +1098,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
}
PExpr*expr = parms_[0];
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, true);
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
return cast_to_width_(sub, expr_wid);
}
@ -1162,13 +1170,21 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
expression as much as possible, and use the reduced
expression if one is created. */
bool need_const = NEED_CONST & flags;
unsigned parm_errors = 0;
unsigned missing_parms = 0;
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
PExpr*expr = parms_[idx];
if (expr) {
NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx, expr);
fun->parm(idx, tmp);
NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx,
expr, need_const);
if (tmp) {
fun->parm(idx, tmp);
} else {
parm_errors += 1;
fun->parm(idx, 0);
}
} else {
missing_parms += 1;
fun->parm(idx, 0);
@ -1183,6 +1199,9 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
des->errors += 1;
}
if (missing_parms || parm_errors)
return 0;
NetExpr*tmp = pad_to_width(fun, expr_wid, *this);
tmp->cast_signed(signed_flag_);
@ -1250,10 +1269,12 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
}
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned flags) const
{
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
if (peek_tail_name(path_)[0] == '$')
return elaborate_sfunc_(des, scope, expr_wid);
return elaborate_sfunc_(des, scope, expr_wid, flags);
NetFuncDef*def = des->find_function(scope, path_);
if (def == 0) {
@ -1265,16 +1286,9 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return elaborate_access_func_(des, scope, access_nature,
expr_wid);
// We do not currently support constant user function and
// this is where things fail because of that, though we
// don't know for sure so we need to display both messages.
if (need_constant_expr || is_param_expr) {
cerr << get_fileline() << ": sorry: constant user "
"functions are not currently supported: "
<< path_ << "()." << endl << " or" << endl;
}
cerr << get_fileline() << ": error: No function " << path_
<< " in this context (" << scope_path(scope) << ")." << endl;
cerr << get_fileline() << ": error: No function named `" << path_
<< "' found in this context (" << scope_path(scope) << ")."
<< endl;
des->errors += 1;
return 0;
}
@ -1283,6 +1297,29 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
NetScope*dscope = def->scope();
ivl_assert(*this, dscope);
bool need_const = NEED_CONST & flags;
// It is possible to get here before the called function has been
// fully elaborated. If this is the case, elaborate it now. This
// ensures we know whether or not it is a constant function.
if (dscope->elab_stage() < 3) {
dscope->need_const_func(need_const);
const PFunction*pfunc = dscope->func_pform();
ivl_assert(*this, pfunc);
pfunc->elaborate(des, dscope);
}
if (dscope->parent() != scope->parent() || !dscope->is_const_func()) {
if (scope->need_const_func()) {
cerr << get_fileline() << ": error: A function invoked by "
"a constant function must be a constant function "
"local to the current module." << endl;
des->errors += 1;
return 0;
}
scope->is_const_func(false);
}
if (! check_call_matches_definition_(des, dscope))
return 0;
@ -1297,6 +1334,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
of the function being called. The scope of the called
function is elaborated when the definition is elaborated. */
unsigned parm_errors = 0;
unsigned missing_parms = 0;
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
PExpr*tmp = parms_[idx];
@ -1304,7 +1342,11 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
parms[idx] = elaborate_rval_expr(des, scope,
def->port(idx)->data_type(),
(unsigned)def->port(idx)->vector_width(),
tmp);
tmp, need_const);
if (parms[idx] == 0) {
parm_errors += 1;
continue;
}
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[idx])) {
cerr << evt->get_fileline() << ": error: An event '"
<< evt->event()->name() << "' can not be a user "
@ -1332,6 +1374,28 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
des->errors += 1;
}
if (need_const && !dscope->is_const_func()) {
// If this is the first time the function has been called in
// a constant context, force the function to be re-elaborated.
// This will generate the necessary error messages to allow
// the user to diagnose the fault.
if (!dscope->need_const_func()) {
dscope->set_elab_stage(2);
dscope->need_const_func(true);
const PFunction*pfunc = dscope->func_pform();
ivl_assert(*this, pfunc);
pfunc->elaborate(des, dscope);
}
cerr << get_fileline() << ": error: `" << dscope->basename()
<< "' is not a constant function." << endl;
des->errors += 1;
return 0;
}
if (missing_parms || parm_errors)
return 0;
/* Look for the return value signal for the called
function. This return value is a magic signal in the scope
@ -1343,7 +1407,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
if (NetNet*res = dscope->find_signal(dscope->basename())) {
NetESignal*eres = new NetESignal(res);
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms);
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
func->set_line(*this);
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
@ -1372,9 +1436,7 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
/* If there is a repeat expression, then evaluate the constant
value and set the repeat count. */
if (repeat_ && (scope != tested_scope_)) {
need_constant_expr = true;
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1);
need_constant_expr = false;
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1, true);
if (tmp == 0) return 0;
if (tmp->expr_type() == IVL_VT_REAL) {
@ -1426,8 +1488,10 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
static int concat_depth = 0;
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned flags) const
{
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
concat_depth += 1;
if (debug_elaborate) {
@ -1459,7 +1523,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
assert(parms_[idx]);
unsigned wid = parms_[idx]->expr_width();
NetExpr*ex = parms_[idx]->elaborate_expr(des, scope, wid, false);
NetExpr*ex = parms_[idx]->elaborate_expr(des, scope, wid, flags);
if (ex == 0) continue;
ex->set_line(*parms_[idx]);
@ -1542,7 +1606,7 @@ unsigned PEFNumber::test_width(Design*, NetScope*, width_mode_t&)
return expr_width_;
}
NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, bool) const
NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
{
NetECReal*tmp = new NetECReal(*value_);
tmp->set_line(*this);
@ -1569,9 +1633,7 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
two bit select expressions, and both must be
constant. Evaluate them and pass the results back to
the caller. */
need_constant_expr = true;
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
need_constant_expr = false;
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
if (lsb_c == 0) {
cerr << index_tail.lsb->get_fileline() << ": error: "
@ -1589,9 +1651,7 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
lsb = lsb_c->value().as_long();
}
need_constant_expr = true;
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1);
need_constant_expr = false;
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
if (msb_c == 0) {
cerr << index_tail.msb->get_fileline() << ": error: "
@ -1628,9 +1688,7 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
/* Calculate the width expression (in the lsb_ position)
first. If the expression is not constant, error but guess 1
so we can keep going and find more errors. */
need_constant_expr = true;
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
need_constant_expr = false;
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
if (wid_c == 0) {
@ -1651,7 +1709,8 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
* When we know that this is an indexed part select (up or down) this
* method calculates the up/down base, as far at it can be calculated.
*/
NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope,
bool need_const) const
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
@ -1660,7 +1719,7 @@ NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
ivl_assert(*this, index_tail.lsb != 0);
ivl_assert(*this, index_tail.msb != 0);
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1);
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
return tmp;
}
@ -1831,7 +1890,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
* The signal name may be escaped, but that affects nothing here.
*/
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool sys_task_arg) const
unsigned expr_wid, unsigned flags) const
{
assert(scope);
@ -1841,12 +1900,22 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
const NetExpr*ex1, *ex2;
if (is_param_expr && path_.size() > 1) {
cerr << get_fileline() << ": error: parameter r-value expression "
"does not support hierarchical references `" << path_
<< "`." << endl;
des->errors += 1;
return 0;
if (path_.size() > 1) {
if (NEED_CONST & flags) {
cerr << get_fileline() << ": error: A hierarchical reference"
" (`" << path_ << "') is not allowed in a constant"
" expression." << endl;
des->errors += 1;
return 0;
}
if (scope->need_const_func()) {
cerr << get_fileline() << ": error: A hierarchical reference"
" (`" << path_ << "') is not allowed in a constant"
" function." << endl;
des->errors += 1;
return 0;
}
scope->is_const_func(false);
}
NetScope*found_in = symbol_search(this, des, scope, path_,
@ -1857,7 +1926,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// the parameter value.
if (par != 0) {
NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in,
ex1, ex2, expr_wid);
ex1, ex2, expr_wid, flags);
if (!tmp) return 0;
@ -1867,20 +1936,29 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return tmp;
}
// If this is a parameter expression, no other identifiers are valid.
if (is_param_expr) {
cerr << get_fileline() << ": error: identifier `"
<< path_ << "` is not a parameter in "
<< scope_path(scope) << "." << endl;
des->errors += 1;
return 0;
}
// If the identifier names a signal (a register or wire)
// then create a NetESignal node to handle it.
if (net != 0) {
if (NEED_CONST & flags) {
cerr << get_fileline() << ": error: A reference to a wire "
"or reg (`" << path_ << "') is not allowed in "
"a constant expression." << endl;
des->errors += 1;
return 0;
}
if (net->scope() != scope) {
if (scope->need_const_func()) {
cerr << get_fileline() << ": error: A reference to a "
"non-local wire or reg (`" << path_ << "') is "
"not allowed in a constant function." << endl;
des->errors += 1;
return 0;
}
scope->is_const_func(false);
}
NetExpr*tmp = elaborate_expr_net(des, scope, net, found_in,
expr_wid, sys_task_arg);
expr_wid, flags);
if (!tmp) return 0;
@ -1890,9 +1968,27 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return tmp;
}
// If the identifier is a named event.
// is a variable reference.
// If the identifier is a named event
// then create a NetEEvent node to handle it.
if (eve != 0) {
if (NEED_CONST & flags) {
cerr << get_fileline() << ": error: A reference to a named "
"event (`" << path_ << "') is not allowed in a "
"constant expression." << endl;
des->errors += 1;
return 0;
}
if (eve->scope() != scope) {
if (scope->need_const_func()) {
cerr << get_fileline() << ": error: A reference to a "
"non-local named event (`" << path_ << "') is "
"not allowed in a constant function." << endl;
des->errors += 1;
return 0;
}
scope->is_const_func(false);
}
NetEEvent*tmp = new NetEEvent(eve);
tmp->set_line(*this);
return tmp;
@ -1987,7 +2083,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
NetExpr*expr = elaborate_expr_net(des, scope, net, found_in,
expr_wid, false);
expr_wid, NO_FLAGS);
NetESFunc*sys_expr = 0;
if (method_name == "name") {
@ -2007,7 +2103,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
<< " attached to " << use_path << "." << endl;
des->errors += 1;
return elaborate_expr_net(des, scope, net, found_in,
expr_wid, false);
expr_wid, NO_FLAGS);
}
sys_expr->set_line(*this);
@ -2023,10 +2119,17 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// are not scopes. If this is not a system task argument, then
// it cannot be a scope name, so give up.
if (! sys_task_arg) {
if ( !(SYS_TASK_ARG & flags) ) {
// I cannot interpret this identifier. Error message.
cerr << get_fileline() << ": error: Unable to bind wire/reg/memory "
"`" << path_ << "' in `" << scope_path(scope) << "'"<< endl;
cerr << get_fileline() << ": error: Unable to bind "
<< (NEED_CONST & flags ? "parameter" : "wire/reg/memory")
<< " `" << path_ << "' in `" << scope_path(scope) << "'"
<< endl;
if (scope->need_const_func()) {
cerr << get_fileline() << ": : `" << scope->basename()
<< "' is being used as a constant function, so may "
"only reference local variables." << endl;
}
des->errors += 1;
return 0;
}
@ -2063,7 +2166,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
<< nsc->basename()
<< " path=" << path_ << endl;
if (! sys_task_arg) {
if ( !(SYS_TASK_ARG & flags) ) {
cerr << get_fileline() << ": error: Scope name "
<< nsc->basename() << " not allowed here." << endl;
des->errors += 1;
@ -2248,7 +2351,8 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*,
const NetExpr*par_msb,
const NetExpr*par_lsb) const
const NetExpr*par_lsb,
bool need_const) const
{
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
@ -2258,7 +2362,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
par_lsb, par_lsv,
par_ex->value().len())) return 0;
NetExpr*base = calculate_up_do_base_(des, scope);
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
if (base == 0) return 0;
unsigned long wid = 0;
@ -2327,7 +2431,8 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
const NetExpr*par,
NetScope*,
const NetExpr*par_msb,
const NetExpr*par_lsb) const
const NetExpr*par_lsb,
bool need_const) const
{
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex);
@ -2337,7 +2442,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
par_lsb, par_lsv,
par_ex->value().len())) return 0;
NetExpr*base = calculate_up_do_base_(des, scope);
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
if (base == 0) return 0;
unsigned long wid = 0;
@ -2414,8 +2519,10 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
NetScope*found_in,
const NetExpr*par_msb,
const NetExpr*par_lsb,
unsigned expr_wid) const
unsigned expr_wid, unsigned flags) const
{
bool need_const = NEED_CONST & flags;
const name_component_t&name_tail = path_.back();
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
@ -2440,11 +2547,11 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
if (use_sel == index_component_t::SEL_IDX_UP)
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
par_msb, par_lsb);
par_msb, par_lsb, need_const);
if (use_sel == index_component_t::SEL_IDX_DO)
return elaborate_expr_param_idx_do_(des, scope, par, found_in,
par_msb, par_lsb);
par_msb, par_lsb, need_const);
// NOTE TO SELF (continued): The code below should be
// rewritten in the above format, as I get to it.
@ -2469,7 +2576,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
/* Handle the case where a parameter has a bit
select attached to it. Generate a NetESelect
object to select the bit as desired. */
NetExpr*mtmp = elab_and_eval(des, scope, index_tail.msb, -1);
NetExpr*mtmp = elab_and_eval(des, scope, index_tail.msb, -1,
need_const);
/* Let's first try to get constant values for both
the parameter and the bit select. If they are
@ -2622,11 +2730,13 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in,
unsigned expr_wid,
bool sys_task_arg) const
unsigned flags) const
{
bool need_const = NEED_CONST & flags;
const name_component_t&name_tail = path_.back();
if (name_tail.index.empty() && !sys_task_arg) {
if (name_tail.index.empty() && !(SYS_TASK_ARG & flags)) {
cerr << get_fileline() << ": error: Array " << path()
<< " Needs an array index here." << endl;
des->errors += 1;
@ -2647,10 +2757,12 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
ivl_assert(*this, !index_front.lsb);
}
NetExpr*word_index = index_front.sel == index_component_t::SEL_NONE
? 0
: elab_and_eval(des, scope, index_front.msb, -1);
if (word_index == 0 && !sys_task_arg)
NetExpr*word_index = 0;
if (index_front.sel != index_component_t::SEL_NONE)
word_index = elab_and_eval(des, scope, index_front.msb, -1,
need_const);
if (word_index == 0 && !(SYS_TASK_ARG & flags))
return 0;
if (NetEConst*word_addr = dynamic_cast<NetEConst*>(word_index)) {
@ -2711,16 +2823,20 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
}
if (word_sel == index_component_t::SEL_PART)
return elaborate_expr_net_part_(des, scope, res, found_in, expr_wid);
return elaborate_expr_net_part_(des, scope, res, found_in,
expr_wid);
if (word_sel == index_component_t::SEL_IDX_UP)
return elaborate_expr_net_idx_up_(des, scope, res, found_in);
return elaborate_expr_net_idx_up_(des, scope, res, found_in,
need_const);
if (word_sel == index_component_t::SEL_IDX_DO)
return elaborate_expr_net_idx_do_(des, scope, res, found_in);
return elaborate_expr_net_idx_do_(des, scope, res, found_in,
need_const);
if (word_sel == index_component_t::SEL_BIT)
return elaborate_expr_net_bit_(des, scope, res, found_in);
return elaborate_expr_net_bit_(des, scope, res, found_in,
need_const);
ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
@ -2837,9 +2953,10 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
* Part select indexed up, i.e. net[<m> +: <l>]
*/
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
NetESignal*net, NetScope*) const
NetESignal*net, NetScope*,
bool need_const) const
{
NetExpr*base = calculate_up_do_base_(des, scope);
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid);
@ -2925,9 +3042,10 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
* Part select indexed down, i.e. net[<m> -: <l>]
*/
NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
NetESignal*net, NetScope*)const
NetESignal*net, NetScope*,
bool need_const) const
{
NetExpr*base = calculate_up_do_base_(des, scope);
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid);
@ -3009,7 +3127,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
}
NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
NetESignal*net, NetScope*) const
NetESignal*net, NetScope*,
bool need_const) const
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
@ -3018,7 +3137,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
NetExpr*ex = elab_and_eval(des, scope, index_tail.msb, -1);
NetExpr*ex = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
// If the bit select is constant, then treat it similar
// to the part select, so that I save the effort of
@ -3111,11 +3230,13 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in,
unsigned expr_wid,
bool sys_task_arg) const
unsigned flags) const
{
if (net->array_dimensions() > 0)
return elaborate_expr_net_word_(des, scope, net, found_in,
expr_wid, sys_task_arg);
expr_wid, flags);
bool need_const = NEED_CONST & flags;
NetESignal*node = new NetESignal(net);
node->set_line(*this);
@ -3143,13 +3264,16 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
expr_wid);
if (use_sel == index_component_t::SEL_IDX_UP)
return elaborate_expr_net_idx_up_(des, scope, node, found_in);
return elaborate_expr_net_idx_up_(des, scope, node, found_in,
need_const);
if (use_sel == index_component_t::SEL_IDX_DO)
return elaborate_expr_net_idx_do_(des, scope, node, found_in);
return elaborate_expr_net_idx_do_(des, scope, node, found_in,
need_const);
if (use_sel == index_component_t::SEL_BIT)
return elaborate_expr_net_bit_(des, scope, node, found_in);
return elaborate_expr_net_bit_(des, scope, node, found_in,
need_const);
// It's not anything else, so this must be a simple identifier
// expression with no part or bit select. Return the signal
@ -3173,7 +3297,7 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
}
NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned) const
{
assert(value_);
verinum val = *value_;
@ -3198,7 +3322,7 @@ unsigned PEString::test_width(Design*, NetScope*, width_mode_t&)
}
NetEConst* PEString::elaborate_expr(Design*, NetScope*,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned) const
{
verinum val(value());
val = pad_to_width(val, expr_wid);
@ -3295,15 +3419,17 @@ bool NetETernary::test_operand_compat(ivl_variable_type_t l,
* methods. If any elaboration fails, then give up and return 0.
*/
NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned flags) const
{
assert(expr_);
assert(tru_);
assert(fal_);
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
ivl_assert(*this, expr_);
ivl_assert(*this, tru_);
ivl_assert(*this, fal_);
// Elaborate and evaluate the condition expression. Note that
// it is always self-determined.
NetExpr*con = elab_and_eval(des, scope, expr_, -1);
NetExpr*con = elab_and_eval(des, scope, expr_, -1, NEED_CONST & flags);
if (con == 0)
return 0;
@ -3326,7 +3452,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
"elaborate TRUE clause of ternary."
<< endl;
return elab_and_eval_alternative_(des, scope, tru_, expr_wid);
return elab_and_eval_alternative_(des, scope, tru_,
expr_wid, flags);
}
// Condition is constant FALSE, so we only need the
@ -3337,20 +3464,21 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
"elaborate FALSE clause of ternary."
<< endl;
return elab_and_eval_alternative_(des, scope, fal_, expr_wid);
return elab_and_eval_alternative_(des, scope, fal_,
expr_wid, flags);
}
// X and Z conditions need to blend both results, so we
// can't short-circuit.
}
NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_, expr_wid);
NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_, expr_wid, flags);
if (tru == 0) {
delete con;
return 0;
}
NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_, expr_wid);
NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_, expr_wid, flags);
if (fal == 0) {
delete con;
delete tru;
@ -3378,7 +3506,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
* self-determined.
*/
NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
PExpr*expr, unsigned expr_wid) const
PExpr*expr, unsigned expr_wid,
unsigned flags) const
{
int context_wid = expr_wid;
if (type_is_vectorable(expr->expr_type()) && !type_is_vectorable(expr_type_)) {
@ -3387,7 +3516,7 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
} else {
expr->cast_signed(signed_flag_);
}
NetExpr*tmp = expr->elaborate_expr(des, scope, expr_wid, false);
NetExpr*tmp = expr->elaborate_expr(des, scope, expr_wid, flags);
if (tmp == 0) return 0;
eval_expr(tmp, context_wid);
@ -3436,8 +3565,10 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const
unsigned expr_wid, unsigned flags) const
{
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
unsigned sub_width = expr_wid;
switch (op_) {
// Reduction operators and ! always have a self determined width.
@ -3457,7 +3588,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
expr_->cast_signed(signed_flag_);
break;
}
NetExpr*ip = expr_->elaborate_expr(des, scope, sub_width, false);
NetExpr*ip = expr_->elaborate_expr(des, scope, sub_width, flags);
if (ip == 0) return 0;
ivl_assert(*expr_, expr_type_ != IVL_VT_NO_TYPE);
@ -3604,7 +3735,7 @@ NetExpr* PEUnary::elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const
return tmp;
}
NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, bool) const
NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
{
return 0;
}

View File

@ -222,9 +222,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
case index_component_t::SEL_IDX_DO:
case index_component_t::SEL_IDX_UP: {
need_constant_expr = true;
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
need_constant_expr = false;
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (!tmp) {
cerr << get_fileline() << ": error: indexed part select of "
@ -480,9 +478,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
}
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
need_constant_expr = true;
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
need_constant_expr = false;
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1, true);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (!tmp) {
cerr << get_fileline() << ": error: array " << sig->name()

View File

@ -554,9 +554,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression
// the same way any other parameter value is evaluated.
need_constant_expr = true;
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
need_constant_expr = false;
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1, true);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
@ -620,9 +618,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index;
container->genvar_tmp_val = genvar;
need_constant_expr = true;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
@ -668,9 +664,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
elaborate_subscope_(des, scope);
// Calculate the step for the loop variable.
need_constant_expr = true;
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
need_constant_expr = false;
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1, true);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
if (step == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
@ -700,9 +694,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
{
need_constant_expr = true;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
@ -792,9 +784,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
{
need_constant_expr = true;
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1, true);
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
if (case_value_co == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
@ -824,9 +814,9 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
bool match_flag = false;
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
need_constant_expr = true;
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
need_constant_expr = false;
NetExpr*item_value_ex = elab_and_eval(des, container,
item->item_test[idx],
-1, true);
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
if (item_value_co == 0) {
cerr << get_fileline() << ": error: Cannot evaluate "
@ -1196,10 +1186,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
*/
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
{
need_constant_expr = true;
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
need_constant_expr = false;
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1, true) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1, true) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
@ -1374,6 +1362,14 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::FUNC);
// Save a reference to the pform representation of the function
// in case we need to perform early elaboration.
scope->set_func_pform(this);
// Assume the function is a constant function until we
// find otherwise.
scope->is_const_func(true);
// Scan the parameters in the function, and store the information
// needed to evaluate the parameter expressions.

View File

@ -35,14 +35,6 @@
# include "util.h"
# include "ivl_assert.h"
/*
* Set the following to true when you need to process an expression
* that is being done in a constant context. This allows the
* elaboration to explicitly say we do not currently support constant
* user functions when the function is not found.
*/
bool need_constant_expr = false;
static bool get_const_argument(NetExpr*exp, verinum&res)
{
switch (exp->expr_type()) {
@ -445,6 +437,11 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
*/
void PFunction::elaborate_sig(Design*des, NetScope*scope) const
{
if (scope->elab_stage() > 1)
return;
scope->set_elab_stage(2);
perm_string fname = scope->basename();
assert(scope->type() == NetScope::FUNC);
@ -472,14 +469,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
if (return_type_.range) {
ivl_assert(*this, return_type_.range->size() == 2);
need_constant_expr = true;
NetExpr*me = elab_and_eval(des, scope,
return_type_.range->at(0), -1);
return_type_.range->at(0), -1,
true);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
return_type_.range->at(1), -1);
return_type_.range->at(1), -1,
true);
assert(le);
need_constant_expr = false;
long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) {
@ -545,14 +542,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ivl_assert(*this, return_type_.range != 0);
long use_wid;
{
need_constant_expr = true;
NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0], -1);
(*return_type_.range)[0], -1,
true);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
(*return_type_.range)[1], -1);
(*return_type_.range)[1], -1,
true);
assert(le);
need_constant_expr = false;
long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) {
@ -848,10 +845,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
bool bad_lsb = false, bad_msb = false;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && port_msb_ != 0) {
/* We do not currently support constant user function. */
need_constant_expr = true;
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
need_constant_expr = false;
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1, true);
if (! eval_as_long(pmsb, texpr)) {
cerr << port_msb_->get_fileline() << ": error: "
@ -865,10 +859,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr;
/* We do not currently support constant user function. */
need_constant_expr = true;
texpr = elab_and_eval(des, scope, port_lsb_, -1);
need_constant_expr = false;
texpr = elab_and_eval(des, scope, port_lsb_, -1, true);
if (! eval_as_long(plsb, texpr)) {
cerr << port_lsb_->get_fileline() << ": error: "
@ -892,10 +883,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
/* If they exist get the net/etc. definition MSB and LSB */
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
/* We do not currently support constant user function. */
need_constant_expr = true;
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
need_constant_expr = false;
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1, true);
if (! eval_as_long(nmsb, texpr)) {
cerr << net_msb_->get_fileline() << ": error: "
@ -909,10 +897,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr;
/* We do not currently support constant user function. */
need_constant_expr = true;
texpr = elab_and_eval(des, scope, net_lsb_, -1);
need_constant_expr = false;
texpr = elab_and_eval(des, scope, net_lsb_, -1, true);
if (! eval_as_long(nlsb, texpr)) {
cerr << net_lsb_->get_fileline() << ": error: "
@ -1003,10 +988,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (lidx_ || ridx_) {
assert(lidx_ && ridx_);
need_constant_expr = true;
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
need_constant_expr = false;
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1, true);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1, true);
if ((lexp == 0) || (rexp == 0)) {
cerr << get_fileline() << ": internal error: There is "

View File

@ -227,10 +227,8 @@ unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
gates, then I am expected to make more than one
gate. Figure out how many are desired. */
if (msb_) {
need_constant_expr = true;
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
need_constant_expr = false;
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1, true);
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1, true);
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
@ -265,8 +263,8 @@ unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
if (debug_elaborate) {
cerr << get_fileline() << ": debug: PGBuiltin: Make array "
<< "[" << high << ":" << low << "]"
<< " of " << count << " gates for " << get_name() << endl;
<< "[" << high << ":" << low << "]" << " of "
<< count << " gates for " << get_name() << endl;
}
}
@ -686,8 +684,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
unsigned instance_width = 1;
perm_string name = get_name();
if (name == "")
name = scope->local_symbol();
if (name == "") name = scope->local_symbol();
/* Calculate the array bounds and instance count for the gate,
as described in the Verilog source. If there is none, then
@ -695,8 +692,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
long low=0, high=0;
unsigned array_count = calculate_array_count_(des, scope, high, low);
if (array_count == 0)
return;
if (array_count == 0) return;
unsigned output_count = calculate_output_count_();
@ -1773,6 +1769,62 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
}
unsigned PGModule::calculate_instance_count_(Design*des, NetScope*scope,
long&high, long&low,
perm_string name) const
{
unsigned count = 1;
high = 0;
low = 0;
/* If the Verilog source has a range specification for the UDP, then
* I am expected to make more than one gate. Figure out how many are
* desired. */
if (msb_) {
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1, true);
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1, true);
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
if (msb_con == 0) {
cerr << get_fileline() << ": error: Unable to evaluate "
"expression " << *msb_ << endl;
des->errors += 1;
return 0;
}
if (lsb_con == 0) {
cerr << get_fileline() << ": error: Unable to evaluate "
"expression " << *lsb_ << endl;
des->errors += 1;
return 0;
}
verinum msb = msb_con->value();
verinum lsb = lsb_con->value();
delete msb_exp;
delete lsb_exp;
if (msb.as_long() > lsb.as_long())
count = msb.as_long() - lsb.as_long() + 1;
else
count = lsb.as_long() - msb.as_long() + 1;
low = lsb.as_long();
high = msb.as_long();
if (debug_elaborate) {
cerr << get_fileline() << ": debug: PGModule: Make range "
<< "[" << high << ":" << low << "]" << " of "
<< count << " UDPs for " << name << endl;
}
}
return count;
}
/*
* From a UDP definition in the source, make a NetUDP
* object. Elaborate the pin expressions as netlists, then connect
@ -1803,6 +1855,19 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
}
}
long low = 0, high = 0;
unsigned inst_count = calculate_instance_count_(des, scope, high, low,
my_name);
if (inst_count == 0) return;
if (inst_count != 1) {
cerr << get_fileline() << ": sorry: UDPs with a range ("
<< my_name << " [" << high << ":" << low << "]) are "
<< "not supported." << endl;
des->errors += 1;
return;
}
assert(udp);
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
net->set_line(*this);
@ -2057,9 +2122,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
{
ivl_assert(*this, rval_);
need_constant_expr = is_constant_;
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval());
need_constant_expr = false;
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval(),
is_constant_);
if (!is_constant_ || !rv) return rv;
@ -3376,7 +3440,8 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
PExpr::width_mode_t mode;
pe->test_width(des, scope, mode);
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(), false);
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(),
PExpr::NO_FLAGS);
if (expr == 0) {
cerr << get_fileline() << ": error: Unable to elaborate"
" wait condition expression." << endl;
@ -3736,6 +3801,11 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
void PFunction::elaborate(Design*des, NetScope*scope) const
{
if (scope->elab_stage() > 2)
return;
scope->set_elab_stage(3);
NetFuncDef*def = scope->func_def();
if (def == 0) {
cerr << get_fileline() << ": internal error: "
@ -3751,6 +3821,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
if (st == 0) {
cerr << statement_->get_fileline() << ": error: Unable to elaborate "
"statement in function " << scope->basename() << "." << endl;
scope->is_const_func(true); // error recovery
des->errors += 1;
return;
}
@ -4204,9 +4275,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const
for (specparam_it_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
need_constant_expr = true;
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1);
need_constant_expr = false;
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1,
true);
NetScope::spec_val_t value;
if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) {

View File

@ -1946,12 +1946,29 @@ NetExpr* NetESFunc::eval_tree()
NetExpr* NetEUFunc::eval_tree()
{
if (need_constant_expr) {
cerr << get_fileline() << ": sorry: constant user "
"functions are not currently supported: "
<< func_->basename() << "()." << endl;
// If we know the function cannot be evaluated as a constant,
// give up now.
if (!func()->is_const_func())
return 0;
// Variables inside static functions can be accessed from outside
// the function, so we can't be sure they are constant unless the
// function was called in a constant context.
if (!func()->is_auto() && !need_const_)
return 0;
// Run through the input parameters to check they are constants.
for (unsigned idx = 0; idx < parm_count(); idx += 1) {
if (dynamic_cast<const NetEConst*> (parm(idx)))
continue;
if (dynamic_cast<const NetECReal*> (parm(idx)))
continue;
return 0;
}
if (need_const_) {
cerr << get_fileline() << ": sorry: Constant user functions are "
"not yet supported." << endl;
}
return 0;
}

View File

@ -36,6 +36,7 @@ CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I. -I..
@ -69,7 +70,7 @@ ivlpp@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o ivlpp@EXEEXT@ @EXTRALIBS@
lexor.c: lexor.lex
flex -olexor.c $(srcdir)/lexor.lex
$(LEX) -olexor.c $(srcdir)/lexor.lex
install: all installdirs $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@

View File

@ -33,6 +33,7 @@
# include "compiler.h"
# include "netmisc.h"
# include "PExpr.h"
# include "PTask.h"
# include <sstream>
# include "ivl_assert.h"
@ -332,7 +333,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
/* Evaluate the msb expression, if it is present. */
PExpr*msb_expr = (*cur).second.msb_expr;
if (msb_expr) {
(*cur).second.msb = elab_and_eval(des, this, msb_expr, -1);
(*cur).second.msb = elab_and_eval(des, this, msb_expr, -1, true);
if (! eval_as_long(msb, (*cur).second.msb)) {
cerr << (*cur).second.val->get_fileline()
<< ": error: Unable to evaluate msb expression "
@ -348,7 +349,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
/* Evaluate the lsb expression, if it is present. */
PExpr*lsb_expr = (*cur).second.lsb_expr;
if (lsb_expr) {
(*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -1);
(*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -1, true);
if (! eval_as_long(lsb, (*cur).second.lsb)) {
cerr << (*cur).second.val->get_fileline()
<< ": error: Unable to evaluate lsb expression "
@ -369,7 +370,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
if (range_flag)
lv_width = (msb >= lsb) ? 1 + msb - lsb : 1 + lsb - msb;
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width);
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width, true);
if (! expr)
return;
@ -488,7 +489,7 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
PExpr*val_expr = (*cur).second.val_expr;
NetScope*val_scope = (*cur).second.val_scope;
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1);
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true);
if (! expr)
return;
@ -631,14 +632,6 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
cur->second.val_expr = 0;
}
/*
* Set the following to true when evaluating the parameter expressions.
* This causes PEIdent::elaborate_expr() to report an error if an
* identifier in an expression is anything other than a non-hierarchical
* parameter name.
*/
bool is_param_expr = false;
void NetScope::evaluate_parameters(Design*des)
{
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
@ -649,13 +642,11 @@ void NetScope::evaluate_parameters(Design*des)
cerr << ":0" << ": debug: "
<< "Evaluate parameters in " << scope_path(this) << endl;
is_param_expr = true;
for (param_ref_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur) {
evaluate_parameter_(des, cur);
}
is_param_expr = false;
}
void Design::residual_defparams()
@ -730,9 +721,18 @@ NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
NetScope*func = find_scope(scope, eval_path, NetScope::FUNC);
if (func && (func->type() == NetScope::FUNC))
if (func && (func->type() == NetScope::FUNC)) {
// If a function is used in a parameter definition or in
// a signal declaration, it is possible to get here before
// the function's signals have been elaborated. If this is
// the case, elaborate them now.
if (func->elab_stage() < 2) {
const PFunction*pfunc = func->func_pform();
assert(pfunc);
pfunc->elaborate_sig(this, func);
}
return func->func_def();
}
return 0;
}

View File

@ -43,6 +43,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
{
events_ = 0;
lcounter_ = 0;
need_const_func_ = false;
is_const_func_ = false;
is_auto_ = false;
is_cell_ = false;
@ -72,6 +74,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
default: /* BEGIN_END and FORK_JOIN, do nothing */
break;
}
func_pform_ = 0;
elab_stage_ = 1;
lineno_ = 0;
def_lineno_ = 0;
genvar_tmp_val = 0;

View File

@ -1988,8 +1988,8 @@ const NetExpr* NetSTask::parm(unsigned idx) const
}
NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
svector<NetExpr*>&p)
: scope_(scope), func_(def), result_sig_(res), parms_(p)
svector<NetExpr*>&p, bool nc)
: scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc)
{
expr_width(result_sig_->expr_width());
}

View File

@ -73,6 +73,7 @@ class NetTaskDef;
class NetEvTrig;
class NetEvWait;
class PExpr;
class PFunction;
class netenum_t;
struct target;
@ -790,6 +791,29 @@ class NetScope : public Attrib {
unsigned get_def_lineno() const { return def_lineno_; };
bool in_func() const;
/* Provide a link back to the pform to allow early elaboration of
constant functions. */
void set_func_pform(const PFunction*pfunc) { func_pform_ = pfunc; };
const PFunction*func_pform() const { return func_pform_; };
/* Allow tracking of elaboration stages. The three stages are:
1 - scope elaboration
2 - signal elaboration
3 - statement elaboration
This is only used for functions, to support early elaboration.
*/
void set_elab_stage(unsigned stage) { elab_stage_ = stage; };
unsigned elab_stage() const { return elab_stage_; };
/* Is this a function called in a constant expression. */
void need_const_func(bool need_const) { need_const_func_ = need_const; };
bool need_const_func() const { return need_const_func_; };
/* Is this a constant function. */
void is_const_func(bool is_const) { is_const_func_ = is_const; };
bool is_const_func() const { return is_const_func_; };
/* Is the task or function automatic. */
void is_auto(bool is_auto__) { is_auto_ = is_auto__; };
bool is_auto() const { return is_auto_; };
@ -904,7 +928,6 @@ class NetScope : public Attrib {
param_ref_t find_parameter(perm_string name);
struct spec_val_t {
ivl_variable_type_t type;
union {
@ -954,6 +977,8 @@ class NetScope : public Attrib {
NetTaskDef*task_;
NetFuncDef*func_;
};
const PFunction*func_pform_;
unsigned elab_stage_;
// Enumerations. The enum_sets_ is a list of all the
// enumerations present in this scope. The enum_names_ is a
@ -966,7 +991,7 @@ class NetScope : public Attrib {
map<hname_t,NetScope*> children_;
unsigned lcounter_;
bool is_auto_, is_cell_;
bool need_const_func_, is_const_func_, is_auto_, is_cell_;
};
/*
@ -3095,7 +3120,7 @@ class NetTaskDef {
class NetEUFunc : public NetExpr {
public:
NetEUFunc(NetScope*, NetScope*, NetESignal*, svector<NetExpr*>&);
NetEUFunc(NetScope*, NetScope*, NetESignal*, svector<NetExpr*>&, bool);
~NetEUFunc();
const NetESignal*result_sig() const;
@ -3119,6 +3144,7 @@ class NetEUFunc : public NetExpr {
NetScope*func_;
NetESignal*result_sig_;
svector<NetExpr*> parms_;
bool need_const_;
private: // not implemented
NetEUFunc(const NetEUFunc&);

View File

@ -470,7 +470,8 @@ static const char*width_mode_name(PExpr::width_mode_t mode)
}
}
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
int context_width, bool need_const)
{
PExpr::width_mode_t mode = PExpr::SIZED;
if ((context_width == -2) && !gn_strict_expr_width_flag)
@ -510,7 +511,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
}
}
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, false);
unsigned flags = PExpr::NO_FLAGS;
if (need_const)
flags |= PExpr::NEED_CONST;
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, flags);
if (tmp == 0) return 0;
eval_expr(tmp, context_width);
@ -524,7 +529,7 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
}
NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
unsigned arg_idx, PExpr*pe)
unsigned arg_idx, PExpr*pe, bool need_const)
{
PExpr::width_mode_t mode = PExpr::SIZED;
pe->test_width(des, scope, mode);
@ -539,7 +544,11 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
<< ", mode=" << width_mode_name(mode) << endl;
}
NetExpr*tmp = pe->elaborate_expr(des, scope, pe->expr_width(), true);
unsigned flags = PExpr::SYS_TASK_ARG;
if (need_const)
flags |= PExpr::NEED_CONST;
NetExpr*tmp = pe->elaborate_expr(des, scope, pe->expr_width(), flags);
if (tmp == 0) return 0;
eval_expr(tmp, -1);

View File

@ -134,17 +134,6 @@ extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
*/
extern unsigned count_lval_width(const class NetAssign_*first);
/*
* This is temporarily used to indicate that a user function elaboration
* fail is likely the result of missing constant user function support.
*/
extern bool need_constant_expr;
/*
* This is used to indicate that we are evaluating a parameter expression.
*/
extern bool is_param_expr;
/*
* This function elaborates an expression, and tries to evaluate it
* right away. If the expression can be evaluated, this returns a
@ -160,14 +149,16 @@ extern bool is_param_expr;
class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
PExpr*pe, int context_width);
PExpr*pe, int context_width,
bool need_const =false);
/*
* This function is a variant of elab_and_eval that elaborates and
* evaluates the arguments of a system task.
*/
extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
unsigned arg_idx, PExpr*pe);
extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope,
perm_string name, unsigned arg_idx,
PExpr*pe, bool need_const =false);
/*
* This function elaborates an expression as if it is for the r-value
* of an assignment, The lv_type and lv_width are the type and width
@ -176,7 +167,8 @@ extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
*/
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t lv_type,
unsigned lv_width, PExpr*expr);
unsigned lv_width, PExpr*expr,
bool need_const =false);
/*
* This procedure evaluates an expression and if the evaluation is

View File

@ -1424,6 +1424,36 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
return net->u_.repeat.count;
case IVL_LPM_CONCAT:
return net->u_.concat.inputs;
case IVL_LPM_ABS:
case IVL_LPM_CAST_INT:
case IVL_LPM_CAST_INT2:
case IVL_LPM_CAST_REAL:
case IVL_LPM_RE_AND:
case IVL_LPM_RE_OR:
case IVL_LPM_RE_XOR:
case IVL_LPM_RE_NAND:
case IVL_LPM_RE_NOR:
case IVL_LPM_RE_XNOR:
case IVL_LPM_SIGN_EXT:
case IVL_LPM_FF:
return 1;
case IVL_LPM_ADD:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_POW:
case IVL_LPM_SUB:
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
return 2;
default:
assert(0);
return 0;

View File

@ -320,6 +320,19 @@ static vhdl_expr *translate_binary(ivl_expr_t e)
int rwidth = rhs->get_type()->get_width();
int result_width = ivl_expr_width(e);
// There's a funny corner-case where both the LHS and RHS are constant
// single bit numbers and the VHDL compiler can't decide between the
// std_ulogic and bit overloads of various operators
const bool lnumber = ivl_expr_type(ivl_expr_oper1(e)) == IVL_EX_NUMBER;
const bool rnumber = ivl_expr_type(ivl_expr_oper2(e)) == IVL_EX_NUMBER;
if (lwidth == 1 && rwidth == 1 && lnumber && rnumber) {
// It's sufficient to qualify only one side
vhdl_fcall *lqual = new vhdl_fcall("std_logic'", lhs->get_type());
lqual->add_expr(lhs);
lhs = lqual;
}
// For === and !== we need to compare std_logic_vectors
// rather than signeds
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0);

View File

@ -41,26 +41,6 @@ static vhdl_expr *part_select_base(vhdl_scope *scope, ivl_lpm_t lpm)
return off->cast(&integer);
}
static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
vhdl_type *result_type =
vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0);
vhdl_binop_expr *expr =
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);
for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e) {
delete expr;
return NULL;
}
expr->add_expr(e);
}
return expr;
}
static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t op)
{
unsigned out_width = ivl_lpm_width(lpm);
@ -68,14 +48,21 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop
vhdl_type::type_for(out_width, ivl_lpm_signed(lpm) != 0);
vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type);
for (int i = 0; i < 2; i++) {
for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e) {
delete expr;
if (NULL == e)
return NULL;
}
expr->add_expr(e->cast(result_type));
// It's possible that the inputs are a mixture of signed and unsigned
// in which case we must cast them to the output type
e = e->cast(vhdl_type::type_for(e->get_type()->get_width(),
ivl_lpm_signed(lpm) != 0));
// Bit of a hack: the LPM inputs are in the wrong order for concatenation
if (op == VHDL_BINOP_CONCAT)
expr->add_expr_front(e);
else
expr->add_expr(e);
}
if (op == VHDL_BINOP_MULT) {
@ -256,7 +243,7 @@ static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
case IVL_LPM_MOD:
return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_MOD);
case IVL_LPM_CONCAT:
return concat_lpm_to_expr(scope, lpm);
return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_CONCAT);
case IVL_LPM_CMP_GE:
return rel_lpm_to_expr(scope, lpm, VHDL_BINOP_GEQ);
case IVL_LPM_CMP_GT:
@ -284,7 +271,7 @@ static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
case IVL_LPM_RE_XOR:
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, false);
case IVL_LPM_RE_XNOR:
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, true);
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XNOR, true);
case IVL_LPM_SIGN_EXT:
return sign_extend_lpm_to_expr(scope, lpm);
case IVL_LPM_ARRAY:

View File

@ -239,7 +239,16 @@ void draw_nexus(ivl_nexus_t nexus)
vhdl_type *type = vhdl_type::type_for(lpm_temp_width,
ivl_lpm_signed(lpm) != 0);
ostringstream ss;
ss << "LPM" << ivl_lpm_basename(lpm);
ss << "LPM";
if (nexus == ivl_lpm_q(lpm))
ss << "_q";
else {
for (unsigned d = 0; d < ivl_lpm_size(lpm); d++) {
if (nexus == ivl_lpm_data(lpm, d))
ss << "_d" << d;
}
}
ss << ivl_lpm_basename(lpm);
if (!vhdl_scope->have_declared(ss.str()))
vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type));

View File

@ -144,7 +144,7 @@ void support_function::emit(std::ostream &of, int level) const
emit_reduction(of, level, "and", '1');
break;
case SF_REDUCE_XOR:
emit_reduction(of, level, "xnor", '0');
emit_reduction(of, level, "xor", '0');
break;
case SF_REDUCE_XNOR:
emit_reduction(of, level, "xnor", '0');

View File

@ -940,6 +940,11 @@ void vhdl_binop_expr::add_expr(vhdl_expr *e)
operands_.push_back(e);
}
void vhdl_binop_expr::add_expr_front(vhdl_expr *e)
{
operands_.push_front(e);
}
void vhdl_binop_expr::find_vars(vhdl_var_set_t& read)
{
for (list<vhdl_expr*>::const_iterator it = operands_.begin();

View File

@ -126,6 +126,7 @@ public:
~vhdl_binop_expr();
void add_expr(vhdl_expr *e);
void add_expr_front(vhdl_expr *e);
void emit(std::ostream &of, int level) const;
void find_vars(vhdl_var_set_t& read);
private:

View File

@ -1089,15 +1089,17 @@ verinum pow(const verinum&left, const verinum&right)
long pow_count = right.as_long();
// We need positive and negative one in a few places.
verinum one (verinum::V0, left.len(), left.has_len());
unsigned len = left.len();
// Positive one must be at least two bits wide!
verinum one (verinum::V0, (len<2) ? 2 : len, left.has_len());
one.has_sign(left.has_sign());
one.set(0, verinum::V1);
verinum m_one (verinum::V1, left.len(), left.has_len());
verinum m_one (verinum::V1, len, left.has_len());
m_one.has_sign(true);
// If either the right or left values are undefined we return 'bx.
if (!right.is_defined() || !left.is_defined()) {
result = verinum(verinum::Vx, left.len(), left.has_len());
result = verinum(verinum::Vx, len, left.has_len());
result.has_sign(left.has_sign());
// If the right value is zero we need to set the result to 1.
} else if (pow_count == 0) {
@ -1105,7 +1107,7 @@ verinum pow(const verinum&left, const verinum&right)
} else if (pow_count < 0) {
// 0 ** <negative> is 'bx.
if (left.is_zero()) {
result = verinum(verinum::Vx, left.len(), left.has_len());
result = verinum(verinum::Vx, len, left.has_len());
result.has_sign(left.has_sign());
// 1 ** <negative> is 1.
} else if (left == one) {
@ -1119,7 +1121,7 @@ verinum pow(const verinum&left, const verinum&right)
}
// Everything else is 0.
} else {
result = verinum(verinum::V0, left.len(), left.has_len());
result = verinum(verinum::V0, len, left.has_len());
result.has_sign(left.has_sign());
}
}

View File

@ -50,7 +50,7 @@ class Architecture : public Scope, public LineInfo {
virtual int elaborate(Entity*ent, Architecture*arc);
virtual int emit(ostream&out, Entity*ent, Architecture*arc);
virtual void dump(ostream&out) const;
virtual void dump(ostream&out, int indent = 0) const;
private:
@ -77,7 +77,7 @@ class Architecture : public Scope, public LineInfo {
int emit(ostream&out, Entity*entity);
// The dump method writes a debug display to the given output.
void dump(ostream&out, perm_string of_entity) const;
void dump(ostream&out, perm_string of_entity, int indent = 0) const;
private:
perm_string name_;
@ -100,7 +100,7 @@ class SignalAssignment : public Architecture::Statement {
~SignalAssignment();
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
virtual void dump(ostream&out) const;
virtual void dump(ostream&out, int ident =0) const;
private:
ExpName*lval_;
@ -116,7 +116,7 @@ class ComponentInstantiation : public Architecture::Statement {
virtual int elaborate(Entity*ent, Architecture*arc);
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
virtual void dump(ostream&out) const;
virtual void dump(ostream&out, int indent =0) const;
private:
perm_string iname_;

View File

@ -55,16 +55,16 @@ void dump_design_entities(const char*path)
}
}
void ComponentBase::dump_ports(ostream&out) const
void ComponentBase::dump_ports(ostream&out, int indent) const
{
if (ports_.size() == 0) {
out << " No ports" << endl;
out << setw(indent) << "" << "No ports" << endl;
} else {
out << " PORTS:" << endl;
out << setw(indent) << "" << "PORTS:" << endl;
for (vector<InterfacePort*>::const_iterator cur = ports_.begin()
; cur != ports_.end() ; ++cur) {
InterfacePort*item = *cur;
out << setw(6) << "" << item->name
out << setw(indent+2) << "" << item->name
<< " : " << item->mode
<< ", type=";
if (item->type)
@ -87,68 +87,68 @@ void Scope::dump_scope(ostream&out) const
}
}
void Entity::dump(ostream&out) const
void Entity::dump(ostream&out, int indent) const
{
out << "entity " << get_name()
out << setw(indent) << "" << "entity " << get_name()
<< " file=" << get_fileline() << endl;
dump_ports(out);
dump_ports(out, indent+2);
for (map<perm_string,Architecture*>::const_iterator cur = arch_.begin()
; cur != arch_.end() ; ++cur) {
cur->second->dump(out, get_name());
cur->second->dump(out, get_name(), indent);
}
}
void Architecture::dump(ostream&out, perm_string of_entity) const
void Architecture::dump(ostream&out, perm_string of_entity, int indent) const
{
out << "architecture " << name_
out << setw(indent) << "" << "architecture " << name_
<< " of entity " << of_entity
<< " file=" << get_fileline() << endl;
// Dump signal declarations
for (map<perm_string,Signal*>::const_iterator cur = signals_.begin()
; cur != signals_.end() ; ++cur) {
cur->second->dump(out);
cur->second->dump(out, indent+3);
}
dump_scope(out);
for (list<Architecture::Statement*>::const_iterator cur = statements_.begin()
; cur != statements_.end() ; ++cur) {
(*cur)->dump(out);
(*cur)->dump(out, indent+3);
}
}
void Architecture::Statement::dump(ostream&out) const
void Architecture::Statement::dump(ostream&out, int indent) const
{
out << " Architecture::Statement at file=" << get_fileline() << endl;
out << setw(indent) << "" << "Architecture::Statement at file=" << get_fileline() << endl;
}
void Signal::dump(ostream&out) const
void Signal::dump(ostream&out, int indent) const
{
out << " signal " << name_ << " is " << *type_ << endl;
out << setw(indent) << "" << "signal " << name_ << " is " << *type_ << endl;
}
void SignalAssignment::dump(ostream&out) const
void SignalAssignment::dump(ostream&out, int indent) const
{
out << " SignalAssignment file=" << get_fileline() << endl;
lval_->dump(out, 4);
out << " <= <expr>..." << endl;
out << setw(indent) << "" << "SignalAssignment file=" << get_fileline() << endl;
lval_->dump(out, indent+1);
out << setw(indent+2) << "" << "<= <expr>..." << endl;
for (list<Expression*>::const_iterator cur = rval_.begin()
; cur != rval_.end() ; ++cur) {
(*cur)->dump(out, 5);
(*cur)->dump(out, indent+2);
}
}
void ComponentInstantiation::dump(ostream&out) const
void ComponentInstantiation::dump(ostream&out, int indent) const
{
out << " Component Instantiation file=" << get_fileline() << endl;
out << setw(indent) << "" << "Component Instantiation file=" << get_fileline() << endl;
for (map<perm_string,Expression*>::const_iterator cur = port_map_.begin()
; cur != port_map_.end() ; ++cur) {
out << " " << cur->first << " => ..." << endl;
cur->second->dump(out, 10);
out << setw(indent+2) <<""<< cur->first << " => ..." << endl;
cur->second->dump(out, indent+6);
}
}

View File

@ -63,7 +63,7 @@ class ComponentBase : public LineInfo {
void set_interface(std::list<InterfacePort*>*ports);
public:
void dump_ports(ostream&out) const;
void dump_ports(ostream&out, int indent = 0) const;
protected:
// This is really only used by the Entity derived class.
@ -94,7 +94,7 @@ class Entity : public ComponentBase {
int elaborate();
int emit(ostream&out);
void dump(ostream&out) const;
void dump(ostream&out, int indent = 0) const;
private:
std::map<perm_string,Architecture*>arch_;

View File

@ -56,7 +56,7 @@ class Expression : public LineInfo {
virtual bool is_primary(void) const;
// Debug dump of the expression.
virtual void dump(ostream&out, int indent) const =0;
virtual void dump(ostream&out, int indent = 0) const =0;
private:
@ -73,7 +73,7 @@ class ExpUnary : public Expression {
protected:
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
void dump_operand1(ostream&out, int indent) const;
void dump_operand1(ostream&out, int indent = 0) const;
private:
Expression*operand1_;
@ -94,7 +94,7 @@ class ExpBinary : public Expression {
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
int emit_operand2(ostream&out, Entity*ent, Architecture*arc);
void dump_operands(ostream&out, int indent) const;
void dump_operands(ostream&out, int indent = 0) const;
private:
Expression*operand1_;
@ -111,7 +111,7 @@ class ExpArithmetic : public ExpBinary {
~ExpArithmetic();
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent) const;
void dump(ostream&out, int indent = 0) const;
private:
fun_t fun_;
@ -126,7 +126,7 @@ class ExpInteger : public Expression {
int emit(ostream&out, Entity*ent, Architecture*arc);
bool is_primary(void) const;
bool evaluate(int64_t&val) const;
void dump(ostream&out, int indent) const;
void dump(ostream&out, int indent = 0) const;
private:
int64_t value_;
@ -142,7 +142,7 @@ class ExpLogical : public ExpBinary {
~ExpLogical();
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent) const;
void dump(ostream&out, int indent = 0) const;
private:
fun_t fun_;
@ -162,7 +162,7 @@ class ExpName : public Expression {
public: // Base methods
int emit(ostream&out, Entity*ent, Architecture*arc);
bool is_primary(void) const;
void dump(ostream&out, int indent) const;
void dump(ostream&out, int indent = 0) const;
const char* name() const;
private:
@ -177,7 +177,7 @@ class ExpUAbs : public ExpUnary {
~ExpUAbs();
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent) const;
void dump(ostream&out, int indent = 0) const;
};
class ExpUNot : public ExpUnary {
@ -187,7 +187,7 @@ class ExpUNot : public ExpUnary {
~ExpUNot();
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent) const;
void dump(ostream&out, int indent = 0) const;
};
#endif

View File

@ -34,7 +34,7 @@ class Signal : public LineInfo {
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out) const;
void dump(ostream&out, int indent = 0) const;
private:
perm_string name_;

View File

@ -53,10 +53,10 @@ LDFLAGS = @LDFLAGS@
# Object files for system.vpi
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
sys_finish.o sys_icarus.o sys_plusargs.o sys_random.o sys_random_mti.o \
sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o sys_time.o \
sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o sys_priv.o sdf_lexor.o \
sdf_parse.o stringheap.o vams_simparam.o
sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o sys_random.o \
sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o \
sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o sys_priv.o \
sdf_lexor.o sdf_parse.o stringheap.o vams_simparam.o
OPP = vcd_priv2.o
ifeq (@HAVE_LIBZ@,yes)
@ -118,12 +118,12 @@ system.vpi: $O $(OPP) ../vvp/libvpi.a
$(CXX) @shared@ -o $@ $O $(OPP) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
sys_readmem_lex.c: sys_readmem_lex.lex
flex -t -Preadmem $(srcdir)/sys_readmem_lex.lex > sys_readmem_lex.c
$(LEX) -t -Preadmem $(srcdir)/sys_readmem_lex.lex > sys_readmem_lex.c
sdf_lexor.o: sdf_lexor.c sdf_parse.h
sdf_lexor.c: sdf_lexor.lex
flex -t -Psdf $(srcdir)/sdf_lexor.lex > sdf_lexor.c
$(LEX) -t -Psdf $(srcdir)/sdf_lexor.lex > sdf_lexor.c
sdf_parse.c sdf_parse.h: $(srcdir)/sdf_parse.y
$(YACC) --verbose -d -p sdf -o sdf_parse.c $(srcdir)/sdf_parse.y

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2010 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2008-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
@ -190,31 +190,6 @@ void sys_special_register(void)
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
tf_data.tfname = "$q_initialize";
tf_data.user_data = "$q_initialize";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
tf_data.tfname = "$q_add";
tf_data.user_data = "$q_add";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
tf_data.tfname = "$q_remove";
tf_data.user_data = "$q_remove";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
tf_data.tfname = "$q_full";
tf_data.user_data = "$q_full";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
tf_data.tfname = "$q_exam";
tf_data.user_data = "$q_exam";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
tf_data.tfname = "$dumpports";
tf_data.user_data = "$dumpports";
res = vpi_register_systf(&tf_data);

1357
vpi/sys_queue.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,7 @@ extern void sys_finish_register();
extern void sys_deposit_register();
extern void sys_display_register();
extern void sys_plusargs_register();
extern void sys_queue_register();
extern void sys_random_register();
extern void sys_random_mti_register();
extern void sys_readmem_register();
@ -198,6 +199,7 @@ void (*vlog_startup_routines[])() = {
sys_deposit_register,
sys_display_register,
sys_plusargs_register,
sys_queue_register,
sys_random_register,
sys_random_mti_register,
sys_readmem_register,

View File

@ -15,6 +15,7 @@ $dist_chi_square vpiSysFuncInt
$dist_t vpiSysFuncInt
$dist_erlang vpiSysFuncInt
$clog2 vpiSysFuncInt
$q_full vpiSysFuncInt
$abstime vpiSysFuncReal
$simparam vpiSysFuncReal

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
@ -460,11 +460,14 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
return;
}
double ad, bd;
double ad, bd, resd;
vector4_to_value(op_a_, ad, true);
vector4_to_value(op_b_, bd, true);
/* 2**-1 and -2**-1 are defined to be zero. */
if ((bd == -1) && (fabs(ad) == 2.0)) resd = 0.0;
else resd = pow(ad, bd);
res4 = vvp_vector4_t(wid_, pow(ad, bd));
res4 = vvp_vector4_t(wid_, resd);
} else {
vvp_vector2_t a2 (op_a_);
vvp_vector2_t b2 (op_b_);

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
@ -81,6 +81,7 @@ static void delete_sub_scopes(struct __vpiScope *scope)
case vpiShortIntVar:
case vpiIntVar:
case vpiByteVar:
case vpiBitVar:
signal_delete((scope->intern)[idx]);
break;
case vpiParameter:

View File

@ -4050,10 +4050,13 @@ bool of_POW_S(vthread_t thr, vvp_code_t cp)
}
/* Calculate the result using the double pow() function. */
double xd, yd;
double xd, yd, resd;
vector4_to_value(xv, xd, true);
vector4_to_value(yv, yd, true);
vvp_vector4_t res = vvp_vector4_t(wid, pow(xd, yd));
/* 2**-1 and -2**-1 are defined to be zero. */
if ((yd == -1.0) && (fabs(xd) == 2.0)) resd = 0.0;
else resd = pow(xd, yd);
vvp_vector4_t res = vvp_vector4_t(wid, resd);
/* Copy the result. */
for (unsigned jdx = 0; jdx < wid; jdx += 1)