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

View File

@ -1,7 +1,7 @@
#ifndef __PGate_H #ifndef __PGate_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -238,6 +238,9 @@ class PGModule : public PGate {
friend class delayed_elaborate_scope_mod_instances; friend class delayed_elaborate_scope_mod_instances;
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const; void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
void elaborate_udp_(Design*, PUdp *udp, 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_(Design*des, Module*mod, NetScope*sc) const;
void elaborate_scope_mod_instances_(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; bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;

View File

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

View File

@ -38,6 +38,8 @@ CC = @CC@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
YACC = @YACC@
MAN = @MAN@ MAN = @MAN@
PS2PDF = @PS2PDF@ PS2PDF = @PS2PDF@
@ -78,10 +80,10 @@ iverilog@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o iverilog@EXEEXT@ @EXTRALIBS@ $(CC) $(LDFLAGS) $O -o iverilog@EXEEXT@ @EXTRALIBS@
cflexor.c: cflexor.lex 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 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 %.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o $(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_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); ivl_assert(*this, tmp);
tmp->set_line(*this); 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, NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t lv_type, unsigned lv_width, ivl_variable_type_t lv_type, unsigned lv_width,
PExpr*expr) PExpr*expr, bool need_const)
{ {
int context_wid = -1; int context_wid = -1;
switch (lv_type) { switch (lv_type) {
@ -99,7 +99,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
break; 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; 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" cerr << get_fileline() << ": internal error: I do not know how to"
<< " elaborate this expression. " << endl; << " elaborate this expression. " << endl;
@ -224,8 +224,10 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
* types. * types.
*/ */
NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope, 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, left_);
ivl_assert(*this, right_); ivl_assert(*this, right_);
@ -249,8 +251,8 @@ NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
left_->cast_signed(signed_flag_); left_->cast_signed(signed_flag_);
} }
NetExpr*lp = left_->elaborate_expr(des, scope, l_width, false); NetExpr*lp = left_->elaborate_expr(des, scope, l_width, flags);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false); NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
if ((lp == 0) || (rp == 0)) { if ((lp == 0) || (rp == 0)) {
delete lp; delete lp;
delete rp; 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, 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, left_);
ivl_assert(*this, right_); 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()) if (type_is_vectorable(right_->expr_type()) && !right_->has_sign())
left_->cast_signed(false); left_->cast_signed(false);
NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, false); NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, flags);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, false); NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, flags);
if ((lp == 0) || (rp == 0)) { if ((lp == 0) || (rp == 0)) {
delete lp; delete lp;
delete rp; delete rp;
@ -569,13 +573,14 @@ unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
} }
NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope, 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, left_);
ivl_assert(*this, right_); ivl_assert(*this, right_);
NetExpr*lp = elab_and_eval(des, scope, left_, -1); bool need_const = NEED_CONST & flags;
NetExpr*rp = elab_and_eval(des, scope, right_, -1); 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)) { if ((lp == 0) || (rp == 0)) {
delete lp; delete lp;
delete rp; delete rp;
@ -620,13 +625,13 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
long r_val = LONG_MAX; long r_val = LONG_MAX;
if (r_width < sizeof(long)*8) { if (r_width < sizeof(long)*8) {
r_val = (1L << r_width) - 1L; r_val = (1L << r_width) - 1L;
if (right_->has_sign()) if ((op_ == 'p') && right_->has_sign())
r_val >>= 1; r_val >>= 1;
} }
// If the right operand is constant, we can use the // If the right operand is constant, we can use the
// actual value. // 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) { if (rp) {
eval_expr(rp, r_width); eval_expr(rp, r_width);
} else { } 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, 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_); ivl_assert(*this, left_);
// The left operand is always context determined, so propagate // 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(); unsigned r_width = right_->expr_width();
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, false); NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, flags);
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false); NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
if (lp == 0 || rp == 0) { if (lp == 0 || rp == 0) {
delete lp; delete lp;
delete rp; delete rp;
@ -1074,7 +1081,8 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
* known function names. * known function names.
*/ */
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, 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_); perm_string name = peek_tail_name(path_);
@ -1090,7 +1098,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
} }
PExpr*expr = parms_[0]; 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); 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 as much as possible, and use the reduced
expression if one is created. */ expression if one is created. */
bool need_const = NEED_CONST & flags;
unsigned parm_errors = 0;
unsigned missing_parms = 0; unsigned missing_parms = 0;
for (unsigned idx = 0 ; idx < nparms ; idx += 1) { for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
PExpr*expr = parms_[idx]; PExpr*expr = parms_[idx];
if (expr) { if (expr) {
NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx, expr); NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx,
fun->parm(idx, tmp); expr, need_const);
if (tmp) {
fun->parm(idx, tmp);
} else {
parm_errors += 1;
fun->parm(idx, 0);
}
} else { } else {
missing_parms += 1; missing_parms += 1;
fun->parm(idx, 0); fun->parm(idx, 0);
@ -1183,6 +1199,9 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
des->errors += 1; des->errors += 1;
} }
if (missing_parms || parm_errors)
return 0;
NetExpr*tmp = pad_to_width(fun, expr_wid, *this); NetExpr*tmp = pad_to_width(fun, expr_wid, *this);
tmp->cast_signed(signed_flag_); 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, 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] == '$') 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_); NetFuncDef*def = des->find_function(scope, path_);
if (def == 0) { if (def == 0) {
@ -1265,16 +1286,9 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return elaborate_access_func_(des, scope, access_nature, return elaborate_access_func_(des, scope, access_nature,
expr_wid); expr_wid);
// We do not currently support constant user function and cerr << get_fileline() << ": error: No function named `" << path_
// this is where things fail because of that, though we << "' found in this context (" << scope_path(scope) << ")."
// don't know for sure so we need to display both messages. << endl;
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;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
@ -1283,6 +1297,29 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
NetScope*dscope = def->scope(); NetScope*dscope = def->scope();
ivl_assert(*this, dscope); 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)) if (! check_call_matches_definition_(des, dscope))
return 0; return 0;
@ -1297,6 +1334,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
of the function being called. The scope of the called of the function being called. The scope of the called
function is elaborated when the definition is elaborated. */ function is elaborated when the definition is elaborated. */
unsigned parm_errors = 0;
unsigned missing_parms = 0; unsigned missing_parms = 0;
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) { for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
PExpr*tmp = parms_[idx]; PExpr*tmp = parms_[idx];
@ -1304,7 +1342,11 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
parms[idx] = elaborate_rval_expr(des, scope, parms[idx] = elaborate_rval_expr(des, scope,
def->port(idx)->data_type(), def->port(idx)->data_type(),
(unsigned)def->port(idx)->vector_width(), (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])) { if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[idx])) {
cerr << evt->get_fileline() << ": error: An event '" cerr << evt->get_fileline() << ": error: An event '"
<< evt->event()->name() << "' can not be a user " << evt->event()->name() << "' can not be a user "
@ -1332,6 +1374,28 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
des->errors += 1; 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 /* Look for the return value signal for the called
function. This return value is a magic signal in the scope 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())) { if (NetNet*res = dscope->find_signal(dscope->basename())) {
NetESignal*eres = new NetESignal(res); 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); func->set_line(*this);
NetExpr*tmp = pad_to_width(func, expr_wid, *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 /* If there is a repeat expression, then evaluate the constant
value and set the repeat count. */ value and set the repeat count. */
if (repeat_ && (scope != tested_scope_)) { if (repeat_ && (scope != tested_scope_)) {
need_constant_expr = true; NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1, true);
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1);
need_constant_expr = false;
if (tmp == 0) return 0; if (tmp == 0) return 0;
if (tmp->expr_type() == IVL_VT_REAL) { 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; static int concat_depth = 0;
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, 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; concat_depth += 1;
if (debug_elaborate) { if (debug_elaborate) {
@ -1459,7 +1523,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
assert(parms_[idx]); assert(parms_[idx]);
unsigned wid = parms_[idx]->expr_width(); 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; if (ex == 0) continue;
ex->set_line(*parms_[idx]); ex->set_line(*parms_[idx]);
@ -1542,7 +1606,7 @@ unsigned PEFNumber::test_width(Design*, NetScope*, width_mode_t&)
return expr_width_; 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_); NetECReal*tmp = new NetECReal(*value_);
tmp->set_line(*this); tmp->set_line(*this);
@ -1569,9 +1633,7 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
two bit select expressions, and both must be two bit select expressions, and both must be
constant. Evaluate them and pass the results back to constant. Evaluate them and pass the results back to
the caller. */ the caller. */
need_constant_expr = true; NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
need_constant_expr = false;
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex); NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
if (lsb_c == 0) { if (lsb_c == 0) {
cerr << index_tail.lsb->get_fileline() << ": error: " 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(); lsb = lsb_c->value().as_long();
} }
need_constant_expr = true; NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1);
need_constant_expr = false;
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex); NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
if (msb_c == 0) { if (msb_c == 0) {
cerr << index_tail.msb->get_fileline() << ": error: " 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) /* Calculate the width expression (in the lsb_ position)
first. If the expression is not constant, error but guess 1 first. If the expression is not constant, error but guess 1
so we can keep going and find more errors. */ 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, true);
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
need_constant_expr = false;
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex); NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
if (wid_c == 0) { 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 * 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. * 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(); const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty()); 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.lsb != 0);
ivl_assert(*this, index_tail.msb != 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; 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. * The signal name may be escaped, but that affects nothing here.
*/ */
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool sys_task_arg) const unsigned expr_wid, unsigned flags) const
{ {
assert(scope); assert(scope);
@ -1841,12 +1900,22 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
const NetExpr*ex1, *ex2; const NetExpr*ex1, *ex2;
if (is_param_expr && path_.size() > 1) { if (path_.size() > 1) {
cerr << get_fileline() << ": error: parameter r-value expression " if (NEED_CONST & flags) {
"does not support hierarchical references `" << path_ cerr << get_fileline() << ": error: A hierarchical reference"
<< "`." << endl; " (`" << path_ << "') is not allowed in a constant"
des->errors += 1; " expression." << endl;
return 0; 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_, NetScope*found_in = symbol_search(this, des, scope, path_,
@ -1857,7 +1926,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// the parameter value. // the parameter value.
if (par != 0) { if (par != 0) {
NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in, NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in,
ex1, ex2, expr_wid); ex1, ex2, expr_wid, flags);
if (!tmp) return 0; if (!tmp) return 0;
@ -1867,20 +1936,29 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return tmp; 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) // If the identifier names a signal (a register or wire)
// then create a NetESignal node to handle it. // then create a NetESignal node to handle it.
if (net != 0) { 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, NetExpr*tmp = elaborate_expr_net(des, scope, net, found_in,
expr_wid, sys_task_arg); expr_wid, flags);
if (!tmp) return 0; if (!tmp) return 0;
@ -1890,9 +1968,27 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return tmp; return tmp;
} }
// If the identifier is a named event. // If the identifier is a named event
// is a variable reference. // then create a NetEEvent node to handle it.
if (eve != 0) { 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); NetEEvent*tmp = new NetEEvent(eve);
tmp->set_line(*this); tmp->set_line(*this);
return tmp; return tmp;
@ -1987,7 +2083,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
} }
NetExpr*expr = elaborate_expr_net(des, scope, net, found_in, NetExpr*expr = elaborate_expr_net(des, scope, net, found_in,
expr_wid, false); expr_wid, NO_FLAGS);
NetESFunc*sys_expr = 0; NetESFunc*sys_expr = 0;
if (method_name == "name") { if (method_name == "name") {
@ -2007,7 +2103,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
<< " attached to " << use_path << "." << endl; << " attached to " << use_path << "." << endl;
des->errors += 1; des->errors += 1;
return elaborate_expr_net(des, scope, net, found_in, return elaborate_expr_net(des, scope, net, found_in,
expr_wid, false); expr_wid, NO_FLAGS);
} }
sys_expr->set_line(*this); 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 // are not scopes. If this is not a system task argument, then
// it cannot be a scope name, so give up. // 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. // I cannot interpret this identifier. Error message.
cerr << get_fileline() << ": error: Unable to bind wire/reg/memory " cerr << get_fileline() << ": error: Unable to bind "
"`" << path_ << "' in `" << scope_path(scope) << "'"<< endl; << (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; des->errors += 1;
return 0; return 0;
} }
@ -2063,7 +2166,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
<< nsc->basename() << nsc->basename()
<< " path=" << path_ << endl; << " path=" << path_ << endl;
if (! sys_task_arg) { if ( !(SYS_TASK_ARG & flags) ) {
cerr << get_fileline() << ": error: Scope name " cerr << get_fileline() << ": error: Scope name "
<< nsc->basename() << " not allowed here." << endl; << nsc->basename() << " not allowed here." << endl;
des->errors += 1; des->errors += 1;
@ -2248,7 +2351,8 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
const NetExpr*par, const NetExpr*par,
NetScope*, NetScope*,
const NetExpr*par_msb, 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); const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex); 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_lsb, par_lsv,
par_ex->value().len())) return 0; 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; if (base == 0) return 0;
unsigned long wid = 0; unsigned long wid = 0;
@ -2327,7 +2431,8 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
const NetExpr*par, const NetExpr*par,
NetScope*, NetScope*,
const NetExpr*par_msb, 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); const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
ivl_assert(*this, par_ex); 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_lsb, par_lsv,
par_ex->value().len())) return 0; 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; if (base == 0) return 0;
unsigned long wid = 0; unsigned long wid = 0;
@ -2414,8 +2519,10 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
NetScope*found_in, NetScope*found_in,
const NetExpr*par_msb, const NetExpr*par_msb,
const NetExpr*par_lsb, 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(); const name_component_t&name_tail = path_.back();
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty()) 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) if (use_sel == index_component_t::SEL_IDX_UP)
return elaborate_expr_param_idx_up_(des, scope, par, found_in, 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) if (use_sel == index_component_t::SEL_IDX_DO)
return elaborate_expr_param_idx_do_(des, scope, par, found_in, 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 // NOTE TO SELF (continued): The code below should be
// rewritten in the above format, as I get to it. // 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 /* Handle the case where a parameter has a bit
select attached to it. Generate a NetESelect select attached to it. Generate a NetESelect
object to select the bit as desired. */ 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 /* Let's first try to get constant values for both
the parameter and the bit select. If they are 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, NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in, NetNet*net, NetScope*found_in,
unsigned expr_wid, 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(); 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() cerr << get_fileline() << ": error: Array " << path()
<< " Needs an array index here." << endl; << " Needs an array index here." << endl;
des->errors += 1; des->errors += 1;
@ -2647,10 +2757,12 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
ivl_assert(*this, !index_front.lsb); ivl_assert(*this, !index_front.lsb);
} }
NetExpr*word_index = index_front.sel == index_component_t::SEL_NONE NetExpr*word_index = 0;
? 0 if (index_front.sel != index_component_t::SEL_NONE)
: elab_and_eval(des, scope, index_front.msb, -1); word_index = elab_and_eval(des, scope, index_front.msb, -1,
if (word_index == 0 && !sys_task_arg) need_const);
if (word_index == 0 && !(SYS_TASK_ARG & flags))
return 0; return 0;
if (NetEConst*word_addr = dynamic_cast<NetEConst*>(word_index)) { 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) 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) 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) 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) 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); 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>] * Part select indexed up, i.e. net[<m> +: <l>]
*/ */
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope, 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; unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid); 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>] * Part select indexed down, i.e. net[<m> -: <l>]
*/ */
NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope, 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; unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid); 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, 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(); const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty()); 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.msb != 0);
ivl_assert(*this, index_tail.lsb == 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 // If the bit select is constant, then treat it similar
// to the part select, so that I save the effort of // 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, NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in, NetNet*net, NetScope*found_in,
unsigned expr_wid, unsigned expr_wid,
bool sys_task_arg) const unsigned flags) const
{ {
if (net->array_dimensions() > 0) if (net->array_dimensions() > 0)
return elaborate_expr_net_word_(des, scope, net, found_in, 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); NetESignal*node = new NetESignal(net);
node->set_line(*this); node->set_line(*this);
@ -3143,13 +3264,16 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
expr_wid); expr_wid);
if (use_sel == index_component_t::SEL_IDX_UP) 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) 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) 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 // It's not anything else, so this must be a simple identifier
// expression with no part or bit select. Return the signal // 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*, NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
unsigned expr_wid, bool) const unsigned expr_wid, unsigned) const
{ {
assert(value_); assert(value_);
verinum val = *value_; verinum val = *value_;
@ -3198,7 +3322,7 @@ unsigned PEString::test_width(Design*, NetScope*, width_mode_t&)
} }
NetEConst* PEString::elaborate_expr(Design*, NetScope*, NetEConst* PEString::elaborate_expr(Design*, NetScope*,
unsigned expr_wid, bool) const unsigned expr_wid, unsigned) const
{ {
verinum val(value()); verinum val(value());
val = pad_to_width(val, expr_wid); 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. * methods. If any elaboration fails, then give up and return 0.
*/ */
NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope, NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, bool) const unsigned expr_wid, unsigned flags) const
{ {
assert(expr_); flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
assert(tru_);
assert(fal_); ivl_assert(*this, expr_);
ivl_assert(*this, tru_);
ivl_assert(*this, fal_);
// Elaborate and evaluate the condition expression. Note that // Elaborate and evaluate the condition expression. Note that
// it is always self-determined. // 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) if (con == 0)
return 0; return 0;
@ -3326,7 +3452,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
"elaborate TRUE clause of ternary." "elaborate TRUE clause of ternary."
<< endl; << 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 // 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." "elaborate FALSE clause of ternary."
<< endl; << 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 // X and Z conditions need to blend both results, so we
// can't short-circuit. // 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) { if (tru == 0) {
delete con; delete con;
return 0; 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) { if (fal == 0) {
delete con; delete con;
delete tru; delete tru;
@ -3378,7 +3506,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
* self-determined. * self-determined.
*/ */
NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope, 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; int context_wid = expr_wid;
if (type_is_vectorable(expr->expr_type()) && !type_is_vectorable(expr_type_)) { 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 { } else {
expr->cast_signed(signed_flag_); 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; if (tmp == 0) return 0;
eval_expr(tmp, context_wid); 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, 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; unsigned sub_width = expr_wid;
switch (op_) { switch (op_) {
// Reduction operators and ! always have a self determined width. // 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_); expr_->cast_signed(signed_flag_);
break; 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; if (ip == 0) return 0;
ivl_assert(*expr_, expr_type_ != IVL_VT_NO_TYPE); 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; return tmp;
} }
NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, bool) const NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
{ {
return 0; 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_DO:
case index_component_t::SEL_IDX_UP: { case index_component_t::SEL_IDX_UP: {
need_constant_expr = true; NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
need_constant_expr = false;
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex); NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (!tmp) { if (!tmp) {
cerr << get_fileline() << ": error: indexed part select of " 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); 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, true);
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
need_constant_expr = false;
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex); NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (!tmp) { if (!tmp) {
cerr << get_fileline() << ": error: array " << sig->name() 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 // The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression // use) the genvar itself, so we can evaluate this expression
// the same way any other parameter value is evaluated. // the same way any other parameter value is evaluated.
need_constant_expr = true; NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1, true);
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
need_constant_expr = false;
NetEConst*init = dynamic_cast<NetEConst*> (init_ex); NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) { if (init == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar" 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; cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index; container->genvar_tmp = loop_index;
container->genvar_tmp_val = genvar; container->genvar_tmp_val = genvar;
need_constant_expr = true; NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
NetEConst*test = dynamic_cast<NetEConst*>(test_ex); NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
if (test == 0) { if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar" cerr << get_fileline() << ": error: Cannot evaluate genvar"
@ -668,9 +664,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
elaborate_subscope_(des, scope); elaborate_subscope_(des, scope);
// Calculate the step for the loop variable. // Calculate the step for the loop variable.
need_constant_expr = true; NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1, true);
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
need_constant_expr = false;
NetEConst*step = dynamic_cast<NetEConst*>(step_ex); NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
if (step == 0) { if (step == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar" 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) 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, true);
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
NetEConst*test = dynamic_cast<NetEConst*> (test_ex); NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
if (test == 0) { if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar" 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) 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, true);
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex); NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
if (case_value_co == 0) { if (case_value_co == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar case" 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; bool match_flag = false;
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) { 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,
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1); item->item_test[idx],
need_constant_expr = false; -1, true);
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex); NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
if (item_value_co == 0) { if (item_value_co == 0) {
cerr << get_fileline() << ": error: Cannot evaluate " 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 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, true) : 0;
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0; NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1, true) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
need_constant_expr = false;
NetEConst*msb = dynamic_cast<NetEConst*> (mse); NetEConst*msb = dynamic_cast<NetEConst*> (mse);
NetEConst*lsb = dynamic_cast<NetEConst*> (lse); NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
@ -1374,6 +1362,14 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
{ {
assert(scope->type() == NetScope::FUNC); 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 // Scan the parameters in the function, and store the information
// needed to evaluate the parameter expressions. // needed to evaluate the parameter expressions.

View File

@ -35,14 +35,6 @@
# include "util.h" # include "util.h"
# include "ivl_assert.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) static bool get_const_argument(NetExpr*exp, verinum&res)
{ {
switch (exp->expr_type()) { 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 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(); perm_string fname = scope->basename();
assert(scope->type() == NetScope::FUNC); assert(scope->type() == NetScope::FUNC);
@ -472,14 +469,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
if (return_type_.range) { if (return_type_.range) {
ivl_assert(*this, return_type_.range->size() == 2); ivl_assert(*this, return_type_.range->size() == 2);
need_constant_expr = true;
NetExpr*me = elab_and_eval(des, scope, NetExpr*me = elab_and_eval(des, scope,
return_type_.range->at(0), -1); return_type_.range->at(0), -1,
true);
assert(me); assert(me);
NetExpr*le = elab_and_eval(des, scope, NetExpr*le = elab_and_eval(des, scope,
return_type_.range->at(1), -1); return_type_.range->at(1), -1,
true);
assert(le); assert(le);
need_constant_expr = false;
long mnum = 0, lnum = 0; long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) { 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); ivl_assert(*this, return_type_.range != 0);
long use_wid; long use_wid;
{ {
need_constant_expr = true;
NetExpr*me = elab_and_eval(des, scope, NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0], -1); (*return_type_.range)[0], -1,
true);
assert(me); assert(me);
NetExpr*le = elab_and_eval(des, scope, NetExpr*le = elab_and_eval(des, scope,
(*return_type_.range)[1], -1); (*return_type_.range)[1], -1,
true);
assert(le); assert(le);
need_constant_expr = false;
long mnum = 0, lnum = 0; long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) { 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; bool bad_lsb = false, bad_msb = false;
/* If they exist get the port definition MSB and LSB */ /* If they exist get the port definition MSB and LSB */
if (port_set_ && port_msb_ != 0) { if (port_set_ && port_msb_ != 0) {
/* We do not currently support constant user function. */ NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1, true);
need_constant_expr = true;
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
need_constant_expr = false;
if (! eval_as_long(pmsb, texpr)) { if (! eval_as_long(pmsb, texpr)) {
cerr << port_msb_->get_fileline() << ": error: " cerr << port_msb_->get_fileline() << ": error: "
@ -865,10 +859,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr; delete texpr;
/* We do not currently support constant user function. */ texpr = elab_and_eval(des, scope, port_lsb_, -1, true);
need_constant_expr = true;
texpr = elab_and_eval(des, scope, port_lsb_, -1);
need_constant_expr = false;
if (! eval_as_long(plsb, texpr)) { if (! eval_as_long(plsb, texpr)) {
cerr << port_lsb_->get_fileline() << ": error: " 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 they exist get the net/etc. definition MSB and LSB */
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) { if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
/* We do not currently support constant user function. */ NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1, true);
need_constant_expr = true;
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
need_constant_expr = false;
if (! eval_as_long(nmsb, texpr)) { if (! eval_as_long(nmsb, texpr)) {
cerr << net_msb_->get_fileline() << ": error: " cerr << net_msb_->get_fileline() << ": error: "
@ -909,10 +897,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr; delete texpr;
/* We do not currently support constant user function. */ texpr = elab_and_eval(des, scope, net_lsb_, -1, true);
need_constant_expr = true;
texpr = elab_and_eval(des, scope, net_lsb_, -1);
need_constant_expr = false;
if (! eval_as_long(nlsb, texpr)) { if (! eval_as_long(nlsb, texpr)) {
cerr << net_lsb_->get_fileline() << ": error: " cerr << net_lsb_->get_fileline() << ": error: "
@ -1003,10 +988,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (lidx_ || ridx_) { if (lidx_ || ridx_) {
assert(lidx_ && ridx_); assert(lidx_ && ridx_);
need_constant_expr = true; NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1, true);
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1); NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1, true);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
need_constant_expr = false;
if ((lexp == 0) || (rexp == 0)) { if ((lexp == 0) || (rexp == 0)) {
cerr << get_fileline() << ": internal error: There is " 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 gates, then I am expected to make more than one
gate. Figure out how many are desired. */ gate. Figure out how many are desired. */
if (msb_) { if (msb_) {
need_constant_expr = true; NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1, true);
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1); NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1, true);
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
need_constant_expr = false;
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp); NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_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) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: PGBuiltin: Make array " cerr << get_fileline() << ": debug: PGBuiltin: Make array "
<< "[" << high << ":" << low << "]" << "[" << high << ":" << low << "]" << " of "
<< " of " << count << " gates for " << get_name() << endl; << count << " gates for " << get_name() << endl;
} }
} }
@ -686,8 +684,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
unsigned instance_width = 1; unsigned instance_width = 1;
perm_string name = get_name(); perm_string name = get_name();
if (name == "") if (name == "") name = scope->local_symbol();
name = scope->local_symbol();
/* Calculate the array bounds and instance count for the gate, /* Calculate the array bounds and instance count for the gate,
as described in the Verilog source. If there is none, then 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; long low=0, high=0;
unsigned array_count = calculate_array_count_(des, scope, high, low); unsigned array_count = calculate_array_count_(des, scope, high, low);
if (array_count == 0) if (array_count == 0) return;
return;
unsigned output_count = calculate_output_count_(); 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 * From a UDP definition in the source, make a NetUDP
* object. Elaborate the pin expressions as netlists, then connect * 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); assert(udp);
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp); NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
net->set_line(*this); net->set_line(*this);
@ -2057,9 +2122,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
{ {
ivl_assert(*this, rval_); ivl_assert(*this, rval_);
need_constant_expr = is_constant_; NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval(),
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval()); is_constant_);
need_constant_expr = false;
if (!is_constant_ || !rv) return rv; if (!is_constant_ || !rv) return rv;
@ -3376,7 +3440,8 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
PExpr::width_mode_t mode; PExpr::width_mode_t mode;
pe->test_width(des, scope, 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) { if (expr == 0) {
cerr << get_fileline() << ": error: Unable to elaborate" cerr << get_fileline() << ": error: Unable to elaborate"
" wait condition expression." << endl; " wait condition expression." << endl;
@ -3736,6 +3801,11 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
void PFunction::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(); NetFuncDef*def = scope->func_def();
if (def == 0) { if (def == 0) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "
@ -3751,6 +3821,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
if (st == 0) { if (st == 0) {
cerr << statement_->get_fileline() << ": error: Unable to elaborate " cerr << statement_->get_fileline() << ": error: Unable to elaborate "
"statement in function " << scope->basename() << "." << endl; "statement in function " << scope->basename() << "." << endl;
scope->is_const_func(true); // error recovery
des->errors += 1; des->errors += 1;
return; return;
} }
@ -4204,9 +4275,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const
for (specparam_it_t cur = specparams.begin() for (specparam_it_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) { ; cur != specparams.end() ; ++ cur ) {
need_constant_expr = true; NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1,
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1); true);
need_constant_expr = false;
NetScope::spec_val_t value; NetScope::spec_val_t value;
if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) { if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) {

View File

@ -1946,12 +1946,29 @@ NetExpr* NetESFunc::eval_tree()
NetExpr* NetEUFunc::eval_tree() NetExpr* NetEUFunc::eval_tree()
{ {
if (need_constant_expr) { // If we know the function cannot be evaluated as a constant,
cerr << get_fileline() << ": sorry: constant user " // give up now.
"functions are not currently supported: " if (!func()->is_const_func())
<< func_->basename() << "()." << endl; 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; return 0;
} }

View File

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

View File

@ -33,6 +33,7 @@
# include "compiler.h" # include "compiler.h"
# include "netmisc.h" # include "netmisc.h"
# include "PExpr.h" # include "PExpr.h"
# include "PTask.h"
# include <sstream> # include <sstream>
# include "ivl_assert.h" # 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. */ /* Evaluate the msb expression, if it is present. */
PExpr*msb_expr = (*cur).second.msb_expr; PExpr*msb_expr = (*cur).second.msb_expr;
if (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)) { if (! eval_as_long(msb, (*cur).second.msb)) {
cerr << (*cur).second.val->get_fileline() cerr << (*cur).second.val->get_fileline()
<< ": error: Unable to evaluate msb expression " << ": 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. */ /* Evaluate the lsb expression, if it is present. */
PExpr*lsb_expr = (*cur).second.lsb_expr; PExpr*lsb_expr = (*cur).second.lsb_expr;
if (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)) { if (! eval_as_long(lsb, (*cur).second.lsb)) {
cerr << (*cur).second.val->get_fileline() cerr << (*cur).second.val->get_fileline()
<< ": error: Unable to evaluate lsb expression " << ": error: Unable to evaluate lsb expression "
@ -369,7 +370,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
if (range_flag) if (range_flag)
lv_width = (msb >= lsb) ? 1 + msb - lsb : 1 + lsb - msb; 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) if (! expr)
return; return;
@ -488,7 +489,7 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
PExpr*val_expr = (*cur).second.val_expr; PExpr*val_expr = (*cur).second.val_expr;
NetScope*val_scope = (*cur).second.val_scope; 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) if (! expr)
return; return;
@ -631,14 +632,6 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
cur->second.val_expr = 0; 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) void NetScope::evaluate_parameters(Design*des)
{ {
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin() for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
@ -649,13 +642,11 @@ void NetScope::evaluate_parameters(Design*des)
cerr << ":0" << ": debug: " cerr << ":0" << ": debug: "
<< "Evaluate parameters in " << scope_path(this) << endl; << "Evaluate parameters in " << scope_path(this) << endl;
is_param_expr = true;
for (param_ref_t cur = parameters.begin() for (param_ref_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur) { ; cur != parameters.end() ; ++ cur) {
evaluate_parameter_(des, cur); evaluate_parameter_(des, cur);
} }
is_param_expr = false;
} }
void Design::residual_defparams() 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); std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
NetScope*func = find_scope(scope, eval_path, NetScope::FUNC); 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 func->func_def();
}
return 0; return 0;
} }

View File

@ -43,6 +43,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
{ {
events_ = 0; events_ = 0;
lcounter_ = 0; lcounter_ = 0;
need_const_func_ = false;
is_const_func_ = false;
is_auto_ = false; is_auto_ = false;
is_cell_ = 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 */ default: /* BEGIN_END and FORK_JOIN, do nothing */
break; break;
} }
func_pform_ = 0;
elab_stage_ = 1;
lineno_ = 0; lineno_ = 0;
def_lineno_ = 0; def_lineno_ = 0;
genvar_tmp_val = 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, NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
svector<NetExpr*>&p) svector<NetExpr*>&p, bool nc)
: scope_(scope), func_(def), result_sig_(res), parms_(p) : scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc)
{ {
expr_width(result_sig_->expr_width()); expr_width(result_sig_->expr_width());
} }

View File

@ -73,6 +73,7 @@ class NetTaskDef;
class NetEvTrig; class NetEvTrig;
class NetEvWait; class NetEvWait;
class PExpr; class PExpr;
class PFunction;
class netenum_t; class netenum_t;
struct target; struct target;
@ -790,6 +791,29 @@ class NetScope : public Attrib {
unsigned get_def_lineno() const { return def_lineno_; }; unsigned get_def_lineno() const { return def_lineno_; };
bool in_func() const; 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. */ /* Is the task or function automatic. */
void is_auto(bool is_auto__) { is_auto_ = is_auto__; }; void is_auto(bool is_auto__) { is_auto_ = is_auto__; };
bool is_auto() const { return 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); param_ref_t find_parameter(perm_string name);
struct spec_val_t { struct spec_val_t {
ivl_variable_type_t type; ivl_variable_type_t type;
union { union {
@ -954,6 +977,8 @@ class NetScope : public Attrib {
NetTaskDef*task_; NetTaskDef*task_;
NetFuncDef*func_; NetFuncDef*func_;
}; };
const PFunction*func_pform_;
unsigned elab_stage_;
// Enumerations. The enum_sets_ is a list of all the // Enumerations. The enum_sets_ is a list of all the
// enumerations present in this scope. The enum_names_ is a // enumerations present in this scope. The enum_names_ is a
@ -966,7 +991,7 @@ class NetScope : public Attrib {
map<hname_t,NetScope*> children_; map<hname_t,NetScope*> children_;
unsigned lcounter_; 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 { class NetEUFunc : public NetExpr {
public: public:
NetEUFunc(NetScope*, NetScope*, NetESignal*, svector<NetExpr*>&); NetEUFunc(NetScope*, NetScope*, NetESignal*, svector<NetExpr*>&, bool);
~NetEUFunc(); ~NetEUFunc();
const NetESignal*result_sig() const; const NetESignal*result_sig() const;
@ -3119,6 +3144,7 @@ class NetEUFunc : public NetExpr {
NetScope*func_; NetScope*func_;
NetESignal*result_sig_; NetESignal*result_sig_;
svector<NetExpr*> parms_; svector<NetExpr*> parms_;
bool need_const_;
private: // not implemented private: // not implemented
NetEUFunc(const NetEUFunc&); 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; PExpr::width_mode_t mode = PExpr::SIZED;
if ((context_width == -2) && !gn_strict_expr_width_flag) 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; if (tmp == 0) return 0;
eval_expr(tmp, context_width); 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, 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; PExpr::width_mode_t mode = PExpr::SIZED;
pe->test_width(des, scope, mode); 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; << ", 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; if (tmp == 0) return 0;
eval_expr(tmp, -1); 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); 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 * This function elaborates an expression, and tries to evaluate it
* right away. If the expression can be evaluated, this returns a * right away. If the expression can be evaluated, this returns a
@ -160,14 +149,16 @@ extern bool is_param_expr;
class PExpr; class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope, 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 * This function is a variant of elab_and_eval that elaborates and
* evaluates the arguments of a system task. * evaluates the arguments of a system task.
*/ */
extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name, extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope,
unsigned arg_idx, PExpr*pe); 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 * 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 * 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, extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t lv_type, 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 * 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; return net->u_.repeat.count;
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
return net->u_.concat.inputs; 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: default:
assert(0); assert(0);
return 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 rwidth = rhs->get_type()->get_width();
int result_width = ivl_expr_width(e); 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 // For === and !== we need to compare std_logic_vectors
// rather than signeds // rather than signeds
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0); 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); 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) 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); 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_type::type_for(out_width, ivl_lpm_signed(lpm) != 0);
vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type); 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)); vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e) { if (NULL == e)
delete expr;
return NULL; 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) { 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: case IVL_LPM_MOD:
return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_MOD); return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_MOD);
case IVL_LPM_CONCAT: 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: case IVL_LPM_CMP_GE:
return rel_lpm_to_expr(scope, lpm, VHDL_BINOP_GEQ); return rel_lpm_to_expr(scope, lpm, VHDL_BINOP_GEQ);
case IVL_LPM_CMP_GT: 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: case IVL_LPM_RE_XOR:
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, false); return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, false);
case IVL_LPM_RE_XNOR: 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: case IVL_LPM_SIGN_EXT:
return sign_extend_lpm_to_expr(scope, lpm); return sign_extend_lpm_to_expr(scope, lpm);
case IVL_LPM_ARRAY: 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, vhdl_type *type = vhdl_type::type_for(lpm_temp_width,
ivl_lpm_signed(lpm) != 0); ivl_lpm_signed(lpm) != 0);
ostringstream ss; 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())) if (!vhdl_scope->have_declared(ss.str()))
vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type)); 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'); emit_reduction(of, level, "and", '1');
break; break;
case SF_REDUCE_XOR: case SF_REDUCE_XOR:
emit_reduction(of, level, "xnor", '0'); emit_reduction(of, level, "xor", '0');
break; break;
case SF_REDUCE_XNOR: case SF_REDUCE_XNOR:
emit_reduction(of, level, "xnor", '0'); 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); 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) void vhdl_binop_expr::find_vars(vhdl_var_set_t& read)
{ {
for (list<vhdl_expr*>::const_iterator it = operands_.begin(); for (list<vhdl_expr*>::const_iterator it = operands_.begin();

View File

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

View File

@ -1089,15 +1089,17 @@ verinum pow(const verinum&left, const verinum&right)
long pow_count = right.as_long(); long pow_count = right.as_long();
// We need positive and negative one in a few places. // 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.has_sign(left.has_sign());
one.set(0, verinum::V1); 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); m_one.has_sign(true);
// If either the right or left values are undefined we return 'bx. // If either the right or left values are undefined we return 'bx.
if (!right.is_defined() || !left.is_defined()) { 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()); result.has_sign(left.has_sign());
// If the right value is zero we need to set the result to 1. // If the right value is zero we need to set the result to 1.
} else if (pow_count == 0) { } else if (pow_count == 0) {
@ -1105,7 +1107,7 @@ verinum pow(const verinum&left, const verinum&right)
} else if (pow_count < 0) { } else if (pow_count < 0) {
// 0 ** <negative> is 'bx. // 0 ** <negative> is 'bx.
if (left.is_zero()) { 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()); result.has_sign(left.has_sign());
// 1 ** <negative> is 1. // 1 ** <negative> is 1.
} else if (left == one) { } else if (left == one) {
@ -1119,7 +1121,7 @@ verinum pow(const verinum&left, const verinum&right)
} }
// Everything else is 0. // Everything else is 0.
} else { } else {
result = verinum(verinum::V0, left.len(), left.has_len()); result = verinum(verinum::V0, len, left.has_len());
result.has_sign(left.has_sign()); 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 elaborate(Entity*ent, Architecture*arc);
virtual int emit(ostream&out, 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: private:
@ -77,7 +77,7 @@ class Architecture : public Scope, public LineInfo {
int emit(ostream&out, Entity*entity); int emit(ostream&out, Entity*entity);
// The dump method writes a debug display to the given output. // 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: private:
perm_string name_; perm_string name_;
@ -100,7 +100,7 @@ class SignalAssignment : public Architecture::Statement {
~SignalAssignment(); ~SignalAssignment();
virtual int emit(ostream&out, Entity*entity, Architecture*arc); 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: private:
ExpName*lval_; ExpName*lval_;
@ -116,7 +116,7 @@ class ComponentInstantiation : public Architecture::Statement {
virtual int elaborate(Entity*ent, Architecture*arc); virtual int elaborate(Entity*ent, Architecture*arc);
virtual int emit(ostream&out, Entity*entity, 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: private:
perm_string iname_; 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) { if (ports_.size() == 0) {
out << " No ports" << endl; out << setw(indent) << "" << "No ports" << endl;
} else { } else {
out << " PORTS:" << endl; out << setw(indent) << "" << "PORTS:" << endl;
for (vector<InterfacePort*>::const_iterator cur = ports_.begin() for (vector<InterfacePort*>::const_iterator cur = ports_.begin()
; cur != ports_.end() ; ++cur) { ; cur != ports_.end() ; ++cur) {
InterfacePort*item = *cur; InterfacePort*item = *cur;
out << setw(6) << "" << item->name out << setw(indent+2) << "" << item->name
<< " : " << item->mode << " : " << item->mode
<< ", type="; << ", type=";
if (item->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; << " file=" << get_fileline() << endl;
dump_ports(out); dump_ports(out, indent+2);
for (map<perm_string,Architecture*>::const_iterator cur = arch_.begin() for (map<perm_string,Architecture*>::const_iterator cur = arch_.begin()
; cur != arch_.end() ; ++cur) { ; 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 << " of entity " << of_entity
<< " file=" << get_fileline() << endl; << " file=" << get_fileline() << endl;
// Dump signal declarations // Dump signal declarations
for (map<perm_string,Signal*>::const_iterator cur = signals_.begin() for (map<perm_string,Signal*>::const_iterator cur = signals_.begin()
; cur != signals_.end() ; ++cur) { ; cur != signals_.end() ; ++cur) {
cur->second->dump(out); cur->second->dump(out, indent+3);
} }
dump_scope(out); dump_scope(out);
for (list<Architecture::Statement*>::const_iterator cur = statements_.begin() for (list<Architecture::Statement*>::const_iterator cur = statements_.begin()
; cur != statements_.end() ; ++cur) { ; 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; out << setw(indent) << "" << "SignalAssignment file=" << get_fileline() << endl;
lval_->dump(out, 4); lval_->dump(out, indent+1);
out << " <= <expr>..." << endl; out << setw(indent+2) << "" << "<= <expr>..." << endl;
for (list<Expression*>::const_iterator cur = rval_.begin() for (list<Expression*>::const_iterator cur = rval_.begin()
; cur != rval_.end() ; ++cur) { ; 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() for (map<perm_string,Expression*>::const_iterator cur = port_map_.begin()
; cur != port_map_.end() ; ++cur) { ; cur != port_map_.end() ; ++cur) {
out << " " << cur->first << " => ..." << endl; out << setw(indent+2) <<""<< cur->first << " => ..." << endl;
cur->second->dump(out, 10); cur->second->dump(out, indent+6);
} }
} }

View File

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

View File

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

View File

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

View File

@ -53,10 +53,10 @@ LDFLAGS = @LDFLAGS@
# Object files for system.vpi # Object files for system.vpi
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \ 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_finish.o sys_icarus.o sys_plusargs.o sys_queue.o sys_random.o \
sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o sys_time.o \ sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o \
sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o sys_priv.o sdf_lexor.o \ sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o sys_priv.o \
sdf_parse.o stringheap.o vams_simparam.o sdf_lexor.o sdf_parse.o stringheap.o vams_simparam.o
OPP = vcd_priv2.o OPP = vcd_priv2.o
ifeq (@HAVE_LIBZ@,yes) 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) $(CXX) @shared@ -o $@ $O $(OPP) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
sys_readmem_lex.c: sys_readmem_lex.lex 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.o: sdf_lexor.c sdf_parse.h
sdf_lexor.c: sdf_lexor.lex 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 sdf_parse.c sdf_parse.h: $(srcdir)/sdf_parse.y
$(YACC) --verbose -d -p sdf -o sdf_parse.c $(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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -190,31 +190,6 @@ void sys_special_register(void)
res = vpi_register_systf(&tf_data); res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res); 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.tfname = "$dumpports";
tf_data.user_data = "$dumpports"; tf_data.user_data = "$dumpports";
res = vpi_register_systf(&tf_data); 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_deposit_register();
extern void sys_display_register(); extern void sys_display_register();
extern void sys_plusargs_register(); extern void sys_plusargs_register();
extern void sys_queue_register();
extern void sys_random_register(); extern void sys_random_register();
extern void sys_random_mti_register(); extern void sys_random_mti_register();
extern void sys_readmem_register(); extern void sys_readmem_register();
@ -198,6 +199,7 @@ void (*vlog_startup_routines[])() = {
sys_deposit_register, sys_deposit_register,
sys_display_register, sys_display_register,
sys_plusargs_register, sys_plusargs_register,
sys_queue_register,
sys_random_register, sys_random_register,
sys_random_mti_register, sys_random_mti_register,
sys_readmem_register, sys_readmem_register,

View File

@ -15,6 +15,7 @@ $dist_chi_square vpiSysFuncInt
$dist_t vpiSysFuncInt $dist_t vpiSysFuncInt
$dist_erlang vpiSysFuncInt $dist_erlang vpiSysFuncInt
$clog2 vpiSysFuncInt $clog2 vpiSysFuncInt
$q_full vpiSysFuncInt
$abstime vpiSysFuncReal $abstime vpiSysFuncReal
$simparam 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -460,11 +460,14 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
return; return;
} }
double ad, bd; double ad, bd, resd;
vector4_to_value(op_a_, ad, true); vector4_to_value(op_a_, ad, true);
vector4_to_value(op_b_, bd, 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 { } else {
vvp_vector2_t a2 (op_a_); vvp_vector2_t a2 (op_a_);
vvp_vector2_t b2 (op_b_); 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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -81,6 +81,7 @@ static void delete_sub_scopes(struct __vpiScope *scope)
case vpiShortIntVar: case vpiShortIntVar:
case vpiIntVar: case vpiIntVar:
case vpiByteVar: case vpiByteVar:
case vpiBitVar:
signal_delete((scope->intern)[idx]); signal_delete((scope->intern)[idx]);
break; break;
case vpiParameter: 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. */ /* Calculate the result using the double pow() function. */
double xd, yd; double xd, yd, resd;
vector4_to_value(xv, xd, true); vector4_to_value(xv, xd, true);
vector4_to_value(yv, yd, 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. */ /* Copy the result. */
for (unsigned jdx = 0; jdx < wid; jdx += 1) for (unsigned jdx = 0; jdx < wid; jdx += 1)