Merge branch 'master' into work5
Conflicts: vhdlpp/architec.h vhdlpp/debug.cc
This commit is contained in:
commit
e017ccb5d2
63
PExpr.h
63
PExpr.h
|
|
@ -45,6 +45,11 @@ class PExpr : public LineInfo {
|
|||
public:
|
||||
enum width_mode_t { SIZED, EXPAND, LOSSLESS, UNSIZED };
|
||||
|
||||
// Flag values that can be passed to elaborate_expr.
|
||||
static const unsigned NO_FLAGS = 0x0;
|
||||
static const unsigned NEED_CONST = 0x1;
|
||||
static const unsigned SYS_TASK_ARG = 0x2;
|
||||
|
||||
PExpr();
|
||||
virtual ~PExpr();
|
||||
|
||||
|
|
@ -122,7 +127,7 @@ class PExpr : public LineInfo {
|
|||
// be incomplete.
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
|
|
@ -195,7 +200,7 @@ class PEConcat : public PExpr {
|
|||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
|
@ -261,7 +266,7 @@ class PEFNumber : public PExpr {
|
|||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -301,7 +306,7 @@ class PEIdent : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
|
||||
// Elaborate the PEIdent as a port to a module. This method
|
||||
// only applies to Ident expressions.
|
||||
|
|
@ -330,7 +335,7 @@ class PEIdent : public PExpr {
|
|||
// invalid bits (xz) in either expression, then the defined
|
||||
// flag is set to *false*.
|
||||
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb, bool&defined) const;
|
||||
NetExpr* calculate_up_do_base_(Design*, NetScope*) const;
|
||||
NetExpr* calculate_up_do_base_(Design*, NetScope*, bool need_const) const;
|
||||
bool calculate_param_range_(Design*, NetScope*,
|
||||
const NetExpr*msb_ex, long&msb,
|
||||
const NetExpr*lsb_ex, long&lsb,
|
||||
|
|
@ -352,7 +357,8 @@ class PEIdent : public PExpr {
|
|||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
unsigned expr_wid) const;
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_param_part_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
|
|
@ -365,25 +371,27 @@ class PEIdent : public PExpr {
|
|||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_param_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
|
|
@ -392,15 +400,18 @@ class PEIdent : public PExpr {
|
|||
NetExpr*elaborate_expr_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
|
|
@ -423,7 +434,7 @@ class PENumber : public PExpr {
|
|||
width_mode_t&mode);
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, bool) const;
|
||||
unsigned expr_wid, unsigned) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
|
@ -456,7 +467,7 @@ class PEString : public PExpr {
|
|||
width_mode_t&mode);
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, bool) const;
|
||||
unsigned expr_wid, unsigned) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
|
||||
private:
|
||||
|
|
@ -480,7 +491,7 @@ class PEUnary : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
private:
|
||||
|
|
@ -508,7 +519,7 @@ class PEBinary : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
protected:
|
||||
|
|
@ -546,7 +557,7 @@ class PEBComp : public PEBinary {
|
|||
width_mode_t&mode);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool sys_task_arg) const;
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
private:
|
||||
unsigned l_width_;
|
||||
|
|
@ -566,7 +577,7 @@ class PEBLogic : public PEBinary {
|
|||
width_mode_t&mode);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool sys_task_arg) const;
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -589,7 +600,7 @@ class PEBLeftWidth : public PEBinary {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
};
|
||||
|
||||
class PEBPower : public PEBLeftWidth {
|
||||
|
|
@ -633,12 +644,13 @@ class PETernary : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
private:
|
||||
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
|
||||
PExpr*expr, unsigned expr_wid) const;
|
||||
PExpr*expr, unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
|
|
@ -672,7 +684,7 @@ class PECallFunction : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
|
@ -686,7 +698,8 @@ class PECallFunction : public PExpr {
|
|||
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const;
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t,
|
||||
unsigned expr_wid) const;
|
||||
unsigned test_width_sfunc_(Design*des, NetScope*scope,
|
||||
|
|
@ -705,7 +718,7 @@ class PEVoid : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
5
PGate.h
5
PGate.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PGate_H
|
||||
#define __PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -238,6 +238,9 @@ class PGModule : public PGate {
|
|||
friend class delayed_elaborate_scope_mod_instances;
|
||||
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
|
||||
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
|
||||
unsigned calculate_instance_count_(Design*, NetScope*,
|
||||
long&high, long&low,
|
||||
perm_string name) const;
|
||||
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
|
||||
void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const;
|
||||
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
# undef HAVE_LIBREADLINE
|
||||
# undef HAVE_LIBZ
|
||||
# undef HAVE_LIBBZ2
|
||||
# undef HAVE_LROUND
|
||||
# undef HAVE_SYS_WAIT_H
|
||||
# undef WORDS_BIGENDIAN
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ CC = @CC@
|
|||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
LEX = @LEX@
|
||||
YACC = @YACC@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
|
|
@ -78,10 +80,10 @@ iverilog@EXEEXT@: $O
|
|||
$(CC) $(LDFLAGS) $O -o iverilog@EXEEXT@ @EXTRALIBS@
|
||||
|
||||
cflexor.c: cflexor.lex
|
||||
flex -s -Pcf -ocflexor.c $(srcdir)/cflexor.lex
|
||||
$(LEX) -s -Pcf -ocflexor.c $(srcdir)/cflexor.lex
|
||||
|
||||
cfparse.h cfparse.c: cfparse.y
|
||||
bison --verbose -t -d -o cfparse.c --name-prefix=cf $(srcdir)/cfparse.y
|
||||
$(YACC) --verbose -t -d -o cfparse.c --name-prefix=cf $(srcdir)/cfparse.y
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
|
||||
|
|
|
|||
|
|
@ -239,7 +239,8 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
|||
tmp_parms[idx] = parms_[idx]->dup_expr();
|
||||
}
|
||||
|
||||
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms);
|
||||
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms,
|
||||
need_const_);
|
||||
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->set_line(*this);
|
||||
|
|
|
|||
379
elab_expr.cc
379
elab_expr.cc
|
|
@ -82,7 +82,7 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
|
|||
|
||||
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||
ivl_variable_type_t lv_type, unsigned lv_width,
|
||||
PExpr*expr)
|
||||
PExpr*expr, bool need_const)
|
||||
{
|
||||
int context_wid = -1;
|
||||
switch (lv_type) {
|
||||
|
|
@ -99,7 +99,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
|||
break;
|
||||
}
|
||||
|
||||
return elab_and_eval(des, scope, expr, context_wid);
|
||||
return elab_and_eval(des, scope, expr, context_wid, need_const);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -127,7 +127,7 @@ unsigned PExpr::test_width(Design*des, NetScope*, width_mode_t&)
|
|||
return 1;
|
||||
}
|
||||
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, bool) const
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: I do not know how to"
|
||||
<< " elaborate this expression. " << endl;
|
||||
|
|
@ -224,8 +224,10 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
* types.
|
||||
*/
|
||||
NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
ivl_assert(*this, left_);
|
||||
ivl_assert(*this, right_);
|
||||
|
||||
|
|
@ -249,8 +251,8 @@ NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
|||
left_->cast_signed(signed_flag_);
|
||||
}
|
||||
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, l_width, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, l_width, flags);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -505,8 +507,10 @@ unsigned PEBComp::test_width(Design*des, NetScope*scope, width_mode_t&)
|
|||
}
|
||||
|
||||
NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
ivl_assert(*this, left_);
|
||||
ivl_assert(*this, right_);
|
||||
|
||||
|
|
@ -517,8 +521,8 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
|||
if (type_is_vectorable(right_->expr_type()) && !right_->has_sign())
|
||||
left_->cast_signed(false);
|
||||
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, false);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, flags);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, flags);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -569,13 +573,14 @@ unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
|
|||
}
|
||||
|
||||
NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
ivl_assert(*this, left_);
|
||||
ivl_assert(*this, right_);
|
||||
|
||||
NetExpr*lp = elab_and_eval(des, scope, left_, -1);
|
||||
NetExpr*rp = elab_and_eval(des, scope, right_, -1);
|
||||
bool need_const = NEED_CONST & flags;
|
||||
NetExpr*lp = elab_and_eval(des, scope, left_, -1, need_const);
|
||||
NetExpr*rp = elab_and_eval(des, scope, right_, -1, need_const);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -620,13 +625,13 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
long r_val = LONG_MAX;
|
||||
if (r_width < sizeof(long)*8) {
|
||||
r_val = (1L << r_width) - 1L;
|
||||
if (right_->has_sign())
|
||||
if ((op_ == 'p') && right_->has_sign())
|
||||
r_val >>= 1;
|
||||
}
|
||||
|
||||
// If the right operand is constant, we can use the
|
||||
// actual value.
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, NO_FLAGS);
|
||||
if (rp) {
|
||||
eval_expr(rp, r_width);
|
||||
} else {
|
||||
|
|
@ -707,8 +712,10 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
}
|
||||
|
||||
NetExpr*PEBLeftWidth::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
ivl_assert(*this, left_);
|
||||
|
||||
// The left operand is always context determined, so propagate
|
||||
|
|
@ -717,8 +724,8 @@ NetExpr*PEBLeftWidth::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
unsigned r_width = right_->expr_width();
|
||||
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, flags);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
|
||||
if (lp == 0 || rp == 0) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -1074,7 +1081,8 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
|
|||
* known function names.
|
||||
*/
|
||||
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const
|
||||
{
|
||||
perm_string name = peek_tail_name(path_);
|
||||
|
||||
|
|
@ -1090,7 +1098,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, true);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
|
||||
|
||||
return cast_to_width_(sub, expr_wid);
|
||||
}
|
||||
|
|
@ -1162,13 +1170,21 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
|||
expression as much as possible, and use the reduced
|
||||
expression if one is created. */
|
||||
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
unsigned parm_errors = 0;
|
||||
unsigned missing_parms = 0;
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||
PExpr*expr = parms_[idx];
|
||||
if (expr) {
|
||||
NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx, expr);
|
||||
fun->parm(idx, tmp);
|
||||
|
||||
NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx,
|
||||
expr, need_const);
|
||||
if (tmp) {
|
||||
fun->parm(idx, tmp);
|
||||
} else {
|
||||
parm_errors += 1;
|
||||
fun->parm(idx, 0);
|
||||
}
|
||||
} else {
|
||||
missing_parms += 1;
|
||||
fun->parm(idx, 0);
|
||||
|
|
@ -1183,6 +1199,9 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (missing_parms || parm_errors)
|
||||
return 0;
|
||||
|
||||
NetExpr*tmp = pad_to_width(fun, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
|
|
@ -1250,10 +1269,12 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
if (peek_tail_name(path_)[0] == '$')
|
||||
return elaborate_sfunc_(des, scope, expr_wid);
|
||||
return elaborate_sfunc_(des, scope, expr_wid, flags);
|
||||
|
||||
NetFuncDef*def = des->find_function(scope, path_);
|
||||
if (def == 0) {
|
||||
|
|
@ -1265,16 +1286,9 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
return elaborate_access_func_(des, scope, access_nature,
|
||||
expr_wid);
|
||||
|
||||
// We do not currently support constant user function and
|
||||
// this is where things fail because of that, though we
|
||||
// don't know for sure so we need to display both messages.
|
||||
if (need_constant_expr || is_param_expr) {
|
||||
cerr << get_fileline() << ": sorry: constant user "
|
||||
"functions are not currently supported: "
|
||||
<< path_ << "()." << endl << " or" << endl;
|
||||
}
|
||||
cerr << get_fileline() << ": error: No function " << path_
|
||||
<< " in this context (" << scope_path(scope) << ")." << endl;
|
||||
cerr << get_fileline() << ": error: No function named `" << path_
|
||||
<< "' found in this context (" << scope_path(scope) << ")."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1283,6 +1297,29 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
NetScope*dscope = def->scope();
|
||||
ivl_assert(*this, dscope);
|
||||
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
// It is possible to get here before the called function has been
|
||||
// fully elaborated. If this is the case, elaborate it now. This
|
||||
// ensures we know whether or not it is a constant function.
|
||||
if (dscope->elab_stage() < 3) {
|
||||
dscope->need_const_func(need_const);
|
||||
const PFunction*pfunc = dscope->func_pform();
|
||||
ivl_assert(*this, pfunc);
|
||||
pfunc->elaborate(des, dscope);
|
||||
}
|
||||
|
||||
if (dscope->parent() != scope->parent() || !dscope->is_const_func()) {
|
||||
if (scope->need_const_func()) {
|
||||
cerr << get_fileline() << ": error: A function invoked by "
|
||||
"a constant function must be a constant function "
|
||||
"local to the current module." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
scope->is_const_func(false);
|
||||
}
|
||||
|
||||
if (! check_call_matches_definition_(des, dscope))
|
||||
return 0;
|
||||
|
||||
|
|
@ -1297,6 +1334,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
of the function being called. The scope of the called
|
||||
function is elaborated when the definition is elaborated. */
|
||||
|
||||
unsigned parm_errors = 0;
|
||||
unsigned missing_parms = 0;
|
||||
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
|
||||
PExpr*tmp = parms_[idx];
|
||||
|
|
@ -1304,7 +1342,11 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
parms[idx] = elaborate_rval_expr(des, scope,
|
||||
def->port(idx)->data_type(),
|
||||
(unsigned)def->port(idx)->vector_width(),
|
||||
tmp);
|
||||
tmp, need_const);
|
||||
if (parms[idx] == 0) {
|
||||
parm_errors += 1;
|
||||
continue;
|
||||
}
|
||||
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[idx])) {
|
||||
cerr << evt->get_fileline() << ": error: An event '"
|
||||
<< evt->event()->name() << "' can not be a user "
|
||||
|
|
@ -1332,6 +1374,28 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (need_const && !dscope->is_const_func()) {
|
||||
|
||||
// If this is the first time the function has been called in
|
||||
// a constant context, force the function to be re-elaborated.
|
||||
// This will generate the necessary error messages to allow
|
||||
// the user to diagnose the fault.
|
||||
if (!dscope->need_const_func()) {
|
||||
dscope->set_elab_stage(2);
|
||||
dscope->need_const_func(true);
|
||||
const PFunction*pfunc = dscope->func_pform();
|
||||
ivl_assert(*this, pfunc);
|
||||
pfunc->elaborate(des, dscope);
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: `" << dscope->basename()
|
||||
<< "' is not a constant function." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (missing_parms || parm_errors)
|
||||
return 0;
|
||||
|
||||
/* Look for the return value signal for the called
|
||||
function. This return value is a magic signal in the scope
|
||||
|
|
@ -1343,7 +1407,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
if (NetNet*res = dscope->find_signal(dscope->basename())) {
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms);
|
||||
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
|
||||
func->set_line(*this);
|
||||
|
||||
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
|
||||
|
|
@ -1372,9 +1436,7 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
|
|||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
if (repeat_ && (scope != tested_scope_)) {
|
||||
need_constant_expr = true;
|
||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1, true);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
if (tmp->expr_type() == IVL_VT_REAL) {
|
||||
|
|
@ -1426,8 +1488,10 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
|
|||
static int concat_depth = 0;
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
concat_depth += 1;
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
@ -1459,7 +1523,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
assert(parms_[idx]);
|
||||
unsigned wid = parms_[idx]->expr_width();
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, scope, wid, false);
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, scope, wid, flags);
|
||||
if (ex == 0) continue;
|
||||
|
||||
ex->set_line(*parms_[idx]);
|
||||
|
|
@ -1542,7 +1606,7 @@ unsigned PEFNumber::test_width(Design*, NetScope*, width_mode_t&)
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, bool) const
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
|
||||
{
|
||||
NetECReal*tmp = new NetECReal(*value_);
|
||||
tmp->set_line(*this);
|
||||
|
|
@ -1569,9 +1633,7 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
|||
two bit select expressions, and both must be
|
||||
constant. Evaluate them and pass the results back to
|
||||
the caller. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
|
||||
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
|
||||
if (lsb_c == 0) {
|
||||
cerr << index_tail.lsb->get_fileline() << ": error: "
|
||||
|
|
@ -1589,9 +1651,7 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
|||
lsb = lsb_c->value().as_long();
|
||||
}
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
|
||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||
if (msb_c == 0) {
|
||||
cerr << index_tail.msb->get_fileline() << ": error: "
|
||||
|
|
@ -1628,9 +1688,7 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
|
|||
/* Calculate the width expression (in the lsb_ position)
|
||||
first. If the expression is not constant, error but guess 1
|
||||
so we can keep going and find more errors. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
||||
|
||||
if (wid_c == 0) {
|
||||
|
|
@ -1651,7 +1709,8 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
|
|||
* When we know that this is an indexed part select (up or down) this
|
||||
* method calculates the up/down base, as far at it can be calculated.
|
||||
*/
|
||||
NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
|
||||
NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope,
|
||||
bool need_const) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
|
@ -1660,7 +1719,7 @@ NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, index_tail.lsb != 0);
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
@ -1831,7 +1890,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
* The signal name may be escaped, but that affects nothing here.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool sys_task_arg) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
|
|
@ -1841,12 +1900,22 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
if (is_param_expr && path_.size() > 1) {
|
||||
cerr << get_fileline() << ": error: parameter r-value expression "
|
||||
"does not support hierarchical references `" << path_
|
||||
<< "`." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
if (path_.size() > 1) {
|
||||
if (NEED_CONST & flags) {
|
||||
cerr << get_fileline() << ": error: A hierarchical reference"
|
||||
" (`" << path_ << "') is not allowed in a constant"
|
||||
" expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
if (scope->need_const_func()) {
|
||||
cerr << get_fileline() << ": error: A hierarchical reference"
|
||||
" (`" << path_ << "') is not allowed in a constant"
|
||||
" function." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
scope->is_const_func(false);
|
||||
}
|
||||
|
||||
NetScope*found_in = symbol_search(this, des, scope, path_,
|
||||
|
|
@ -1857,7 +1926,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// the parameter value.
|
||||
if (par != 0) {
|
||||
NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in,
|
||||
ex1, ex2, expr_wid);
|
||||
ex1, ex2, expr_wid, flags);
|
||||
|
||||
if (!tmp) return 0;
|
||||
|
||||
|
|
@ -1867,20 +1936,29 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
// If this is a parameter expression, no other identifiers are valid.
|
||||
if (is_param_expr) {
|
||||
cerr << get_fileline() << ": error: identifier `"
|
||||
<< path_ << "` is not a parameter in "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (net != 0) {
|
||||
if (NEED_CONST & flags) {
|
||||
cerr << get_fileline() << ": error: A reference to a wire "
|
||||
"or reg (`" << path_ << "') is not allowed in "
|
||||
"a constant expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
if (net->scope() != scope) {
|
||||
if (scope->need_const_func()) {
|
||||
cerr << get_fileline() << ": error: A reference to a "
|
||||
"non-local wire or reg (`" << path_ << "') is "
|
||||
"not allowed in a constant function." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
scope->is_const_func(false);
|
||||
}
|
||||
|
||||
NetExpr*tmp = elaborate_expr_net(des, scope, net, found_in,
|
||||
expr_wid, sys_task_arg);
|
||||
expr_wid, flags);
|
||||
|
||||
if (!tmp) return 0;
|
||||
|
||||
|
|
@ -1890,9 +1968,27 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
// If the identifier is a named event.
|
||||
// is a variable reference.
|
||||
// If the identifier is a named event
|
||||
// then create a NetEEvent node to handle it.
|
||||
if (eve != 0) {
|
||||
if (NEED_CONST & flags) {
|
||||
cerr << get_fileline() << ": error: A reference to a named "
|
||||
"event (`" << path_ << "') is not allowed in a "
|
||||
"constant expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
if (eve->scope() != scope) {
|
||||
if (scope->need_const_func()) {
|
||||
cerr << get_fileline() << ": error: A reference to a "
|
||||
"non-local named event (`" << path_ << "') is "
|
||||
"not allowed in a constant function." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
scope->is_const_func(false);
|
||||
}
|
||||
|
||||
NetEEvent*tmp = new NetEEvent(eve);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
|
|
@ -1987,7 +2083,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetExpr*expr = elaborate_expr_net(des, scope, net, found_in,
|
||||
expr_wid, false);
|
||||
expr_wid, NO_FLAGS);
|
||||
NetESFunc*sys_expr = 0;
|
||||
|
||||
if (method_name == "name") {
|
||||
|
|
@ -2007,7 +2103,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< " attached to " << use_path << "." << endl;
|
||||
des->errors += 1;
|
||||
return elaborate_expr_net(des, scope, net, found_in,
|
||||
expr_wid, false);
|
||||
expr_wid, NO_FLAGS);
|
||||
}
|
||||
|
||||
sys_expr->set_line(*this);
|
||||
|
|
@ -2023,10 +2119,17 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// are not scopes. If this is not a system task argument, then
|
||||
// it cannot be a scope name, so give up.
|
||||
|
||||
if (! sys_task_arg) {
|
||||
if ( !(SYS_TASK_ARG & flags) ) {
|
||||
// I cannot interpret this identifier. Error message.
|
||||
cerr << get_fileline() << ": error: Unable to bind wire/reg/memory "
|
||||
"`" << path_ << "' in `" << scope_path(scope) << "'"<< endl;
|
||||
cerr << get_fileline() << ": error: Unable to bind "
|
||||
<< (NEED_CONST & flags ? "parameter" : "wire/reg/memory")
|
||||
<< " `" << path_ << "' in `" << scope_path(scope) << "'"
|
||||
<< endl;
|
||||
if (scope->need_const_func()) {
|
||||
cerr << get_fileline() << ": : `" << scope->basename()
|
||||
<< "' is being used as a constant function, so may "
|
||||
"only reference local variables." << endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2063,7 +2166,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< nsc->basename()
|
||||
<< " path=" << path_ << endl;
|
||||
|
||||
if (! sys_task_arg) {
|
||||
if ( !(SYS_TASK_ARG & flags) ) {
|
||||
cerr << get_fileline() << ": error: Scope name "
|
||||
<< nsc->basename() << " not allowed here." << endl;
|
||||
des->errors += 1;
|
||||
|
|
@ -2248,7 +2351,8 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
|||
const NetExpr*par,
|
||||
NetScope*,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const
|
||||
{
|
||||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||
ivl_assert(*this, par_ex);
|
||||
|
|
@ -2258,7 +2362,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
|||
par_lsb, par_lsv,
|
||||
par_ex->value().len())) return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
if (base == 0) return 0;
|
||||
|
||||
unsigned long wid = 0;
|
||||
|
|
@ -2327,7 +2431,8 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
|
|||
const NetExpr*par,
|
||||
NetScope*,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const
|
||||
{
|
||||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||
ivl_assert(*this, par_ex);
|
||||
|
|
@ -2337,7 +2442,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
|
|||
par_lsb, par_lsv,
|
||||
par_ex->value().len())) return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
if (base == 0) return 0;
|
||||
|
||||
unsigned long wid = 0;
|
||||
|
|
@ -2414,8 +2519,10 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
unsigned expr_wid) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
|
|
@ -2440,11 +2547,11 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
|
||||
par_msb, par_lsb);
|
||||
par_msb, par_lsb, need_const);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_param_idx_do_(des, scope, par, found_in,
|
||||
par_msb, par_lsb);
|
||||
par_msb, par_lsb, need_const);
|
||||
|
||||
// NOTE TO SELF (continued): The code below should be
|
||||
// rewritten in the above format, as I get to it.
|
||||
|
|
@ -2469,7 +2576,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
/* Handle the case where a parameter has a bit
|
||||
select attached to it. Generate a NetESelect
|
||||
object to select the bit as desired. */
|
||||
NetExpr*mtmp = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetExpr*mtmp = elab_and_eval(des, scope, index_tail.msb, -1,
|
||||
need_const);
|
||||
|
||||
/* Let's first try to get constant values for both
|
||||
the parameter and the bit select. If they are
|
||||
|
|
@ -2622,11 +2730,13 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const
|
||||
unsigned flags) const
|
||||
{
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
if (name_tail.index.empty() && !sys_task_arg) {
|
||||
if (name_tail.index.empty() && !(SYS_TASK_ARG & flags)) {
|
||||
cerr << get_fileline() << ": error: Array " << path()
|
||||
<< " Needs an array index here." << endl;
|
||||
des->errors += 1;
|
||||
|
|
@ -2647,10 +2757,12 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, !index_front.lsb);
|
||||
}
|
||||
|
||||
NetExpr*word_index = index_front.sel == index_component_t::SEL_NONE
|
||||
? 0
|
||||
: elab_and_eval(des, scope, index_front.msb, -1);
|
||||
if (word_index == 0 && !sys_task_arg)
|
||||
NetExpr*word_index = 0;
|
||||
if (index_front.sel != index_component_t::SEL_NONE)
|
||||
word_index = elab_and_eval(des, scope, index_front.msb, -1,
|
||||
need_const);
|
||||
|
||||
if (word_index == 0 && !(SYS_TASK_ARG & flags))
|
||||
return 0;
|
||||
|
||||
if (NetEConst*word_addr = dynamic_cast<NetEConst*>(word_index)) {
|
||||
|
|
@ -2711,16 +2823,20 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
if (word_sel == index_component_t::SEL_PART)
|
||||
return elaborate_expr_net_part_(des, scope, res, found_in, expr_wid);
|
||||
return elaborate_expr_net_part_(des, scope, res, found_in,
|
||||
expr_wid);
|
||||
|
||||
if (word_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, res, found_in);
|
||||
return elaborate_expr_net_idx_up_(des, scope, res, found_in,
|
||||
need_const);
|
||||
|
||||
if (word_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, res, found_in);
|
||||
return elaborate_expr_net_idx_do_(des, scope, res, found_in,
|
||||
need_const);
|
||||
|
||||
if (word_sel == index_component_t::SEL_BIT)
|
||||
return elaborate_expr_net_bit_(des, scope, res, found_in);
|
||||
return elaborate_expr_net_bit_(des, scope, res, found_in,
|
||||
need_const);
|
||||
|
||||
ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
|
||||
|
||||
|
|
@ -2837,9 +2953,10 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
|||
* Part select indexed up, i.e. net[<m> +: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetESignal*net, NetScope*) const
|
||||
NetESignal*net, NetScope*,
|
||||
bool need_const) const
|
||||
{
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
|
@ -2925,9 +3042,10 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
|||
* Part select indexed down, i.e. net[<m> -: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
NetESignal*net, NetScope*)const
|
||||
NetESignal*net, NetScope*,
|
||||
bool need_const) const
|
||||
{
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
|
@ -3009,7 +3127,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
NetESignal*net, NetScope*) const
|
||||
NetESignal*net, NetScope*,
|
||||
bool need_const) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
|
@ -3018,7 +3137,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
NetExpr*ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetExpr*ex = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
|
||||
|
||||
// If the bit select is constant, then treat it similar
|
||||
// to the part select, so that I save the effort of
|
||||
|
|
@ -3111,11 +3230,13 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const
|
||||
unsigned flags) const
|
||||
{
|
||||
if (net->array_dimensions() > 0)
|
||||
return elaborate_expr_net_word_(des, scope, net, found_in,
|
||||
expr_wid, sys_task_arg);
|
||||
expr_wid, flags);
|
||||
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
|
|
@ -3143,13 +3264,16 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
|||
expr_wid);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, node, found_in);
|
||||
return elaborate_expr_net_idx_up_(des, scope, node, found_in,
|
||||
need_const);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, node, found_in);
|
||||
return elaborate_expr_net_idx_do_(des, scope, node, found_in,
|
||||
need_const);
|
||||
|
||||
if (use_sel == index_component_t::SEL_BIT)
|
||||
return elaborate_expr_net_bit_(des, scope, node, found_in);
|
||||
return elaborate_expr_net_bit_(des, scope, node, found_in,
|
||||
need_const);
|
||||
|
||||
// It's not anything else, so this must be a simple identifier
|
||||
// expression with no part or bit select. Return the signal
|
||||
|
|
@ -3173,7 +3297,7 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
|
|||
}
|
||||
|
||||
NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned) const
|
||||
{
|
||||
assert(value_);
|
||||
verinum val = *value_;
|
||||
|
|
@ -3198,7 +3322,7 @@ unsigned PEString::test_width(Design*, NetScope*, width_mode_t&)
|
|||
}
|
||||
|
||||
NetEConst* PEString::elaborate_expr(Design*, NetScope*,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned) const
|
||||
{
|
||||
verinum val(value());
|
||||
val = pad_to_width(val, expr_wid);
|
||||
|
|
@ -3295,15 +3419,17 @@ bool NetETernary::test_operand_compat(ivl_variable_type_t l,
|
|||
* methods. If any elaboration fails, then give up and return 0.
|
||||
*/
|
||||
NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
assert(expr_);
|
||||
assert(tru_);
|
||||
assert(fal_);
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
ivl_assert(*this, expr_);
|
||||
ivl_assert(*this, tru_);
|
||||
ivl_assert(*this, fal_);
|
||||
|
||||
// Elaborate and evaluate the condition expression. Note that
|
||||
// it is always self-determined.
|
||||
NetExpr*con = elab_and_eval(des, scope, expr_, -1);
|
||||
NetExpr*con = elab_and_eval(des, scope, expr_, -1, NEED_CONST & flags);
|
||||
if (con == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -3326,7 +3452,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
|||
"elaborate TRUE clause of ternary."
|
||||
<< endl;
|
||||
|
||||
return elab_and_eval_alternative_(des, scope, tru_, expr_wid);
|
||||
return elab_and_eval_alternative_(des, scope, tru_,
|
||||
expr_wid, flags);
|
||||
}
|
||||
|
||||
// Condition is constant FALSE, so we only need the
|
||||
|
|
@ -3337,20 +3464,21 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
|||
"elaborate FALSE clause of ternary."
|
||||
<< endl;
|
||||
|
||||
return elab_and_eval_alternative_(des, scope, fal_, expr_wid);
|
||||
return elab_and_eval_alternative_(des, scope, fal_,
|
||||
expr_wid, flags);
|
||||
}
|
||||
|
||||
// X and Z conditions need to blend both results, so we
|
||||
// can't short-circuit.
|
||||
}
|
||||
|
||||
NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_, expr_wid);
|
||||
NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_, expr_wid, flags);
|
||||
if (tru == 0) {
|
||||
delete con;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_, expr_wid);
|
||||
NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_, expr_wid, flags);
|
||||
if (fal == 0) {
|
||||
delete con;
|
||||
delete tru;
|
||||
|
|
@ -3378,7 +3506,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
|||
* self-determined.
|
||||
*/
|
||||
NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
|
||||
PExpr*expr, unsigned expr_wid) const
|
||||
PExpr*expr, unsigned expr_wid,
|
||||
unsigned flags) const
|
||||
{
|
||||
int context_wid = expr_wid;
|
||||
if (type_is_vectorable(expr->expr_type()) && !type_is_vectorable(expr_type_)) {
|
||||
|
|
@ -3387,7 +3516,7 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
|
|||
} else {
|
||||
expr->cast_signed(signed_flag_);
|
||||
}
|
||||
NetExpr*tmp = expr->elaborate_expr(des, scope, expr_wid, false);
|
||||
NetExpr*tmp = expr->elaborate_expr(des, scope, expr_wid, flags);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
eval_expr(tmp, context_wid);
|
||||
|
|
@ -3436,8 +3565,10 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
|
||||
|
||||
NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
unsigned sub_width = expr_wid;
|
||||
switch (op_) {
|
||||
// Reduction operators and ! always have a self determined width.
|
||||
|
|
@ -3457,7 +3588,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
|||
expr_->cast_signed(signed_flag_);
|
||||
break;
|
||||
}
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope, sub_width, false);
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope, sub_width, flags);
|
||||
if (ip == 0) return 0;
|
||||
|
||||
ivl_assert(*expr_, expr_type_ != IVL_VT_NO_TYPE);
|
||||
|
|
@ -3604,7 +3735,7 @@ NetExpr* PEUnary::elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, bool) const
|
||||
NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,9 +222,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
|||
|
||||
case index_component_t::SEL_IDX_DO:
|
||||
case index_component_t::SEL_IDX_UP: {
|
||||
need_constant_expr = true;
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
if (!tmp) {
|
||||
cerr << get_fileline() << ": error: indexed part select of "
|
||||
|
|
@ -480,9 +478,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
}
|
||||
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1, true);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
if (!tmp) {
|
||||
cerr << get_fileline() << ": error: array " << sig->name()
|
||||
|
|
|
|||
|
|
@ -554,9 +554,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
// The initial value for the genvar does not need (nor can it
|
||||
// use) the genvar itself, so we can evaluate this expression
|
||||
// the same way any other parameter value is evaluated.
|
||||
need_constant_expr = true;
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1, true);
|
||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||
if (init == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
|
|
@ -620,9 +618,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
|
||||
container->genvar_tmp = loop_index;
|
||||
container->genvar_tmp_val = genvar;
|
||||
need_constant_expr = true;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
|
||||
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
||||
if (test == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
|
|
@ -668,9 +664,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
elaborate_subscope_(des, scope);
|
||||
|
||||
// Calculate the step for the loop variable.
|
||||
need_constant_expr = true;
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1, true);
|
||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||
if (step == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
|
|
@ -700,9 +694,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
|
||||
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
|
||||
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
||||
if (test == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
|
|
@ -792,9 +784,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
|||
|
||||
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1, true);
|
||||
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
||||
if (case_value_co == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
||||
|
|
@ -824,9 +814,9 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
|||
|
||||
bool match_flag = false;
|
||||
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
|
||||
need_constant_expr = true;
|
||||
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*item_value_ex = elab_and_eval(des, container,
|
||||
item->item_test[idx],
|
||||
-1, true);
|
||||
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
||||
if (item_value_co == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate "
|
||||
|
|
@ -1196,10 +1186,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
|||
*/
|
||||
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
||||
need_constant_expr = false;
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1, true) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1, true) : 0;
|
||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||
|
||||
|
|
@ -1374,6 +1362,14 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
|
||||
// Save a reference to the pform representation of the function
|
||||
// in case we need to perform early elaboration.
|
||||
scope->set_func_pform(this);
|
||||
|
||||
// Assume the function is a constant function until we
|
||||
// find otherwise.
|
||||
scope->is_const_func(true);
|
||||
|
||||
// Scan the parameters in the function, and store the information
|
||||
// needed to evaluate the parameter expressions.
|
||||
|
||||
|
|
|
|||
55
elab_sig.cc
55
elab_sig.cc
|
|
@ -35,14 +35,6 @@
|
|||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* Set the following to true when you need to process an expression
|
||||
* that is being done in a constant context. This allows the
|
||||
* elaboration to explicitly say we do not currently support constant
|
||||
* user functions when the function is not found.
|
||||
*/
|
||||
bool need_constant_expr = false;
|
||||
|
||||
static bool get_const_argument(NetExpr*exp, verinum&res)
|
||||
{
|
||||
switch (exp->expr_type()) {
|
||||
|
|
@ -445,6 +437,11 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
|||
*/
|
||||
void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (scope->elab_stage() > 1)
|
||||
return;
|
||||
|
||||
scope->set_elab_stage(2);
|
||||
|
||||
perm_string fname = scope->basename();
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
|
||||
|
|
@ -472,14 +469,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (return_type_.range) {
|
||||
ivl_assert(*this, return_type_.range->size() == 2);
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
return_type_.range->at(0), -1);
|
||||
return_type_.range->at(0), -1,
|
||||
true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
return_type_.range->at(1), -1);
|
||||
return_type_.range->at(1), -1,
|
||||
true);
|
||||
assert(le);
|
||||
need_constant_expr = false;
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
|
|
@ -545,14 +542,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, return_type_.range != 0);
|
||||
long use_wid;
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0], -1);
|
||||
(*return_type_.range)[0], -1,
|
||||
true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[1], -1);
|
||||
(*return_type_.range)[1], -1,
|
||||
true);
|
||||
assert(le);
|
||||
need_constant_expr = false;
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
|
|
@ -848,10 +845,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
bool bad_lsb = false, bad_msb = false;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
if (port_set_ && port_msb_ != 0) {
|
||||
/* We do not currently support constant user function. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1, true);
|
||||
|
||||
if (! eval_as_long(pmsb, texpr)) {
|
||||
cerr << port_msb_->get_fileline() << ": error: "
|
||||
|
|
@ -865,10 +859,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
delete texpr;
|
||||
|
||||
/* We do not currently support constant user function. */
|
||||
need_constant_expr = true;
|
||||
texpr = elab_and_eval(des, scope, port_lsb_, -1);
|
||||
need_constant_expr = false;
|
||||
texpr = elab_and_eval(des, scope, port_lsb_, -1, true);
|
||||
|
||||
if (! eval_as_long(plsb, texpr)) {
|
||||
cerr << port_lsb_->get_fileline() << ": error: "
|
||||
|
|
@ -892,10 +883,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
/* If they exist get the net/etc. definition MSB and LSB */
|
||||
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
|
||||
/* We do not currently support constant user function. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1, true);
|
||||
|
||||
if (! eval_as_long(nmsb, texpr)) {
|
||||
cerr << net_msb_->get_fileline() << ": error: "
|
||||
|
|
@ -909,10 +897,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
delete texpr;
|
||||
|
||||
/* We do not currently support constant user function. */
|
||||
need_constant_expr = true;
|
||||
texpr = elab_and_eval(des, scope, net_lsb_, -1);
|
||||
need_constant_expr = false;
|
||||
texpr = elab_and_eval(des, scope, net_lsb_, -1, true);
|
||||
|
||||
if (! eval_as_long(nlsb, texpr)) {
|
||||
cerr << net_lsb_->get_fileline() << ": error: "
|
||||
|
|
@ -1003,10 +988,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (lidx_ || ridx_) {
|
||||
assert(lidx_ && ridx_);
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1, true);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1, true);
|
||||
|
||||
if ((lexp == 0) || (rexp == 0)) {
|
||||
cerr << get_fileline() << ": internal error: There is "
|
||||
|
|
|
|||
104
elaborate.cc
104
elaborate.cc
|
|
@ -227,10 +227,8 @@ unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
|
|||
gates, then I am expected to make more than one
|
||||
gate. Figure out how many are desired. */
|
||||
if (msb_) {
|
||||
need_constant_expr = true;
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1, true);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1, true);
|
||||
|
||||
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
||||
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
||||
|
|
@ -265,8 +263,8 @@ unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
|
|||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGBuiltin: Make array "
|
||||
<< "[" << high << ":" << low << "]"
|
||||
<< " of " << count << " gates for " << get_name() << endl;
|
||||
<< "[" << high << ":" << low << "]" << " of "
|
||||
<< count << " gates for " << get_name() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -686,8 +684,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
unsigned instance_width = 1;
|
||||
perm_string name = get_name();
|
||||
|
||||
if (name == "")
|
||||
name = scope->local_symbol();
|
||||
if (name == "") name = scope->local_symbol();
|
||||
|
||||
/* Calculate the array bounds and instance count for the gate,
|
||||
as described in the Verilog source. If there is none, then
|
||||
|
|
@ -695,8 +692,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
long low=0, high=0;
|
||||
unsigned array_count = calculate_array_count_(des, scope, high, low);
|
||||
if (array_count == 0)
|
||||
return;
|
||||
if (array_count == 0) return;
|
||||
|
||||
unsigned output_count = calculate_output_count_();
|
||||
|
||||
|
|
@ -1773,6 +1769,62 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
|
||||
}
|
||||
|
||||
unsigned PGModule::calculate_instance_count_(Design*des, NetScope*scope,
|
||||
long&high, long&low,
|
||||
perm_string name) const
|
||||
{
|
||||
unsigned count = 1;
|
||||
high = 0;
|
||||
low = 0;
|
||||
|
||||
/* If the Verilog source has a range specification for the UDP, then
|
||||
* I am expected to make more than one gate. Figure out how many are
|
||||
* desired. */
|
||||
if (msb_) {
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1, true);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1, true);
|
||||
|
||||
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
||||
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
||||
|
||||
if (msb_con == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
"expression " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lsb_con == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
"expression " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum msb = msb_con->value();
|
||||
verinum lsb = lsb_con->value();
|
||||
|
||||
delete msb_exp;
|
||||
delete lsb_exp;
|
||||
|
||||
if (msb.as_long() > lsb.as_long())
|
||||
count = msb.as_long() - lsb.as_long() + 1;
|
||||
else
|
||||
count = lsb.as_long() - msb.as_long() + 1;
|
||||
|
||||
low = lsb.as_long();
|
||||
high = msb.as_long();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGModule: Make range "
|
||||
<< "[" << high << ":" << low << "]" << " of "
|
||||
<< count << " UDPs for " << name << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* From a UDP definition in the source, make a NetUDP
|
||||
* object. Elaborate the pin expressions as netlists, then connect
|
||||
|
|
@ -1803,6 +1855,19 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
|||
}
|
||||
}
|
||||
|
||||
long low = 0, high = 0;
|
||||
unsigned inst_count = calculate_instance_count_(des, scope, high, low,
|
||||
my_name);
|
||||
if (inst_count == 0) return;
|
||||
|
||||
if (inst_count != 1) {
|
||||
cerr << get_fileline() << ": sorry: UDPs with a range ("
|
||||
<< my_name << " [" << high << ":" << low << "]) are "
|
||||
<< "not supported." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(udp);
|
||||
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
|
||||
net->set_line(*this);
|
||||
|
|
@ -2057,9 +2122,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
|||
{
|
||||
ivl_assert(*this, rval_);
|
||||
|
||||
need_constant_expr = is_constant_;
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval());
|
||||
need_constant_expr = false;
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval(),
|
||||
is_constant_);
|
||||
|
||||
if (!is_constant_ || !rv) return rv;
|
||||
|
||||
|
|
@ -3376,7 +3440,8 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
|
|||
|
||||
PExpr::width_mode_t mode;
|
||||
pe->test_width(des, scope, mode);
|
||||
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(), false);
|
||||
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(),
|
||||
PExpr::NO_FLAGS);
|
||||
if (expr == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to elaborate"
|
||||
" wait condition expression." << endl;
|
||||
|
|
@ -3736,6 +3801,11 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (scope->elab_stage() > 2)
|
||||
return;
|
||||
|
||||
scope->set_elab_stage(3);
|
||||
|
||||
NetFuncDef*def = scope->func_def();
|
||||
if (def == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
|
|
@ -3751,6 +3821,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
|||
if (st == 0) {
|
||||
cerr << statement_->get_fileline() << ": error: Unable to elaborate "
|
||||
"statement in function " << scope->basename() << "." << endl;
|
||||
scope->is_const_func(true); // error recovery
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
|
@ -4204,9 +4275,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
|||
for (specparam_it_t cur = specparams.begin()
|
||||
; cur != specparams.end() ; ++ cur ) {
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1,
|
||||
true);
|
||||
NetScope::spec_val_t value;
|
||||
|
||||
if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) {
|
||||
|
|
|
|||
25
eval_tree.cc
25
eval_tree.cc
|
|
@ -1946,12 +1946,29 @@ NetExpr* NetESFunc::eval_tree()
|
|||
|
||||
NetExpr* NetEUFunc::eval_tree()
|
||||
{
|
||||
if (need_constant_expr) {
|
||||
cerr << get_fileline() << ": sorry: constant user "
|
||||
"functions are not currently supported: "
|
||||
<< func_->basename() << "()." << endl;
|
||||
// If we know the function cannot be evaluated as a constant,
|
||||
// give up now.
|
||||
if (!func()->is_const_func())
|
||||
return 0;
|
||||
|
||||
// Variables inside static functions can be accessed from outside
|
||||
// the function, so we can't be sure they are constant unless the
|
||||
// function was called in a constant context.
|
||||
if (!func()->is_auto() && !need_const_)
|
||||
return 0;
|
||||
|
||||
// Run through the input parameters to check they are constants.
|
||||
for (unsigned idx = 0; idx < parm_count(); idx += 1) {
|
||||
if (dynamic_cast<const NetEConst*> (parm(idx)))
|
||||
continue;
|
||||
if (dynamic_cast<const NetECReal*> (parm(idx)))
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (need_const_) {
|
||||
cerr << get_fileline() << ": sorry: Constant user functions are "
|
||||
"not yet supported." << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ CC = @CC@
|
|||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
LEX = @LEX@
|
||||
|
||||
ifeq (@srcdir@,.)
|
||||
INCLUDE_PATH = -I. -I..
|
||||
|
|
@ -69,7 +70,7 @@ ivlpp@EXEEXT@: $O
|
|||
$(CC) $(LDFLAGS) $O -o ivlpp@EXEEXT@ @EXTRALIBS@
|
||||
|
||||
lexor.c: lexor.lex
|
||||
flex -olexor.c $(srcdir)/lexor.lex
|
||||
$(LEX) -olexor.c $(srcdir)/lexor.lex
|
||||
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include "PExpr.h"
|
||||
# include "PTask.h"
|
||||
# include <sstream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
|
@ -332,7 +333,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
|||
/* Evaluate the msb expression, if it is present. */
|
||||
PExpr*msb_expr = (*cur).second.msb_expr;
|
||||
if (msb_expr) {
|
||||
(*cur).second.msb = elab_and_eval(des, this, msb_expr, -1);
|
||||
(*cur).second.msb = elab_and_eval(des, this, msb_expr, -1, true);
|
||||
if (! eval_as_long(msb, (*cur).second.msb)) {
|
||||
cerr << (*cur).second.val->get_fileline()
|
||||
<< ": error: Unable to evaluate msb expression "
|
||||
|
|
@ -348,7 +349,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
|||
/* Evaluate the lsb expression, if it is present. */
|
||||
PExpr*lsb_expr = (*cur).second.lsb_expr;
|
||||
if (lsb_expr) {
|
||||
(*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -1);
|
||||
(*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -1, true);
|
||||
if (! eval_as_long(lsb, (*cur).second.lsb)) {
|
||||
cerr << (*cur).second.val->get_fileline()
|
||||
<< ": error: Unable to evaluate lsb expression "
|
||||
|
|
@ -369,7 +370,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
|||
if (range_flag)
|
||||
lv_width = (msb >= lsb) ? 1 + msb - lsb : 1 + lsb - msb;
|
||||
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width);
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width, true);
|
||||
if (! expr)
|
||||
return;
|
||||
|
||||
|
|
@ -488,7 +489,7 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
|
|||
PExpr*val_expr = (*cur).second.val_expr;
|
||||
NetScope*val_scope = (*cur).second.val_scope;
|
||||
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1);
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true);
|
||||
if (! expr)
|
||||
return;
|
||||
|
||||
|
|
@ -631,14 +632,6 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
|
|||
cur->second.val_expr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the following to true when evaluating the parameter expressions.
|
||||
* This causes PEIdent::elaborate_expr() to report an error if an
|
||||
* identifier in an expression is anything other than a non-hierarchical
|
||||
* parameter name.
|
||||
*/
|
||||
bool is_param_expr = false;
|
||||
|
||||
void NetScope::evaluate_parameters(Design*des)
|
||||
{
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
|
|
@ -649,13 +642,11 @@ void NetScope::evaluate_parameters(Design*des)
|
|||
cerr << ":0" << ": debug: "
|
||||
<< "Evaluate parameters in " << scope_path(this) << endl;
|
||||
|
||||
is_param_expr = true;
|
||||
for (param_ref_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; ++ cur) {
|
||||
|
||||
evaluate_parameter_(des, cur);
|
||||
}
|
||||
is_param_expr = false;
|
||||
}
|
||||
|
||||
void Design::residual_defparams()
|
||||
|
|
@ -730,9 +721,18 @@ NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
|
|||
|
||||
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
|
||||
NetScope*func = find_scope(scope, eval_path, NetScope::FUNC);
|
||||
if (func && (func->type() == NetScope::FUNC))
|
||||
if (func && (func->type() == NetScope::FUNC)) {
|
||||
// If a function is used in a parameter definition or in
|
||||
// a signal declaration, it is possible to get here before
|
||||
// the function's signals have been elaborated. If this is
|
||||
// the case, elaborate them now.
|
||||
if (func->elab_stage() < 2) {
|
||||
const PFunction*pfunc = func->func_pform();
|
||||
assert(pfunc);
|
||||
pfunc->elaborate_sig(this, func);
|
||||
}
|
||||
return func->func_def();
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
|
|||
{
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
need_const_func_ = false;
|
||||
is_const_func_ = false;
|
||||
is_auto_ = false;
|
||||
is_cell_ = false;
|
||||
|
||||
|
|
@ -72,6 +74,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
|
|||
default: /* BEGIN_END and FORK_JOIN, do nothing */
|
||||
break;
|
||||
}
|
||||
func_pform_ = 0;
|
||||
elab_stage_ = 1;
|
||||
lineno_ = 0;
|
||||
def_lineno_ = 0;
|
||||
genvar_tmp_val = 0;
|
||||
|
|
|
|||
|
|
@ -1988,8 +1988,8 @@ const NetExpr* NetSTask::parm(unsigned idx) const
|
|||
}
|
||||
|
||||
NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
|
||||
svector<NetExpr*>&p)
|
||||
: scope_(scope), func_(def), result_sig_(res), parms_(p)
|
||||
svector<NetExpr*>&p, bool nc)
|
||||
: scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc)
|
||||
{
|
||||
expr_width(result_sig_->expr_width());
|
||||
}
|
||||
|
|
|
|||
32
netlist.h
32
netlist.h
|
|
@ -73,6 +73,7 @@ class NetTaskDef;
|
|||
class NetEvTrig;
|
||||
class NetEvWait;
|
||||
class PExpr;
|
||||
class PFunction;
|
||||
class netenum_t;
|
||||
|
||||
struct target;
|
||||
|
|
@ -790,6 +791,29 @@ class NetScope : public Attrib {
|
|||
unsigned get_def_lineno() const { return def_lineno_; };
|
||||
|
||||
bool in_func() const;
|
||||
|
||||
/* Provide a link back to the pform to allow early elaboration of
|
||||
constant functions. */
|
||||
void set_func_pform(const PFunction*pfunc) { func_pform_ = pfunc; };
|
||||
const PFunction*func_pform() const { return func_pform_; };
|
||||
|
||||
/* Allow tracking of elaboration stages. The three stages are:
|
||||
1 - scope elaboration
|
||||
2 - signal elaboration
|
||||
3 - statement elaboration
|
||||
This is only used for functions, to support early elaboration.
|
||||
*/
|
||||
void set_elab_stage(unsigned stage) { elab_stage_ = stage; };
|
||||
unsigned elab_stage() const { return elab_stage_; };
|
||||
|
||||
/* Is this a function called in a constant expression. */
|
||||
void need_const_func(bool need_const) { need_const_func_ = need_const; };
|
||||
bool need_const_func() const { return need_const_func_; };
|
||||
|
||||
/* Is this a constant function. */
|
||||
void is_const_func(bool is_const) { is_const_func_ = is_const; };
|
||||
bool is_const_func() const { return is_const_func_; };
|
||||
|
||||
/* Is the task or function automatic. */
|
||||
void is_auto(bool is_auto__) { is_auto_ = is_auto__; };
|
||||
bool is_auto() const { return is_auto_; };
|
||||
|
|
@ -904,7 +928,6 @@ class NetScope : public Attrib {
|
|||
|
||||
param_ref_t find_parameter(perm_string name);
|
||||
|
||||
|
||||
struct spec_val_t {
|
||||
ivl_variable_type_t type;
|
||||
union {
|
||||
|
|
@ -954,6 +977,8 @@ class NetScope : public Attrib {
|
|||
NetTaskDef*task_;
|
||||
NetFuncDef*func_;
|
||||
};
|
||||
const PFunction*func_pform_;
|
||||
unsigned elab_stage_;
|
||||
|
||||
// Enumerations. The enum_sets_ is a list of all the
|
||||
// enumerations present in this scope. The enum_names_ is a
|
||||
|
|
@ -966,7 +991,7 @@ class NetScope : public Attrib {
|
|||
map<hname_t,NetScope*> children_;
|
||||
|
||||
unsigned lcounter_;
|
||||
bool is_auto_, is_cell_;
|
||||
bool need_const_func_, is_const_func_, is_auto_, is_cell_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3095,7 +3120,7 @@ class NetTaskDef {
|
|||
class NetEUFunc : public NetExpr {
|
||||
|
||||
public:
|
||||
NetEUFunc(NetScope*, NetScope*, NetESignal*, svector<NetExpr*>&);
|
||||
NetEUFunc(NetScope*, NetScope*, NetESignal*, svector<NetExpr*>&, bool);
|
||||
~NetEUFunc();
|
||||
|
||||
const NetESignal*result_sig() const;
|
||||
|
|
@ -3119,6 +3144,7 @@ class NetEUFunc : public NetExpr {
|
|||
NetScope*func_;
|
||||
NetESignal*result_sig_;
|
||||
svector<NetExpr*> parms_;
|
||||
bool need_const_;
|
||||
|
||||
private: // not implemented
|
||||
NetEUFunc(const NetEUFunc&);
|
||||
|
|
|
|||
17
netmisc.cc
17
netmisc.cc
|
|
@ -470,7 +470,8 @@ static const char*width_mode_name(PExpr::width_mode_t mode)
|
|||
}
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
int context_width, bool need_const)
|
||||
{
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
if ((context_width == -2) && !gn_strict_expr_width_flag)
|
||||
|
|
@ -510,7 +511,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
|
|||
}
|
||||
}
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, false);
|
||||
unsigned flags = PExpr::NO_FLAGS;
|
||||
if (need_const)
|
||||
flags |= PExpr::NEED_CONST;
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, flags);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
eval_expr(tmp, context_width);
|
||||
|
|
@ -524,7 +529,7 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
|
|||
}
|
||||
|
||||
NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
||||
unsigned arg_idx, PExpr*pe)
|
||||
unsigned arg_idx, PExpr*pe, bool need_const)
|
||||
{
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
pe->test_width(des, scope, mode);
|
||||
|
|
@ -539,7 +544,11 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
|||
<< ", mode=" << width_mode_name(mode) << endl;
|
||||
}
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, pe->expr_width(), true);
|
||||
unsigned flags = PExpr::SYS_TASK_ARG;
|
||||
if (need_const)
|
||||
flags |= PExpr::NEED_CONST;
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, pe->expr_width(), flags);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
eval_expr(tmp, -1);
|
||||
|
|
|
|||
22
netmisc.h
22
netmisc.h
|
|
@ -134,17 +134,6 @@ extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
|
|||
*/
|
||||
extern unsigned count_lval_width(const class NetAssign_*first);
|
||||
|
||||
/*
|
||||
* This is temporarily used to indicate that a user function elaboration
|
||||
* fail is likely the result of missing constant user function support.
|
||||
*/
|
||||
extern bool need_constant_expr;
|
||||
|
||||
/*
|
||||
* This is used to indicate that we are evaluating a parameter expression.
|
||||
*/
|
||||
extern bool is_param_expr;
|
||||
|
||||
/*
|
||||
* This function elaborates an expression, and tries to evaluate it
|
||||
* right away. If the expression can be evaluated, this returns a
|
||||
|
|
@ -160,14 +149,16 @@ extern bool is_param_expr;
|
|||
class PExpr;
|
||||
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
PExpr*pe, int context_width);
|
||||
PExpr*pe, int context_width,
|
||||
bool need_const =false);
|
||||
|
||||
/*
|
||||
* This function is a variant of elab_and_eval that elaborates and
|
||||
* evaluates the arguments of a system task.
|
||||
*/
|
||||
extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
||||
unsigned arg_idx, PExpr*pe);
|
||||
extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope,
|
||||
perm_string name, unsigned arg_idx,
|
||||
PExpr*pe, bool need_const =false);
|
||||
/*
|
||||
* This function elaborates an expression as if it is for the r-value
|
||||
* of an assignment, The lv_type and lv_width are the type and width
|
||||
|
|
@ -176,7 +167,8 @@ extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
|||
*/
|
||||
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width, PExpr*expr);
|
||||
unsigned lv_width, PExpr*expr,
|
||||
bool need_const =false);
|
||||
|
||||
/*
|
||||
* This procedure evaluates an expression and if the evaluation is
|
||||
|
|
|
|||
30
t-dll-api.cc
30
t-dll-api.cc
|
|
@ -1424,6 +1424,36 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
|||
return net->u_.repeat.count;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.inputs;
|
||||
case IVL_LPM_ABS:
|
||||
case IVL_LPM_CAST_INT:
|
||||
case IVL_LPM_CAST_INT2:
|
||||
case IVL_LPM_CAST_REAL:
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_OR:
|
||||
case IVL_LPM_RE_XOR:
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
case IVL_LPM_FF:
|
||||
return 1;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_POW:
|
||||
case IVL_LPM_SUB:
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
return 2;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -320,6 +320,19 @@ static vhdl_expr *translate_binary(ivl_expr_t e)
|
|||
int rwidth = rhs->get_type()->get_width();
|
||||
int result_width = ivl_expr_width(e);
|
||||
|
||||
// There's a funny corner-case where both the LHS and RHS are constant
|
||||
// single bit numbers and the VHDL compiler can't decide between the
|
||||
// std_ulogic and bit overloads of various operators
|
||||
const bool lnumber = ivl_expr_type(ivl_expr_oper1(e)) == IVL_EX_NUMBER;
|
||||
const bool rnumber = ivl_expr_type(ivl_expr_oper2(e)) == IVL_EX_NUMBER;
|
||||
if (lwidth == 1 && rwidth == 1 && lnumber && rnumber) {
|
||||
// It's sufficient to qualify only one side
|
||||
vhdl_fcall *lqual = new vhdl_fcall("std_logic'", lhs->get_type());
|
||||
lqual->add_expr(lhs);
|
||||
|
||||
lhs = lqual;
|
||||
}
|
||||
|
||||
// For === and !== we need to compare std_logic_vectors
|
||||
// rather than signeds
|
||||
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0);
|
||||
|
|
|
|||
|
|
@ -41,26 +41,6 @@ static vhdl_expr *part_select_base(vhdl_scope *scope, ivl_lpm_t lpm)
|
|||
return off->cast(&integer);
|
||||
}
|
||||
|
||||
static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
||||
{
|
||||
vhdl_type *result_type =
|
||||
vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0);
|
||||
vhdl_binop_expr *expr =
|
||||
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);
|
||||
|
||||
for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) {
|
||||
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||
if (NULL == e) {
|
||||
delete expr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expr->add_expr(e);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t op)
|
||||
{
|
||||
unsigned out_width = ivl_lpm_width(lpm);
|
||||
|
|
@ -68,14 +48,21 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop
|
|||
vhdl_type::type_for(out_width, ivl_lpm_signed(lpm) != 0);
|
||||
vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
|
||||
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||
if (NULL == e) {
|
||||
delete expr;
|
||||
if (NULL == e)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expr->add_expr(e->cast(result_type));
|
||||
// It's possible that the inputs are a mixture of signed and unsigned
|
||||
// in which case we must cast them to the output type
|
||||
e = e->cast(vhdl_type::type_for(e->get_type()->get_width(),
|
||||
ivl_lpm_signed(lpm) != 0));
|
||||
|
||||
// Bit of a hack: the LPM inputs are in the wrong order for concatenation
|
||||
if (op == VHDL_BINOP_CONCAT)
|
||||
expr->add_expr_front(e);
|
||||
else
|
||||
expr->add_expr(e);
|
||||
}
|
||||
|
||||
if (op == VHDL_BINOP_MULT) {
|
||||
|
|
@ -256,7 +243,7 @@ static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
|||
case IVL_LPM_MOD:
|
||||
return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_MOD);
|
||||
case IVL_LPM_CONCAT:
|
||||
return concat_lpm_to_expr(scope, lpm);
|
||||
return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_CONCAT);
|
||||
case IVL_LPM_CMP_GE:
|
||||
return rel_lpm_to_expr(scope, lpm, VHDL_BINOP_GEQ);
|
||||
case IVL_LPM_CMP_GT:
|
||||
|
|
@ -284,7 +271,7 @@ static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
|||
case IVL_LPM_RE_XOR:
|
||||
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, false);
|
||||
case IVL_LPM_RE_XNOR:
|
||||
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, true);
|
||||
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XNOR, true);
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
return sign_extend_lpm_to_expr(scope, lpm);
|
||||
case IVL_LPM_ARRAY:
|
||||
|
|
|
|||
|
|
@ -239,7 +239,16 @@ void draw_nexus(ivl_nexus_t nexus)
|
|||
vhdl_type *type = vhdl_type::type_for(lpm_temp_width,
|
||||
ivl_lpm_signed(lpm) != 0);
|
||||
ostringstream ss;
|
||||
ss << "LPM" << ivl_lpm_basename(lpm);
|
||||
ss << "LPM";
|
||||
if (nexus == ivl_lpm_q(lpm))
|
||||
ss << "_q";
|
||||
else {
|
||||
for (unsigned d = 0; d < ivl_lpm_size(lpm); d++) {
|
||||
if (nexus == ivl_lpm_data(lpm, d))
|
||||
ss << "_d" << d;
|
||||
}
|
||||
}
|
||||
ss << ivl_lpm_basename(lpm);
|
||||
|
||||
if (!vhdl_scope->have_declared(ss.str()))
|
||||
vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type));
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ void support_function::emit(std::ostream &of, int level) const
|
|||
emit_reduction(of, level, "and", '1');
|
||||
break;
|
||||
case SF_REDUCE_XOR:
|
||||
emit_reduction(of, level, "xnor", '0');
|
||||
emit_reduction(of, level, "xor", '0');
|
||||
break;
|
||||
case SF_REDUCE_XNOR:
|
||||
emit_reduction(of, level, "xnor", '0');
|
||||
|
|
|
|||
|
|
@ -940,6 +940,11 @@ void vhdl_binop_expr::add_expr(vhdl_expr *e)
|
|||
operands_.push_back(e);
|
||||
}
|
||||
|
||||
void vhdl_binop_expr::add_expr_front(vhdl_expr *e)
|
||||
{
|
||||
operands_.push_front(e);
|
||||
}
|
||||
|
||||
void vhdl_binop_expr::find_vars(vhdl_var_set_t& read)
|
||||
{
|
||||
for (list<vhdl_expr*>::const_iterator it = operands_.begin();
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ public:
|
|||
~vhdl_binop_expr();
|
||||
|
||||
void add_expr(vhdl_expr *e);
|
||||
void add_expr_front(vhdl_expr *e);
|
||||
void emit(std::ostream &of, int level) const;
|
||||
void find_vars(vhdl_var_set_t& read);
|
||||
private:
|
||||
|
|
|
|||
12
verinum.cc
12
verinum.cc
|
|
@ -1089,15 +1089,17 @@ verinum pow(const verinum&left, const verinum&right)
|
|||
long pow_count = right.as_long();
|
||||
|
||||
// We need positive and negative one in a few places.
|
||||
verinum one (verinum::V0, left.len(), left.has_len());
|
||||
unsigned len = left.len();
|
||||
// Positive one must be at least two bits wide!
|
||||
verinum one (verinum::V0, (len<2) ? 2 : len, left.has_len());
|
||||
one.has_sign(left.has_sign());
|
||||
one.set(0, verinum::V1);
|
||||
verinum m_one (verinum::V1, left.len(), left.has_len());
|
||||
verinum m_one (verinum::V1, len, left.has_len());
|
||||
m_one.has_sign(true);
|
||||
|
||||
// If either the right or left values are undefined we return 'bx.
|
||||
if (!right.is_defined() || !left.is_defined()) {
|
||||
result = verinum(verinum::Vx, left.len(), left.has_len());
|
||||
result = verinum(verinum::Vx, len, left.has_len());
|
||||
result.has_sign(left.has_sign());
|
||||
// If the right value is zero we need to set the result to 1.
|
||||
} else if (pow_count == 0) {
|
||||
|
|
@ -1105,7 +1107,7 @@ verinum pow(const verinum&left, const verinum&right)
|
|||
} else if (pow_count < 0) {
|
||||
// 0 ** <negative> is 'bx.
|
||||
if (left.is_zero()) {
|
||||
result = verinum(verinum::Vx, left.len(), left.has_len());
|
||||
result = verinum(verinum::Vx, len, left.has_len());
|
||||
result.has_sign(left.has_sign());
|
||||
// 1 ** <negative> is 1.
|
||||
} else if (left == one) {
|
||||
|
|
@ -1119,7 +1121,7 @@ verinum pow(const verinum&left, const verinum&right)
|
|||
}
|
||||
// Everything else is 0.
|
||||
} else {
|
||||
result = verinum(verinum::V0, left.len(), left.has_len());
|
||||
result = verinum(verinum::V0, len, left.has_len());
|
||||
result.has_sign(left.has_sign());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class Architecture : public Scope, public LineInfo {
|
|||
|
||||
virtual int elaborate(Entity*ent, Architecture*arc);
|
||||
virtual int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ class Architecture : public Scope, public LineInfo {
|
|||
int emit(ostream&out, Entity*entity);
|
||||
|
||||
// The dump method writes a debug display to the given output.
|
||||
void dump(ostream&out, perm_string of_entity) const;
|
||||
void dump(ostream&out, perm_string of_entity, int indent = 0) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
|
@ -100,7 +100,7 @@ class SignalAssignment : public Architecture::Statement {
|
|||
~SignalAssignment();
|
||||
|
||||
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(ostream&out, int ident =0) const;
|
||||
|
||||
private:
|
||||
ExpName*lval_;
|
||||
|
|
@ -116,7 +116,7 @@ class ComponentInstantiation : public Architecture::Statement {
|
|||
|
||||
virtual int elaborate(Entity*ent, Architecture*arc);
|
||||
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(ostream&out, int indent =0) const;
|
||||
|
||||
private:
|
||||
perm_string iname_;
|
||||
|
|
|
|||
|
|
@ -55,16 +55,16 @@ void dump_design_entities(const char*path)
|
|||
}
|
||||
}
|
||||
|
||||
void ComponentBase::dump_ports(ostream&out) const
|
||||
void ComponentBase::dump_ports(ostream&out, int indent) const
|
||||
{
|
||||
if (ports_.size() == 0) {
|
||||
out << " No ports" << endl;
|
||||
out << setw(indent) << "" << "No ports" << endl;
|
||||
} else {
|
||||
out << " PORTS:" << endl;
|
||||
out << setw(indent) << "" << "PORTS:" << endl;
|
||||
for (vector<InterfacePort*>::const_iterator cur = ports_.begin()
|
||||
; cur != ports_.end() ; ++cur) {
|
||||
InterfacePort*item = *cur;
|
||||
out << setw(6) << "" << item->name
|
||||
out << setw(indent+2) << "" << item->name
|
||||
<< " : " << item->mode
|
||||
<< ", type=";
|
||||
if (item->type)
|
||||
|
|
@ -87,68 +87,68 @@ void Scope::dump_scope(ostream&out) const
|
|||
}
|
||||
}
|
||||
|
||||
void Entity::dump(ostream&out) const
|
||||
void Entity::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << "entity " << get_name()
|
||||
out << setw(indent) << "" << "entity " << get_name()
|
||||
<< " file=" << get_fileline() << endl;
|
||||
dump_ports(out);
|
||||
dump_ports(out, indent+2);
|
||||
|
||||
for (map<perm_string,Architecture*>::const_iterator cur = arch_.begin()
|
||||
; cur != arch_.end() ; ++cur) {
|
||||
cur->second->dump(out, get_name());
|
||||
cur->second->dump(out, get_name(), indent);
|
||||
}
|
||||
}
|
||||
|
||||
void Architecture::dump(ostream&out, perm_string of_entity) const
|
||||
void Architecture::dump(ostream&out, perm_string of_entity, int indent) const
|
||||
{
|
||||
out << "architecture " << name_
|
||||
out << setw(indent) << "" << "architecture " << name_
|
||||
<< " of entity " << of_entity
|
||||
<< " file=" << get_fileline() << endl;
|
||||
|
||||
// Dump signal declarations
|
||||
for (map<perm_string,Signal*>::const_iterator cur = signals_.begin()
|
||||
; cur != signals_.end() ; ++cur) {
|
||||
cur->second->dump(out);
|
||||
cur->second->dump(out, indent+3);
|
||||
}
|
||||
|
||||
dump_scope(out);
|
||||
|
||||
for (list<Architecture::Statement*>::const_iterator cur = statements_.begin()
|
||||
; cur != statements_.end() ; ++cur) {
|
||||
(*cur)->dump(out);
|
||||
(*cur)->dump(out, indent+3);
|
||||
}
|
||||
}
|
||||
|
||||
void Architecture::Statement::dump(ostream&out) const
|
||||
void Architecture::Statement::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << " Architecture::Statement at file=" << get_fileline() << endl;
|
||||
out << setw(indent) << "" << "Architecture::Statement at file=" << get_fileline() << endl;
|
||||
}
|
||||
|
||||
void Signal::dump(ostream&out) const
|
||||
void Signal::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << " signal " << name_ << " is " << *type_ << endl;
|
||||
out << setw(indent) << "" << "signal " << name_ << " is " << *type_ << endl;
|
||||
}
|
||||
|
||||
void SignalAssignment::dump(ostream&out) const
|
||||
void SignalAssignment::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << " SignalAssignment file=" << get_fileline() << endl;
|
||||
lval_->dump(out, 4);
|
||||
out << " <= <expr>..." << endl;
|
||||
out << setw(indent) << "" << "SignalAssignment file=" << get_fileline() << endl;
|
||||
lval_->dump(out, indent+1);
|
||||
out << setw(indent+2) << "" << "<= <expr>..." << endl;
|
||||
|
||||
for (list<Expression*>::const_iterator cur = rval_.begin()
|
||||
; cur != rval_.end() ; ++cur) {
|
||||
(*cur)->dump(out, 5);
|
||||
(*cur)->dump(out, indent+2);
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentInstantiation::dump(ostream&out) const
|
||||
void ComponentInstantiation::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << " Component Instantiation file=" << get_fileline() << endl;
|
||||
out << setw(indent) << "" << "Component Instantiation file=" << get_fileline() << endl;
|
||||
|
||||
for (map<perm_string,Expression*>::const_iterator cur = port_map_.begin()
|
||||
; cur != port_map_.end() ; ++cur) {
|
||||
out << " " << cur->first << " => ..." << endl;
|
||||
cur->second->dump(out, 10);
|
||||
out << setw(indent+2) <<""<< cur->first << " => ..." << endl;
|
||||
cur->second->dump(out, indent+6);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class ComponentBase : public LineInfo {
|
|||
void set_interface(std::list<InterfacePort*>*ports);
|
||||
|
||||
public:
|
||||
void dump_ports(ostream&out) const;
|
||||
void dump_ports(ostream&out, int indent = 0) const;
|
||||
|
||||
protected:
|
||||
// This is really only used by the Entity derived class.
|
||||
|
|
@ -94,7 +94,7 @@ class Entity : public ComponentBase {
|
|||
int elaborate();
|
||||
int emit(ostream&out);
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
std::map<perm_string,Architecture*>arch_;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class Expression : public LineInfo {
|
|||
virtual bool is_primary(void) const;
|
||||
|
||||
// Debug dump of the expression.
|
||||
virtual void dump(ostream&out, int indent) const =0;
|
||||
virtual void dump(ostream&out, int indent = 0) const =0;
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ class ExpUnary : public Expression {
|
|||
|
||||
protected:
|
||||
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump_operand1(ostream&out, int indent) const;
|
||||
void dump_operand1(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
Expression*operand1_;
|
||||
|
|
@ -94,7 +94,7 @@ class ExpBinary : public Expression {
|
|||
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
|
||||
int emit_operand2(ostream&out, Entity*ent, Architecture*arc);
|
||||
|
||||
void dump_operands(ostream&out, int indent) const;
|
||||
void dump_operands(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
Expression*operand1_;
|
||||
|
|
@ -111,7 +111,7 @@ class ExpArithmetic : public ExpBinary {
|
|||
~ExpArithmetic();
|
||||
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump(ostream&out, int indent) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
fun_t fun_;
|
||||
|
|
@ -126,7 +126,7 @@ class ExpInteger : public Expression {
|
|||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
bool is_primary(void) const;
|
||||
bool evaluate(int64_t&val) const;
|
||||
void dump(ostream&out, int indent) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
int64_t value_;
|
||||
|
|
@ -142,7 +142,7 @@ class ExpLogical : public ExpBinary {
|
|||
~ExpLogical();
|
||||
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump(ostream&out, int indent) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
fun_t fun_;
|
||||
|
|
@ -162,7 +162,7 @@ class ExpName : public Expression {
|
|||
public: // Base methods
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
const char* name() const;
|
||||
|
||||
private:
|
||||
|
|
@ -177,7 +177,7 @@ class ExpUAbs : public ExpUnary {
|
|||
~ExpUAbs();
|
||||
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump(ostream&out, int indent) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
};
|
||||
|
||||
class ExpUNot : public ExpUnary {
|
||||
|
|
@ -187,7 +187,7 @@ class ExpUNot : public ExpUnary {
|
|||
~ExpUNot();
|
||||
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump(ostream&out, int indent) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class Signal : public LineInfo {
|
|||
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ LDFLAGS = @LDFLAGS@
|
|||
|
||||
# Object files for system.vpi
|
||||
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
|
||||
sys_finish.o sys_icarus.o sys_plusargs.o sys_random.o sys_random_mti.o \
|
||||
sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o sys_time.o \
|
||||
sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o sys_priv.o sdf_lexor.o \
|
||||
sdf_parse.o stringheap.o vams_simparam.o
|
||||
sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o sys_random.o \
|
||||
sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o sys_sdf.o \
|
||||
sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o sys_priv.o \
|
||||
sdf_lexor.o sdf_parse.o stringheap.o vams_simparam.o
|
||||
OPP = vcd_priv2.o
|
||||
|
||||
ifeq (@HAVE_LIBZ@,yes)
|
||||
|
|
@ -118,12 +118,12 @@ system.vpi: $O $(OPP) ../vvp/libvpi.a
|
|||
$(CXX) @shared@ -o $@ $O $(OPP) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
|
||||
|
||||
sys_readmem_lex.c: sys_readmem_lex.lex
|
||||
flex -t -Preadmem $(srcdir)/sys_readmem_lex.lex > sys_readmem_lex.c
|
||||
$(LEX) -t -Preadmem $(srcdir)/sys_readmem_lex.lex > sys_readmem_lex.c
|
||||
|
||||
sdf_lexor.o: sdf_lexor.c sdf_parse.h
|
||||
|
||||
sdf_lexor.c: sdf_lexor.lex
|
||||
flex -t -Psdf $(srcdir)/sdf_lexor.lex > sdf_lexor.c
|
||||
$(LEX) -t -Psdf $(srcdir)/sdf_lexor.lex > sdf_lexor.c
|
||||
|
||||
sdf_parse.c sdf_parse.h: $(srcdir)/sdf_parse.y
|
||||
$(YACC) --verbose -d -p sdf -o sdf_parse.c $(srcdir)/sdf_parse.y
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2010 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2008-2011 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -190,31 +190,6 @@ void sys_special_register(void)
|
|||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.tfname = "$q_initialize";
|
||||
tf_data.user_data = "$q_initialize";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.tfname = "$q_add";
|
||||
tf_data.user_data = "$q_add";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.tfname = "$q_remove";
|
||||
tf_data.user_data = "$q_remove";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.tfname = "$q_full";
|
||||
tf_data.user_data = "$q_full";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.tfname = "$q_exam";
|
||||
tf_data.user_data = "$q_exam";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
vpip_make_systf_system_defined(res);
|
||||
|
||||
tf_data.tfname = "$dumpports";
|
||||
tf_data.user_data = "$dumpports";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -29,6 +29,7 @@ extern void sys_finish_register();
|
|||
extern void sys_deposit_register();
|
||||
extern void sys_display_register();
|
||||
extern void sys_plusargs_register();
|
||||
extern void sys_queue_register();
|
||||
extern void sys_random_register();
|
||||
extern void sys_random_mti_register();
|
||||
extern void sys_readmem_register();
|
||||
|
|
@ -198,6 +199,7 @@ void (*vlog_startup_routines[])() = {
|
|||
sys_deposit_register,
|
||||
sys_display_register,
|
||||
sys_plusargs_register,
|
||||
sys_queue_register,
|
||||
sys_random_register,
|
||||
sys_random_mti_register,
|
||||
sys_readmem_register,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ $dist_chi_square vpiSysFuncInt
|
|||
$dist_t vpiSysFuncInt
|
||||
$dist_erlang vpiSysFuncInt
|
||||
$clog2 vpiSysFuncInt
|
||||
$q_full vpiSysFuncInt
|
||||
|
||||
$abstime vpiSysFuncReal
|
||||
$simparam vpiSysFuncReal
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -460,11 +460,14 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
return;
|
||||
}
|
||||
|
||||
double ad, bd;
|
||||
double ad, bd, resd;
|
||||
vector4_to_value(op_a_, ad, true);
|
||||
vector4_to_value(op_b_, bd, true);
|
||||
/* 2**-1 and -2**-1 are defined to be zero. */
|
||||
if ((bd == -1) && (fabs(ad) == 2.0)) resd = 0.0;
|
||||
else resd = pow(ad, bd);
|
||||
|
||||
res4 = vvp_vector4_t(wid_, pow(ad, bd));
|
||||
res4 = vvp_vector4_t(wid_, resd);
|
||||
} else {
|
||||
vvp_vector2_t a2 (op_a_);
|
||||
vvp_vector2_t b2 (op_b_);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -81,6 +81,7 @@ static void delete_sub_scopes(struct __vpiScope *scope)
|
|||
case vpiShortIntVar:
|
||||
case vpiIntVar:
|
||||
case vpiByteVar:
|
||||
case vpiBitVar:
|
||||
signal_delete((scope->intern)[idx]);
|
||||
break;
|
||||
case vpiParameter:
|
||||
|
|
|
|||
|
|
@ -4050,10 +4050,13 @@ bool of_POW_S(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
/* Calculate the result using the double pow() function. */
|
||||
double xd, yd;
|
||||
double xd, yd, resd;
|
||||
vector4_to_value(xv, xd, true);
|
||||
vector4_to_value(yv, yd, true);
|
||||
vvp_vector4_t res = vvp_vector4_t(wid, pow(xd, yd));
|
||||
/* 2**-1 and -2**-1 are defined to be zero. */
|
||||
if ((yd == -1.0) && (fabs(xd) == 2.0)) resd = 0.0;
|
||||
else resd = pow(xd, yd);
|
||||
vvp_vector4_t res = vvp_vector4_t(wid, resd);
|
||||
|
||||
/* Copy the result. */
|
||||
for (unsigned jdx = 0; jdx < wid; jdx += 1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue