Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Expression width rework.

This patch is a major rework of expression elaboration and
evaluation in the compiler, aimed at better compliance with
the IEEE standard.
  • Loading branch information...
commit 312b4da46fe94a2af619b3c95f0503334bf19a4e 1 parent 2df6850
@martinwhitaker martinwhitaker authored committed
View
2  Makefile.in
@@ -106,7 +106,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
netenum.o net_event.o net_expr.o net_func.o net_link.o net_modulo.o \
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
- pform_disciplines.o pform_dump.o pform_types.o set_width.o \
+ pform_disciplines.o pform_dump.o pform_types.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \
PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
View
8 PDelays.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
+ * Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -78,11 +78,7 @@ unsigned PDelays::delay_count() const
static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
{
- ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
- bool tmp_flag = false;
- expr->test_width(des, scope, 0, 0, tmp_type, tmp_flag);
- NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
- eval_expr(dex);
+ NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
View
25 PExpr.cc
@@ -1,5 +1,5 @@
/*
- * 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
@@ -31,8 +31,10 @@
PExpr::PExpr()
{
- expr_width_ = 0;
- expr_type_ = IVL_VT_NO_TYPE;
+ expr_type_ = IVL_VT_NO_TYPE;
+ expr_width_ = 0;
+ min_width_ = 0;
+ signed_flag_ = false;
}
PExpr::~PExpr()
@@ -94,8 +96,8 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
- left_width_ = 0;
- right_width_ = 0;
+ l_width_ = 0;
+ r_width_ = 0;
}
PEBComp::~PEBComp()
@@ -204,13 +206,16 @@ bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
}
PEConcat::PEConcat(const list<PExpr*>&p, PExpr*r)
-: parms_(p.size()), tested_widths_(p.size()), repeat_(r)
+: parms_(p.size()), width_modes_(p.size()), repeat_(r)
{
int tmp_idx = 0;
assert(parms_.size() == p.size());
for (list<PExpr*>::const_iterator idx = p.begin()
; idx != p.end() ; ++idx)
parms_[tmp_idx++] = *idx;
+
+ tested_scope_ = 0;
+ repeat_count_ = 1;
}
PEConcat::~PEConcat()
@@ -437,3 +442,11 @@ bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
assert(expr_);
return expr_->has_aa_term(des, scope);
}
+
+PEVoid::PEVoid()
+{
+}
+
+PEVoid::~PEVoid()
+{
+}
View
260 PExpr.h
@@ -1,7 +1,7 @@
#ifndef __PExpr_H
#define __PExpr_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
@@ -43,6 +43,8 @@ class NetScope;
class PExpr : public LineInfo {
public:
+ enum width_mode_t { SIZED, EXPAND, LOSSLESS, UNSIZED };
+
PExpr();
virtual ~PExpr();
@@ -62,53 +64,65 @@ class PExpr : public LineInfo {
// references to automatically allocated variables.
virtual bool has_aa_term(Design*des, NetScope*scope) const;
- // This method tests the width that the expression wants to
- // be. It is used by elaboration of assignments to figure out
- // the width of the expression.
- //
- // The "min" is the width of the local context, so is the
- // minimum width that this function should return. Initially
- // this is the same as the lval width.
+ // This method tests the type and width that the expression wants
+ // to be. It should be called before elaborating an expression to
+ // figure out the type and width of the expression. It also figures
+ // out the minimum width that can be used to evaluate the expression
+ // without changing the result. This allows the expression width to
+ // be pruned when not all bits of the result are used.
//
- // The "lval" is the width of the destination where this
- // result is going to go. This can be used to constrain the
- // amount that an expression can reasonably expand. For
- // example, there is no point expanding an addition to beyond
- // the lval. This extra bit of information allows the
- // expression to optimize itself a bit. If the lval==0, then
- // the subexpression should not make l-value related
- // optimizations.
+ // Normally mode should be initialised to SIZED before starting to
+ // test the width of an expression. In SIZED mode the expression
+ // width will be calculated strictly according to the IEEE standard
+ // rules for expression width.
+ // If the expression contains an unsized literal, mode will be
+ // changed to LOSSLESS. In LOSSLESS mode the expression width will
+ // be calculated as the minimum width necessary to avoid arithmetic
+ // overflow or underflow.
+ // If the expression both contains an unsized literal and contains
+ // an operation that coerces a vector operand to a different type
+ // (signed <-> unsigned), mode is changed to UNSIZED. UNSIZED mode
+ // is the same as LOSSLESS, except that the final expression width
+ // will be forced to be at least integer_width. This is necessary
+ // to ensure compatibility with the IEEE standard, which requires
+ // unsized literals to be treated as having the same width as an
+ // integer. The lossless width calculation is inadequate in this
+ // case because coercing an operand to a different type means that
+ // the expression no longer obeys the normal rules of arithmetic.
//
- // The expr_type is an output argument that gives the
- // calculated type for the expression.
+ // If mode is initialised to EXPAND instead of SIZED, the expression
+ // width will be calculated as the minimum width necessary to avoid
+ // arithmetic overflow or underflow, even if it contains no unsized
+ // literals. mode will be changed LOSSLESS or UNSIZED as described
+ // above. This supports a non-standard mode of expression width
+ // calculation.
//
- // The unsized_flag is set to true if the expression is
- // unsized and therefore expandable. This happens if a
- // sub-expression is an unsized literal. Some expressions make
- // special use of that.
- virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ // When the final value of mode is UNSIZED, the width returned by
+ // this method is the calculated lossless width, but the width
+ // returned by a subsequent call to the expr_width method will be
+ // the final expression width.
+ virtual unsigned test_width(Design*des, NetScope*scope,
+ width_mode_t&mode);
// After the test_width method is complete, these methods
// return valid results.
ivl_variable_type_t expr_type() const { return expr_type_; }
unsigned expr_width() const { return expr_width_; }
+ unsigned min_width() const { return min_width_; }
+ bool has_sign() const { return signed_flag_; }
+
+ // This method allows the expression type (signed/unsigned)
+ // to be propagated down to any context-dependant operands.
+ void cast_signed(bool flag) { signed_flag_ = flag; }
// Procedural elaboration of the expression. The expr_width is
- // the width of the context of the expression (i.e. the
- // l-value width of an assignment),
- //
- // ... or -1 if the expression is self-determined. or
- // ... or -2 if the expression is losslessly
- // self-determined. This can happen in situations where the
- // result is going to a pseudo-infinitely wide context.
+ // the required width of the expression.
//
// The sys_task_arg flag is true if expressions are allowed to
// be incomplete.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid,
+ bool sys_task_arg) const;
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
@@ -140,9 +154,13 @@ class PExpr : public LineInfo {
virtual bool is_the_same(const PExpr*that) const;
protected:
+ unsigned fix_width_(width_mode_t mode);
+
// The derived class test_width methods should fill these in.
ivl_variable_type_t expr_type_;
unsigned expr_width_;
+ unsigned min_width_;
+ bool signed_flag_;
private: // not implemented
PExpr(const PExpr&);
@@ -165,14 +183,13 @@ class PEConcat : public PExpr {
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid,
+ bool sys_task_arg) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
@@ -181,9 +198,11 @@ class PEConcat : public PExpr {
bool bidirectional_flag) const;
private:
vector<PExpr*>parms_;
- std::valarray<unsigned>tested_widths_;
+ std::valarray<width_mode_t>width_modes_;
PExpr*repeat_;
+ NetScope*tested_scope_;
+ unsigned repeat_count_;
};
/*
@@ -232,11 +251,10 @@ class PEFNumber : public PExpr {
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid,
+ bool sys_task_arg) const;
virtual void dump(ostream&) const;
@@ -262,9 +280,7 @@ class PEIdent : public PExpr {
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
@@ -277,7 +293,8 @@ class PEIdent : public PExpr {
bool is_force) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid,
+ bool sys_task_arg) const;
// Elaborate the PEIdent as a port to a module. This method
// only applies to Ident expressions.
@@ -326,13 +343,14 @@ class PEIdent : public PExpr {
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb,
- int expr_wid) const;
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_param_part_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
- const NetExpr*par_lsb) const;
+ const NetExpr*par_lsb,
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_param_idx_up_(Design*des,
NetScope*scope,
const NetExpr*par,
@@ -349,28 +367,31 @@ class PEIdent : public PExpr {
NetScope*scope,
NetNet*net,
NetScope*found,
+ unsigned expr_wid,
bool sys_task_arg) const;
NetExpr*elaborate_expr_net_word_(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
+ unsigned expr_wid,
bool sys_task_arg) const;
NetExpr*elaborate_expr_net_part_(Design*des,
- NetScope*scope,
- NetESignal*net,
- NetScope*found) const;
+ NetScope*scope,
+ NetESignal*net,
+ NetScope*found,
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_net_idx_up_(Design*des,
- NetScope*scope,
- NetESignal*net,
- NetScope*found) const;
+ NetScope*scope,
+ NetESignal*net,
+ NetScope*found) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
- NetScope*scope,
- NetESignal*net,
- NetScope*found) const;
+ NetScope*scope,
+ NetESignal*net,
+ NetScope*found) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
- NetScope*scope,
- NetESignal*net,
- NetScope*found) const;
+ NetScope*scope,
+ NetESignal*net,
+ NetScope*found) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
@@ -390,12 +411,10 @@ class PENumber : public PExpr {
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
- int expr_width, bool) const;
+ unsigned expr_wid, bool) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
@@ -425,12 +444,10 @@ class PEString : public PExpr {
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
- int expr_width, bool) const;
+ unsigned expr_wid, bool) const;
verinum* eval_const(Design*, NetScope*) const;
private:
@@ -450,16 +467,15 @@ class PEUnary : public PExpr {
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid,
+ bool sys_task_arg) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
private:
- NetExpr* elaborate_expr_bits_(NetExpr*operand, int expr_wid) const;
+ NetExpr* elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const;
private:
char op_;
@@ -479,12 +495,11 @@ class PEBinary : public PExpr {
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid,
+ bool sys_task_arg) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
protected:
@@ -493,22 +508,22 @@ class PEBinary : public PExpr {
PExpr*right_;
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp,
- int use_wid) const;
+ unsigned expr_wid) const;
NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp,
- int use_wid) const;
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_base_bits_(Design*, NetExpr*lp, NetExpr*rp,
- int use_wid) const;
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_base_div_(Design*, NetExpr*lp, NetExpr*rp,
- int use_wid) const;
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_base_lshift_(Design*, NetExpr*lp, NetExpr*rp,
- int use_wid) const;
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_base_rshift_(Design*, NetExpr*lp, NetExpr*rp,
- int use_wid) const;
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_base_mult_(Design*, NetExpr*lp, NetExpr*rp,
- int use_wid) const;
+ unsigned expr_wid) const;
NetExpr*elaborate_expr_base_add_(Design*, NetExpr*lp, NetExpr*rp,
- int use_wid) const;
+ unsigned expr_wid) const;
};
@@ -523,16 +538,14 @@ class PEBComp : public PEBinary {
~PEBComp();
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&flag);
+ width_mode_t&mode);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid, bool sys_task_arg) const;
private:
- int left_width_;
- int right_width_;
+ unsigned l_width_;
+ unsigned r_width_;
};
/*
@@ -545,12 +558,10 @@ class PEBLogic : public PEBinary {
~PEBLogic();
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&flag);
+ width_mode_t&mode);
NetExpr* elaborate_expr(Design*des, NetScope*scope,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid, bool sys_task_arg) const;
};
/*
@@ -565,17 +576,15 @@ class PEBLeftWidth : public PEBinary {
~PEBLeftWidth() =0;
virtual NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
- int expr_wid) const =0;
+ unsigned expr_wid) const =0;
protected:
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&flag);
+ width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
- int expr_width, bool sys_task_arg) const;
-
+ unsigned expr_wid,
+ bool sys_task_arg) const;
};
class PEBPower : public PEBLeftWidth {
@@ -585,7 +594,7 @@ class PEBPower : public PEBLeftWidth {
~PEBPower();
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
- int expr_wid) const;
+ unsigned expr_wid) const;
};
class PEBShift : public PEBLeftWidth {
@@ -595,7 +604,7 @@ class PEBShift : public PEBLeftWidth {
~PEBShift();
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
- int expr_wid) const;
+ unsigned expr_wid) const;
};
/*
@@ -615,17 +624,16 @@ class PETernary : public PExpr {
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
- int expr_width, bool sys_task_arg) const;
+ unsigned expr_wid,
+ bool sys_task_arg) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
private:
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
- PExpr*expr, int use_wid) const;
+ PExpr*expr, unsigned expr_wid) const;
private:
PExpr*expr_;
@@ -658,12 +666,11 @@ class PECallFunction : public PExpr {
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
- int expr_wid, bool sys_task_arg) const;
+ unsigned expr_wid,
+ bool sys_task_arg) const;
virtual unsigned test_width(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
private:
pform_name_t path_;
@@ -671,14 +678,29 @@ class PECallFunction : public PExpr {
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
- NetExpr* cast_to_width_(NetExpr*expr, int wid, bool signed_flag) const;
+ NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
- NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
- NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t) const;
+ NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
+ unsigned expr_wid) const;
+ NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t,
+ unsigned expr_wid) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
- unsigned min, unsigned lval,
- ivl_variable_type_t&expr_type,
- bool&unsized_flag);
+ width_mode_t&mode);
+};
+
+/*
+ * This class is used for error recovery. All methods do nothing and return
+ * null or default values.
+ */
+class PEVoid : public PExpr {
+
+ public:
+ explicit PEVoid();
+ ~PEVoid();
+
+ virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
+ unsigned expr_wid,
+ bool sys_task_arg) const;
};
#endif
View
8 design_dump.cc
@@ -1396,12 +1396,8 @@ void NetEBinary::dump(ostream&o) const
void NetEConcat::dump(ostream&o) const
{
- if (repeat_calculated_) {
- if (repeat_value_ != 1)
- o << repeat_value_;
- } else if (repeat_) {
- o << "<" << *repeat_ << ">";
- }
+ if (repeat_ != 1)
+ o << repeat_;
if (parms_[0])
o << "{" << *parms_[0];
View
144 dup_expr.cc
@@ -32,19 +32,103 @@ NetEAccess* NetEAccess::dup_expr() const
return tmp;
}
+NetEBinary* NetEBinary::dup_expr() const
+{
+ ivl_assert(*this, 0);
+ return 0;
+}
+
+NetEBAdd* NetEBAdd::dup_expr() const
+{
+ NetEBAdd*tmp = new NetEBAdd(op_, left_->dup_expr(), right_->dup_expr(),
+ expr_width(), has_sign());
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
+
+NetEBBits* NetEBBits::dup_expr() const
+{
+ NetEBBits*tmp = new NetEBBits(op_, left_->dup_expr(), right_->dup_expr(),
+ expr_width(), has_sign());
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
+
NetEBComp* NetEBComp::dup_expr() const
{
- NetEBComp*tmp = new NetEBComp(op_, left_->dup_expr(),
- right_->dup_expr());
- assert(tmp);
+ NetEBComp*tmp = new NetEBComp(op_, left_->dup_expr(), right_->dup_expr());
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
+
+NetEBDiv* NetEBDiv::dup_expr() const
+{
+ NetEBDiv*tmp = new NetEBDiv(op_, left_->dup_expr(), right_->dup_expr(),
+ expr_width(), has_sign());
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
+
+NetEBLogic* NetEBLogic::dup_expr() const
+{
+ NetEBLogic*tmp = new NetEBLogic(op_, left_->dup_expr(), right_->dup_expr());
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
+NetEBMult* NetEBMult::dup_expr() const
+{
+ NetEBMult*tmp = new NetEBMult(op_, left_->dup_expr(), right_->dup_expr(),
+ expr_width(), has_sign());
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
+
+NetEBPow* NetEBPow::dup_expr() const
+{
+ NetEBPow*tmp = new NetEBPow(op_, left_->dup_expr(), right_->dup_expr(),
+ expr_width(), has_sign());
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
+
+NetEBShift* NetEBShift::dup_expr() const
+{
+ NetEBShift*tmp = new NetEBShift(op_, left_->dup_expr(), right_->dup_expr(),
+ expr_width(), has_sign());
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
+
+NetEConcat* NetEConcat::dup_expr() const
+{
+ NetEConcat*dup = new NetEConcat(parms_.count(), repeat_);
+ ivl_assert(*this, dup);
+ dup->set_line(*this);
+ for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
+ if (parms_[idx]) {
+ NetExpr*tmp = parms_[idx]->dup_expr();
+ ivl_assert(*this, tmp);
+ dup->parms_[idx] = tmp;
+ }
+
+ dup->expr_width(expr_width());
+
+ return dup;
+}
+
NetEConst* NetEConst::dup_expr() const
{
NetEConst*tmp = new NetEConst(value_);
- assert(tmp);
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
@@ -52,7 +136,7 @@ NetEConst* NetEConst::dup_expr() const
NetEConstEnum* NetEConstEnum::dup_expr() const
{
NetEConstEnum*tmp = new NetEConstEnum(scope_, name_, enum_set_, value());
- assert(tmp);
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
@@ -60,7 +144,15 @@ NetEConstEnum* NetEConstEnum::dup_expr() const
NetEConstParam* NetEConstParam::dup_expr() const
{
NetEConstParam*tmp = new NetEConstParam(scope_, name_, value());
- assert(tmp);
+ ivl_assert(*this, tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
+
+NetECReal* NetECReal::dup_expr() const
+{
+ NetECReal*tmp = new NetECReal(value_);
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
@@ -68,26 +160,26 @@ NetEConstParam* NetEConstParam::dup_expr() const
NetECRealParam* NetECRealParam::dup_expr() const
{
NetECRealParam*tmp = new NetECRealParam(scope_, name_, value());
- assert(tmp);
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEEvent* NetEEvent::dup_expr() const
{
- assert(0);
+ ivl_assert(*this, 0);
return 0;
}
NetENetenum* NetENetenum::dup_expr() const
{
- assert(0);
+ ivl_assert(*this, 0);
return 0;
}
NetEScope* NetEScope::dup_expr() const
{
- assert(0);
+ ivl_assert(*this, 0);
return 0;
}
@@ -96,7 +188,7 @@ NetESelect* NetESelect::dup_expr() const
NetESelect*tmp = new NetESelect(expr_->dup_expr(),
base_? base_->dup_expr() : 0,
expr_width(), sel_type_);
- assert(tmp);
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
@@ -104,11 +196,11 @@ NetESelect* NetESelect::dup_expr() const
NetESFunc* NetESFunc::dup_expr() const
{
NetESFunc*tmp = new NetESFunc(name_, type_, expr_width(), nparms());
- assert(tmp);
+ ivl_assert(*this, tmp);
tmp->cast_signed(has_sign());
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
- assert(parm(idx));
+ ivl_assert(*this, parm(idx));
tmp->parm(idx, parm(idx)->dup_expr());
}
@@ -119,7 +211,7 @@ NetESFunc* NetESFunc::dup_expr() const
NetESignal* NetESignal::dup_expr() const
{
NetESignal*tmp = new NetESignal(net_, word_);
- assert(tmp);
+ ivl_assert(*this, tmp);
tmp->expr_width(expr_width());
tmp->set_line(*this);
return tmp;
@@ -129,8 +221,10 @@ NetETernary* NetETernary::dup_expr() const
{
NetETernary*tmp = new NetETernary(cond_->dup_expr(),
true_val_->dup_expr(),
- false_val_->dup_expr());
- assert(tmp);
+ false_val_->dup_expr(),
+ expr_width(),
+ has_sign());
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
@@ -141,29 +235,29 @@ NetEUFunc* NetEUFunc::dup_expr() const
svector<NetExpr*> tmp_parms (parms_.count());
for (unsigned idx = 0 ; idx < tmp_parms.count() ; idx += 1) {
- assert(parms_[idx]);
+ ivl_assert(*this, parms_[idx]);
tmp_parms[idx] = parms_[idx]->dup_expr();
}
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms);
- assert(tmp);
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEUBits* NetEUBits::dup_expr() const
{
- NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr());
- assert(tmp);
+ NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr(), expr_width(), has_sign());
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEUnary* NetEUnary::dup_expr() const
{
- NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
- assert(tmp);
+ NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr(), expr_width(), has_sign());
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
@@ -171,15 +265,15 @@ NetEUnary* NetEUnary::dup_expr() const
NetEUReduce* NetEUReduce::dup_expr() const
{
NetEUReduce*tmp = new NetEUReduce(op_, expr_->dup_expr());
- assert(tmp);
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetECast* NetECast::dup_expr() const
{
- NetECast*tmp = new NetECast(op_, expr_->dup_expr());
- assert(tmp);
+ NetECast*tmp = new NetECast(op_, expr_->dup_expr(), expr_width(), has_sign());
+ ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
View
1,869 elab_expr.cc
787 additions, 1,082 deletions not shown
View
20 elab_lval.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
+ * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -255,12 +255,6 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
ivl_assert(*this, index_head.msb != 0);
ivl_assert(*this, index_head.lsb == 0);
- // These are not used, but they need to have a default value.
- ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
- bool unsized_flag_tmp = false;
- index_head.msb->test_width(des, scope, integer_width, integer_width,
- expr_type_tmp, unsized_flag_tmp);
-
NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
// If there is a non-zero base to the memory, then build an
@@ -335,12 +329,6 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
NetNet*reg = lv->sig();
- // These are not used, but they need to have a default value.
- ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
- bool unsized_flag_tmp = false;
- index_tail.msb->test_width(des, scope, integer_width, integer_width,
- expr_type_tmp, unsized_flag_tmp);
-
// Bit selects have a single select expression. Evaluate the
// constant value and treat it as a part select with a bit
// width of 1.
@@ -463,12 +451,6 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
unsigned long wid;
calculate_up_do_width_(des, scope, wid);
- // These are not used, but they need to have a default value.
- ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
- bool unsized_flag_tmp = false;
- index_tail.msb->test_width(des, scope, integer_width, integer_width,
- expr_type_tmp, unsized_flag_tmp);
-
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
ivl_select_type_t sel_type = IVL_SEL_OTHER;
View
12 elab_net.cc
@@ -198,12 +198,6 @@ 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: {
- // These are not used, but they need to have a default value.
- ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
- bool unsized_flag_tmp = false;
- index_tail.msb->test_width(des, scope,
- integer_width, integer_width,
- expr_type_tmp, unsized_flag_tmp);
need_constant_expr = true;
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
need_constant_expr = false;
@@ -477,12 +471,6 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
}
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
- // These are not used, but they need to have a default value.
- ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
- bool unsized_flag_tmp = false;
- index_head.msb->test_width(des, scope,
- integer_width, integer_width,
- expr_type_tmp, unsized_flag_tmp);
need_constant_expr = true;
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
need_constant_expr = false;
View
18 elab_scope.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
+ * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -61,7 +61,6 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
tmp->high_open_flag = range->high_open_flag;
if (range->low_expr) {
- probe_expr_width(des, scope, range->low_expr);
tmp->low_expr = elab_and_eval(des, scope, range->low_expr, -1);
ivl_assert(*range->low_expr, tmp->low_expr);
} else {
@@ -78,7 +77,6 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
tmp->high_expr = tmp->low_expr;
} else if (range->high_expr) {
- probe_expr_width(des, scope, range->high_expr);
tmp->high_expr = elab_and_eval(des, scope, range->high_expr, -1);
ivl_assert(*range->high_expr, tmp->high_expr);
} else {
@@ -136,8 +134,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
{
bool rc_flag;
assert(enum_type->range->size() == 2);
- NetExpr*msb_ex = enum_type->range->front()->elaborate_expr(des, scope, -2, false);
- NetExpr*lsb_ex = enum_type->range->back() ->elaborate_expr(des, scope, -2, false);
+ NetExpr*msb_ex = elab_and_eval(des, scope, enum_type->range->front(), -1);
+ NetExpr*lsb_ex = elab_and_eval(des, scope, enum_type->range->back(), -1);
long msb = 0;
rc_flag = eval_as_long(msb, msb_ex);
@@ -162,7 +160,6 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
// There is an explicit value. elaborate/evaluate
// the value and assign it to the enumeration name.
NetExpr*val = elab_and_eval(des, scope, cur->parm,
- use_enum->base_width(),
use_enum->base_width());
NetEConst*val_const = dynamic_cast<NetEConst*> (val);
if (val_const == 0) {
@@ -557,7 +554,6 @@ 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.
- probe_expr_width(des, container, loop_init);
need_constant_expr = true;
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
need_constant_expr = false;
@@ -624,7 +620,6 @@ 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;
- probe_expr_width(des, container, loop_test);
need_constant_expr = true;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
@@ -673,7 +668,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
elaborate_subscope_(des, scope);
// Calculate the step for the loop variable.
- probe_expr_width(des, container, loop_step);
need_constant_expr = true;
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
need_constant_expr = false;
@@ -692,7 +686,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
delete step;
delete test_ex;
- probe_expr_width(des, container, loop_test);
test_ex = elab_and_eval(des, container, loop_test, -1);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
@@ -707,7 +700,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
{
- probe_expr_width(des, container, loop_test);
need_constant_expr = true;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
@@ -800,7 +792,6 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
{
- probe_expr_width(des, container, loop_test);
need_constant_expr = true;
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
need_constant_expr = false;
@@ -833,7 +824,6 @@ 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 ) {
- probe_expr_width(des, container, item->item_test[idx]);
need_constant_expr = true;
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
need_constant_expr = false;
@@ -1206,8 +1196,6 @@ 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
{
- if (msb_) probe_expr_width(des, sc, msb_);
- if (lsb_) probe_expr_width(des, sc, lsb_);
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;
View
13 elab_sig.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
+ * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -471,8 +471,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_REG_S:
if (return_type_.range) {
ivl_assert(*this, return_type_.range->size() == 2);
- probe_expr_width(des, scope, return_type_.range->at(0));
- probe_expr_width(des, scope, return_type_.range->at(1));
need_constant_expr = true;
NetExpr*me = elab_and_eval(des, scope,
@@ -545,8 +543,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_ATOM2:
case PTF_ATOM2_S:
ivl_assert(*this, return_type_.range != 0);
- probe_expr_width(des, scope, (*return_type_.range)[0]);
- probe_expr_width(des, scope, (*return_type_.range)[1]);
long use_wid;
{
need_constant_expr = true;
@@ -852,7 +848,6 @@ 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) {
- probe_expr_width(des, scope, port_msb_);
/* We do not currently support constant user function. */
need_constant_expr = true;
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
@@ -870,7 +865,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr;
- probe_expr_width(des, scope, port_lsb_);
/* We do not currently support constant user function. */
need_constant_expr = true;
texpr = elab_and_eval(des, scope, port_lsb_, -1);
@@ -898,7 +892,6 @@ 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) {
- probe_expr_width(des, scope, net_msb_);
/* We do not currently support constant user function. */
need_constant_expr = true;
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
@@ -916,7 +909,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr;
- probe_expr_width(des, scope, net_lsb_);
/* We do not currently support constant user function. */
need_constant_expr = true;
texpr = elab_and_eval(des, scope, net_lsb_, -1);
@@ -1011,9 +1003,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (lidx_ || ridx_) {
assert(lidx_ && ridx_);
- probe_expr_width(des, scope, lidx_);
- probe_expr_width(des, scope, ridx_);
-
need_constant_expr = true;
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
View
169 elaborate.cc
@@ -115,6 +115,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
cerr << get_fileline() << ": debug: PGAssign: elaborated r-value"
<< " width="<< rval->vector_width()
<< ", type="<< rval->data_type()
+ << ", signed="<< rval->get_signed()
<< ", expr=" << *rval_expr << endl;
}
@@ -227,11 +228,6 @@ unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
gate. Figure out how many are desired. */
if (msb_) {
need_constant_expr = true;
- ivl_variable_type_t use_type;
- bool flag = false;
- msb_->test_width(des, scope, 0, 0, use_type, flag);
- flag = false;
- lsb_->test_width(des, scope, 0, 0, use_type, flag);
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
need_constant_expr = false;
@@ -820,12 +816,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
sig = lval_sigs[idx];
} else {
- unsigned use_width = array_count * instance_width;
- ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
- bool flag = false;
- ex->test_width(des, scope, 0, use_width, tmp_type, flag);
- NetExpr*tmp = elab_and_eval(des, scope, ex,
- use_width, use_width);
+ NetExpr*tmp = elab_and_eval(des, scope, ex, -1);
sig = tmp->synthesize(des, scope, tmp);
delete tmp;
}
@@ -1332,13 +1323,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
port is actually empty on the inside. We assume
in that case that the port is input. */
- ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
- bool flag = false;
- pins[idx]->test_width(des, scope, 0, desired_vector_width,
- tmp_type, flag);
- NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx],
- desired_vector_width,
- desired_vector_width);
+ NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx], -1);
if (tmp_expr == 0) {
cerr << pins[idx]->get_fileline()
<< ": internal error: Port expression "
@@ -1891,7 +1876,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
if (pins[idx] == 0)
continue;
- NetExpr*expr_tmp = elab_and_eval(des, scope, pins[idx], 1, 1);
+ NetExpr*expr_tmp = elab_and_eval(des, scope, pins[idx], 1);
if (expr_tmp == 0) {
cerr << "internal error: Expression too complicated "
"for elaboration:" << *pins[idx] << endl;
@@ -2046,7 +2031,6 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
*/
static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
{
- probe_expr_width(des, scope, expr);
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based
@@ -2101,12 +2085,11 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
NetExpr*scal_val = new NetECReal(verireal(round));
scal_val->set_line(*expr);
- dex = new NetEBMult('*', dex, scal_val);
+ dex = new NetEBMult('*', dex, scal_val, 1, true);
dex->set_line(*expr);
// Cast this part of the expression to an integer.
- dex = new NetECast('i', dex);
- dex->set_width(64);
+ dex = new NetECast('i', dex, 64, false);
dex->set_line(*expr);
// Now scale the integer value.
@@ -2117,8 +2100,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
scal_val = new NetEConst(verinum(scale, 64));
scal_val->set_line(*expr);
- dex = new NetEBMult('*', dex, scal_val);
- dex->set_width(64);
+ dex = new NetEBMult('*', dex, scal_val, 64, false);
dex->set_line(*expr);
} else {
int shift = scope->time_unit() - des->get_precision();
@@ -2128,7 +2110,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
NetExpr*scal_val = new NetEConst(verinum(scale, 64));
scal_val->set_line(*expr);
- dex = new NetEBMult('*', dex, scal_val);
+ dex = new NetEBMult('*', dex, scal_val, 64, false);
dex->set_line(*expr);
}
@@ -2176,17 +2158,6 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
if (delay || event_) {
unsigned wid = count_lval_width(lv);
- rv->set_width(wid);
- rv = pad_to_width(rv, wid, *this);
-
- if (wid > rv->expr_width()) {
- cerr << get_fileline() << ": error: Unable to match "
- "expression width of " << rv->expr_width() <<
- " to l-value width of " << wid << "." << endl;
- //XXXX delete rv;
- return 0;
- }
-
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::REG, wid);
tmp->local_flag(true);
@@ -2276,22 +2247,6 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
return bl;
}
- /* Based on the specific type of the l-value, do cleanup
- processing on the r-value. */
- if (rv->expr_type() == IVL_VT_REAL) {
-
- // The r-value is a real. Casting will happen in the
- // code generator, so leave it.
-
- } else {
- unsigned wid = count_lval_width(lv);
- if (wid > rv->expr_width()) {
- rv->set_width(wid);
- rv = pad_to_width(rv, wid, *this);
- }
- ivl_assert(*this, rv->expr_width() >= wid);
- }
-
if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: Cast expression to int2" << endl;
@@ -2342,20 +2297,6 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
if (rv == 0) return 0;
- /* Handle the (common) case that the r-value is a vector. This
- includes just about everything but reals. In this case, we
- need to pad the r-value to match the width of the l-value.
-
- If in this case the l-val is a variable (i.e., real) then
- the width to pad to will be 0, so this code is harmless. */
- if (rv->expr_type() == IVL_VT_REAL) {
-
- } else {
- unsigned wid = count_lval_width(lv);
- rv->set_width(wid);
- rv = pad_to_width(rv, wid, *this);
- }
-
NetExpr*delay = 0;
if (delay_ != 0) {
assert(count_ == 0 && event_ == 0);
@@ -2507,7 +2448,6 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
- probe_expr_width(des, scope, expr_);
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {
cerr << get_fileline() << ": error: Unable to elaborate this case"
@@ -2562,7 +2502,6 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
NetExpr*gu = 0;
NetProc*st = 0;
assert(cur_expr);
- probe_expr_width(des, scope, cur_expr);
gu = elab_and_eval(des, scope, cur_expr, -1);
if (cur->stat)
@@ -2585,7 +2524,6 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
<< " with conditional: " << *expr_ << endl;
// Elaborate and try to evaluate the conditional expression.
- probe_expr_width(des, scope, expr_);
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {
cerr << get_fileline() << ": error: Unable to elaborate"
@@ -2701,29 +2639,12 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
svector<NetExpr*>eparms (parm_count);
+ perm_string name = peek_tail_name(path_);
+
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
PExpr*ex = parm(idx);
if (ex != 0) {
- ivl_variable_type_t use_type;
- bool flag = false;
- int use_wid = ex->test_width(des,scope,0,0, use_type, flag);
- if (debug_elaborate)
- cerr << ex->get_fileline() << ": debug: "
- << "Argument " << (idx+1)
- << " of system task tests its width as " << use_wid
- << ", type=" << use_type
- << ", unsized_flag=" << flag << endl;
-
- // If the argument expression is unsized, then
- // elaborate as self-determined *lossless* instead
- // of sized.
- if (flag==true)
- use_wid = -2;
-
- eparms[idx] = ex->elaborate_expr(des, scope, use_wid, true);
- if (eparms[idx])
- eval_expr(eparms[idx]);
-
+ eparms[idx] = elab_sys_task_arg(des, scope, name, idx, ex);
} else {
eparms[idx] = 0;
}
@@ -2733,8 +2654,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
// $sdf_annotate system task. There will be nothing for $sdf
// to annotate, and the user is intending to turn the behavior
// off anyhow, so replace the system task invocation with a no-op.
- if (gn_specify_blocks_flag == false
- && peek_tail_name(path_) == "$sdf_annotate") {
+ if (gn_specify_blocks_flag == false && name == "$sdf_annotate") {
cerr << get_fileline() << ": warning: Omitting $sdf_annotate() "
<< "since specify blocks are being omitted." << endl;
@@ -2743,8 +2663,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
return noop;
}
- NetSTask*cur = new NetSTask(peek_tail_name(path_), def_sfunc_as_task,
- eparms);
+ NetSTask*cur = new NetSTask(name, def_sfunc_as_task, eparms);
cur->set_line(*this);
return cur;
}
@@ -2871,11 +2790,6 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
des->errors += 1;
continue;
}
- if (wid > rv->expr_width()) {
- rv->set_width(wid);
- rv = pad_to_width(rv, wid, *this);
- }
- ivl_assert(*this, rv->expr_width() >= wid);
NetAssign*pr = new NetAssign(lv, rv);
pr->set_line(*this);
@@ -2988,9 +2902,6 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
if (rexp == 0)
return 0;
- rexp->set_width(lwid);
- rexp = pad_to_width(rexp, lwid, *this);
-
dev = new NetCAssign(lval, rexp);
if (debug_elaborate) {
@@ -3306,8 +3217,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
}
}
- probe_expr_width(des, scope, expr_[idx]->expr());
- NetExpr*tmp = elab_and_eval(des, scope, expr_[idx]->expr(), 0);
+ NetExpr*tmp = elab_and_eval(des, scope, expr_[idx]->expr(), -1);
if (tmp == 0) {
expr_[idx]->dump(cerr);
cerr << endl;
@@ -3409,8 +3319,9 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
/* Elaborate wait expression. Don't eval yet, we will do that
shortly, after we apply a reduction or. */
- probe_expr_width(des, scope, pe);
- NetExpr*expr = pe->elaborate_expr(des, scope, -1, false);
+ PExpr::width_mode_t mode;
+ pe->test_width(des, scope, mode);
+ NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(), false);
if (expr == 0) {
cerr << get_fileline() << ": error: Unable to elaborate"
" wait condition expression." << endl;
@@ -3607,9 +3518,6 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
if (rexp == 0)
return 0;
- rexp->set_width(lwid, true);
- rexp = pad_to_width(rexp, lwid, *this);
-
if (ltype==IVL_VT_BOOL && rexp->expr_type()!=IVL_VT_BOOL) {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
@@ -3670,32 +3578,14 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
assert(sig);
NetAssign_*lv = new NetAssign_(sig);
- /* Calculate the width of the initialization as if this were
- any other assignment statement. */
- unsigned use_width = lv->lwidth();
- bool unsized_flag = false;
- ivl_variable_type_t expr1_type = IVL_VT_NO_TYPE;
- use_width = expr1_->test_width(des, scope, use_width, use_width, expr1_type, unsized_flag);
-
/* Make the r-value of the initial assignment, and size it
properly. Then use it to build the assignment statement. */
- etmp = elab_and_eval(des, scope, expr1_, use_width);
- etmp->set_width(use_width);
- etmp = pad_to_width(etmp, use_width, *this);
+ etmp = elaborate_rval_expr(des, scope, lv->expr_type(), lv->lwidth(),
+ expr1_);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: FOR initial assign: "
<< sig->name() << " = " << *etmp << endl;
- assert(etmp->expr_width() >= lv->lwidth());
- }
-
- /* Based on the specific type of the l-value, do cleanup
- processing on the r-value. */
- if (etmp->expr_type() != IVL_VT_REAL) {
- unsigned wid = count_lval_width(lv);
- etmp->set_width(wid);
- etmp = pad_to_width(etmp, wid, *this);
- assert(etmp->expr_width() >= wid);
}
NetAssign*init = new NetAssign(lv, etmp);
@@ -3729,9 +3619,16 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
assert(sig);
lv = new NetAssign_(sig);
- /* Make the rvalue of the increment expression, and size it
- for the lvalue. */
- etmp = elab_and_eval(des, scope, expr2_, lv->lwidth());
+ /* Make the r-value of the increment assignment, and size it
+ properly. Then use it to build the assignment statement. */
+ etmp = elaborate_rval_expr(des, scope, lv->expr_type(), lv->lwidth(),
+ expr2_);
+
+ if (debug_elaborate) {
+ cerr << get_fileline() << ": debug: FOR increment assign: "
+ << sig->name() << " = " << *etmp << endl;
+ }
+
NetAssign*step = new NetAssign(lv, etmp);
step->set_line(*this);
@@ -3741,7 +3638,6 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
/* Elaborate the condition expression. Try to evaluate it too,
in case it is a constant. This is an interesting case
worthy of a warning. */
- probe_expr_width(des, scope, cond_);
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
if (ce == 0) {
delete top;
@@ -3832,7 +3728,6 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
- probe_expr_width(des, scope, expr_);
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {
cerr << get_fileline() << ": Unable to elaborate"
@@ -3956,7 +3851,6 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
*/
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
{
- probe_expr_width(des, scope, cond_);
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
NetWhile*loop = new NetWhile(tmp, statement_->elaborate(des, scope));
return loop;
@@ -4059,8 +3953,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
them for the timescale/precision of the scope. */
for (unsigned idx = 0 ; idx < ndelays ; idx += 1) {
PExpr*exp = delays[idx];
- probe_expr_width(des, scope, exp);
- NetExpr*cur = elab_and_eval(des, scope, exp, 0);
+ NetExpr*cur = elab_and_eval(des, scope, exp, -1);
if (NetEConst*con = dynamic_cast<NetEConst*> (cur)) {
verinum fn = con->value();
@@ -4098,7 +3991,6 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
NetNet*condit_sig = 0;
if (conditional && condition) {
- probe_expr_width(des, scope, condition);
NetExpr*tmp = elab_and_eval(des, scope, condition, -1);
ivl_assert(*condition, tmp);
@@ -4255,7 +4147,6 @@ bool Module::elaborate(Design*des, NetScope*scope) const
for (specparam_it_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
- probe_expr_width(des, scope, (*cur).second);
need_constant_expr = true;
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1);
need_constant_expr = false;
View
4 elaborate_analog.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008 Stephen Williams (steve@icarus.com)
+ * Copyright (c) 2008,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
@@ -28,8 +28,6 @@
NetProc* AContrib::elaborate(Design*des, NetScope*scope) const
{
- probe_expr_width(des, scope, lval_);
- probe_expr_width(des, scope, rval_);
NetExpr*lval = elab_and_eval(des, scope, lval_, -1);
NetExpr*rval = elab_and_eval(des, scope, rval_, -1);
View
318 eval_tree.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
+ * Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -29,7 +29,7 @@
# include "ivl_assert.h"
# include "netmisc.h"
-NetExpr* NetExpr::eval_tree(int)
+NetExpr* NetExpr::eval_tree()
{
return 0;
}
@@ -114,12 +114,12 @@ NetECReal* NetEBAdd::eval_tree_real_()
return res;
}
-NetExpr* NetEBAdd::eval_tree(int prune_to_width)
+NetExpr* NetEBAdd::eval_tree()
{
- eval_expr(left_, prune_to_width);
- eval_expr(right_, prune_to_width);
+ eval_expr(left_);
+ eval_expr(right_);
- if (left_->expr_type() == IVL_VT_REAL || right_->expr_type()==IVL_VT_REAL)
+ if (expr_type() == IVL_VT_REAL)
return eval_tree_real_();
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
@@ -131,33 +131,23 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
+ unsigned wid = expr_width();
+ ivl_assert(*this, wid > 0);
+ ivl_assert(*this, lval.len() == wid);
+ ivl_assert(*this, rval.len() == wid);
+
verinum val;
switch (op_) {
case '+':
- val = lval + rval;
+ val = verinum(lval + rval, wid);
break;
case '-':
- val = lval - rval;
+ val = verinum(lval - rval, wid);
break;
default:
return 0;
}
- /* Result might have known width. */
- if (has_width()) {
- unsigned lwid = lc->expr_width();
- unsigned rwid = rc->expr_width();
- unsigned wid = (rwid > lwid) ? rwid : lwid;
- if (prune_to_width < 0)
- wid += 1;
- verinum val2=verinum(val,wid);
- val=val2;
- } else {
- /* No fixed width, so trim the bits losslessly. */
- verinum val2 = trim_vnum(val);
- val = val2;
- }
-
NetEConst *res = new NetEConst(val);
ivl_assert(*this, res);
res->set_line(*this);
@@ -188,37 +178,20 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
- if (lval.len() < expr_width())
- lval = pad_to_width(lval, expr_width());
- if (rval.len() < expr_width())
- rval = pad_to_width(rval, expr_width());
-
- if (se->expr_width() > this->expr_width()) {
- cerr << get_fileline() << ": internal error: "
- << "expr_width()=" << expr_width()
- << ", sub expr_width()=" << se->expr_width()
- << ", sub expression=" << *se << endl;
- }
- ivl_assert(*this, se->expr_width() <= this->expr_width());
+ unsigned wid = expr_width();
+ ivl_assert(*this, wid > 0);
+ ivl_assert(*this, lval.len() == wid);
+ ivl_assert(*this, rval.len() == wid);
verinum val;
if (op_ == se->op_) {
/* (a + lval) + rval --> a + (rval+lval) */
/* (a - lval) - rval --> a - (rval+lval) */
- val = rval + lval;
+ val = verinum(rval + lval, wid);
} else {
/* (a - lval) + rval --> a + (rval-lval) */
/* (a + lval) - rval --> a - (rval-lval) */
- val = rval - lval;
- }
-
- // Since we padded the operands above to be the minimum
- // width, the val should also be at least expr_width().
- ivl_assert(*this, val.len() >= expr_width());
- if (val.len() > expr_width()) {
- verinum tmp (val, expr_width());
- tmp.has_sign(val.has_sign());
- val = tmp;
+ val = verinum(rval - lval, wid);
}
NetEConst*tmp = new NetEConst(val);
@@ -236,15 +209,15 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
return 0;
}
-NetEConst* NetEBBits::eval_tree(int prune_to_width)
+NetEConst* NetEBBits::eval_tree()
{
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluating expression:"
- << *this << ", prune_to_width=" << prune_to_width << endl;
+ << *this << endl;
}
- eval_expr(left_, prune_to_width);
- eval_expr(right_, prune_to_width);
+ eval_expr(left_);
+ eval_expr(right_);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
@@ -266,79 +239,33 @@ NetEConst* NetEBBits::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
- unsigned lwid = lc->expr_width();
- if (lwid == 0) lwid = lval.len();
-
- unsigned rwid = rc->expr_width();
- if (rwid == 0) rwid = rval.len();
-
unsigned wid = expr_width();
- if (wid == 0)
- wid = (rwid > lwid)? rwid : lwid;
+ ivl_assert(*this, wid > 0);
+ ivl_assert(*this, lval.len() == wid);
+ ivl_assert(*this, rval.len() == wid);
verinum res (verinum::V0, wid);
- if (lwid > wid)
- lwid = wid;
- if (rwid > wid)
- rwid = wid;
-
- // Sub-expressions of bitwise operators need to be the same
- // width. Pad them out if necessary.
- if (lwid < wid) {
- lval = pad_to_width(lval, wid);
- lwid = wid;
- }
- if (rwid < wid) {
- rval = pad_to_width(rval, wid);
- rwid = wid;
- }
-
switch (op()) {
case '|': {
- unsigned cnt = lwid;
- if (cnt > wid) cnt = wid;
- if (cnt > rwid) cnt = rwid;
- for (unsigned idx = 0 ; idx < cnt ; idx += 1)
+ for (unsigned idx = 0 ; idx < wid ; idx += 1)
res.set(idx, lval.get(idx) | rval.get(idx));
- if (lwid < rwid)
- for (unsigned idx = lwid ; idx < rwid ; idx += 1)
- res.set(idx, rval.get(idx));
-
- if (rwid < lwid)
- for (unsigned idx = rwid ; idx < lwid ; idx += 1)
- res.set(idx, lval.get(idx));
-
break;
}
case '&': {
- unsigned cnt = lwid;
- if (cnt > wid) cnt = wid;
- if (cnt > rwid) cnt = rwid;
- for (unsigned idx = 0 ; idx < cnt ; idx += 1)
+ for (unsigned idx = 0 ; idx < wid ; idx += 1)
res.set(idx, lval.get(idx) & rval.get(idx));
break;
}
case '^': {
- unsigned cnt = lwid;
- if (cnt > wid) cnt = wid;
- if (cnt > rwid) cnt = rwid;
- for (unsigned idx = 0 ; idx < cnt ; idx += 1)
+ for (unsigned idx = 0 ; idx < wid ; idx += 1)
res.set(idx, lval.get(idx) ^ rval.get(idx));
- if (lwid < rwid)
- for (unsigned idx = lwid ; idx < rwid ; idx += 1)
- res.set(idx, rval.get(idx));
-
- if (rwid < lwid)
- for (unsigned idx = rwid ; idx < lwid ; idx += 1)
- res.set(idx, lval.get(idx));
-
break;
}
@@ -761,7 +688,7 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag)
return result;
}
-NetEConst* NetEBComp::eval_tree(int)
+NetEConst* NetEBComp::eval_tree()
{
eval_expr(left_);
eval_expr(right_);
@@ -850,11 +777,8 @@ NetExpr* NetEBDiv::eval_tree_real_()
* The NetEBDiv operator includes the / and % operators. First evaluate
* the sub-expressions, then perform the required operation.
*/
-NetExpr* NetEBDiv::eval_tree(int prune_to_width)
+NetExpr* NetEBDiv::eval_tree()
{
-// assert(prune_to_width <= 0);
-// HERE
-
eval_expr(left_);
eval_expr(right_);
@@ -865,20 +789,26 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (lc == 0 || rc == 0) return 0;
- // Make sure the expression is evaluated at the
- // expression width.
- verinum lval = pad_to_width(lc->value(), expr_width());
- verinum rval = pad_to_width(rc->value(), expr_width());
+ verinum lval = lc->value();
+ verinum rval = rc->value();
- NetExpr*tmp = 0;
+ unsigned wid = expr_width();
+ ivl_assert(*this, wid > 0);
+ ivl_assert(*this, lval.len() == wid);
+ ivl_assert(*this, rval.len() == wid);
+
+ verinum val;
switch (op_) {
case '/':
- tmp = new NetEConst(lval / rval);
+ val = verinum(lval / rval, wid);
break;
case '%':
- tmp = new NetEConst(lval % rval);
+ val = verinum(lval % rval, wid);
break;
+ default:
+ return 0;
}
+ NetExpr*tmp = new NetEConst(val);
ivl_assert(*this, tmp);
tmp->set_line(*this);
@@ -928,7 +858,7 @@ NetEConst* NetEBLogic::eval_tree_real_()
return tmp;
}
-NetEConst* NetEBLogic::eval_tree(int)
+NetEConst* NetEBLogic::eval_tree()
{
eval_expr(left_);
eval_expr(right_);
@@ -1024,11 +954,8 @@ NetExpr* NetEBMult::eval_tree_real_()
return res;
}
-NetExpr* NetEBMult::eval_tree(int prune_to_width)
+NetExpr* NetEBMult::eval_tree()
{
-// assert(prune_to_width <= 0);
-// HERE
-
eval_expr(left_);
eval_expr(right_);
@@ -1042,7 +969,13 @@ NetExpr* NetEBMult::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
- NetEConst*tmp = new NetEConst(lval * rval);
+ unsigned wid = expr_width();
+ ivl_assert(*this, wid > 0);
+ ivl_assert(*this, lval.len() == wid);
+ ivl_assert(*this, rval.len() == wid);
+
+ verinum val(lval * rval, wid);
+ NetEConst*tmp = new NetEConst(val);
ivl_assert(*this, tmp);
tmp->set_line(*this);
@@ -1072,11 +1005,8 @@ NetExpr* NetEBPow::eval_tree_real_()
return res;
}
-NetExpr* NetEBPow::eval_tree(int prune_to_width)
+NetExpr* NetEBPow::eval_tree()
{
-// assert(prune_to_width <= 0);
-// HERE
-
eval_expr(left_);
eval_expr(right_);
@@ -1090,7 +1020,12 @@ NetExpr* NetEBPow::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
- NetEConst*res = new NetEConst( pow(lval,rval) );
+ unsigned wid = expr_width();
+ ivl_assert(*this, wid > 0);
+ ivl_assert(*this, lval.len() == wid);
+
+ verinum val(pow(lval, rval), wid);
+ NetEConst*res = new NetEConst(val);
ivl_assert(*this, res);
res->set_line(*this);
@@ -1105,7 +1040,7 @@ NetExpr* NetEBPow::eval_tree(int prune_to_width)
* Evaluate the shift operator if possible. For this to work, both
* operands must be constant.
*/
-NetEConst* NetEBShift::eval_tree(int prune_to_width)
+NetEConst* NetEBShift::eval_tree()
{
eval_expr(left_);
eval_expr(right_);
@@ -1116,79 +1051,44 @@ NetEConst* NetEBShift::eval_tree(int prune_to_width)
NetEConst*res;
- verinum rv = re->value();
verinum lv = le->value();
+ verinum rv = re->value();
- /* Make an early estimate of the expression width. */
unsigned wid = expr_width();
+ ivl_assert(*this, wid > 0);
+ ivl_assert(*this, lv.len() == wid);
if (rv.is_defined()) {
-
unsigned shift = rv.as_ulong();
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: "
<< "Evaluate " << lv << "<<" << op() << ">> "
- << rv << ", wid=" << wid << ", shift=" << shift
- << ", lv.has_len()=" << lv.has_len() << endl;
- }
-
- if ((wid == 0) || ! lv.has_len()) {
- /* If the caller doesn't care what the width is,
- then calculate a width from the trimmed left
- expression, plus the shift. This avoids
- data loss. */
- lv = trim_vnum(lv);
- wid = lv.len();
- if (op() == 'l')
- wid = lv.len() + shift;
+ << rv << ", wid=" << wid << ", shift=" << shift << endl;
}
- if (prune_to_width > 0 && wid > (unsigned)prune_to_width)
- wid = prune_to_width;
-
- assert(wid > 0);
- verinum::V pad = verinum::V0;
- if (op() == 'R' && has_sign()) {
- pad = lv[lv.len()-1];
- }
- verinum nv (pad, wid, lv.has_len());
-
- if (op() == 'r' || op() == 'R') {
- unsigned cnt = wid;
- if (cnt > nv.len())
- cnt = nv.len();
- if (shift >= lv.len())
- cnt = 0;
- else if (cnt > (lv.len()-shift))
- cnt = (lv.len()-shift);
- for (unsigned idx = 0 ; idx < cnt ; idx += 1)
- nv.set(idx, lv[idx+shift]);
-
- } else {
- unsigned cnt = wid;
- if (cnt > lv.len())
- cnt = lv.len();
- if (shift >= nv.len())
- cnt = 0;
- else if (cnt > (nv.len()-shift))
- cnt = nv.len() - shift;
-
- for (unsigned idx = 0 ; idx < cnt ; idx += 1)
- nv.set(idx+shift, lv[idx]);
+ verinum val;
+ switch (op_) {
+ case 'l':
+ val = verinum(lv << shift, wid);
+ break;
+ case 'r':
+ lv.has_sign(false);
+ val = verinum(lv >> shift, wid);
+ break;
+ case 'R':
+ lv.has_sign(true);
+ val = verinum(lv >> shift, wid);
+ break;
+ default:
+ return 0;
}
+ val.has_sign(has_sign());
- res = new NetEConst(nv);
-
+ res = new NetEConst(val);
} else {
- if (wid == 0) wid = left_->expr_width();
-
- if (prune_to_width > 0 && wid > (unsigned)prune_to_width)
- wid = prune_to_width;
-
- assert(wid > 0);
- verinum nv (verinum::Vx, wid);
- res = new NetEConst(nv);
+ verinum val (verinum::Vx, wid);
+ res = new NetEConst(val);
}
res->set_line(*this);
@@ -1196,7 +1096,7 @@ NetEConst* NetEBShift::eval_tree(int prune_to_width)
return res;
}
-NetEConst* NetEConcat::eval_tree(int prune_to_width)
+NetEConst* NetEConcat::eval_tree()
{
// HERE
unsigned repeat_val = repeat();
@@ -1204,7 +1104,7 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluating expression:"
- << *this << ", prune_to_width=" << prune_to_width << endl;
+ << *this << endl;
}
unsigned gap = 0;
@@ -1225,7 +1125,7 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
// that is here. If I succeed, reset the parameter to
// the evaluated value.
assert(parms_[idx]);
- NetExpr*expr = parms_[idx]->eval_tree(0);
+ NetExpr*expr = parms_[idx]->eval_tree();
if (expr) {
expr->set_line(*parms_[idx]);
delete parms_[idx];
@@ -1285,16 +1185,15 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
val.has_sign( this->has_sign() );
NetEConst*res = new NetEConst(val);
- res->set_width(val.len());
return res;
}
-NetEConst* NetESelect::eval_tree(int prune_to_width)
+NetEConst* NetESelect::eval_tree()
{
// HERE
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluating expression:"
- << *this << ", prune_to_width=" << prune_to_width << endl;
+ << *this << endl;
}
eval_expr(expr_);
@@ -1318,14 +1217,12 @@ NetEConst* NetESelect::eval_tree(int prune_to_width)
verinum::V pad_bit = verinum::Vx;
if (base_ == 0) {
- /* If the base is NULL (different from 0) the this
- select is here for sign extension. So calculate a
- proper pad bit. Extend x or z or 0, and sign extend 1
- if this is signed. */
- unsigned top = expr->expr_width()-1;
-
- pad_bit = eval.get(top);
- if (pad_bit==verinum::V1 && !has_sign())
+ /* If the base is NULL (different from 0) then this
+ select is here for zero or sign extension. So
+ calculate a proper pad bit. */
+ if (has_sign())
+ pad_bit = eval.get(expr->expr_width()-1);
+ else
pad_bit = verinum::V0;
}
@@ -1365,12 +1262,12 @@ static void print_ternary_cond(NetExpr*expr)
* evaluates to x or z, then merge the constant bits of the true and
* false expressions.
*/
-NetExpr* NetETernary::eval_tree(int prune_to_width)
+NetExpr* NetETernary::eval_tree()
{
eval_expr(cond_);
switch (const_logical(cond_)) {
case C_0:
- eval_expr(false_val_, prune_to_width);
+ eval_expr(false_val_);
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate ternary with "
@@ -1393,7 +1290,7 @@ NetExpr* NetETernary::eval_tree(int prune_to_width)
return false_val_->dup_expr();
case C_1:
- eval_expr(true_val_, prune_to_width);
+ eval_expr(true_val_);
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate ternary with "
<< "constant condition value: ";
@@ -1425,8 +1322,8 @@ NetExpr* NetETernary::eval_tree(int prune_to_width)
expressions down to constants then compare the values to
build up a constant result. */
- eval_expr(true_val_, prune_to_width);
- eval_expr(false_val_, prune_to_width);
+ eval_expr(true_val_);
+ eval_expr(false_val_);
NetEConst*t = dynamic_cast<NetEConst*>(true_val_);
NetEConst*f = dynamic_cast<NetEConst*>(false_val_);
@@ -1509,7 +1406,7 @@ NetExpr* NetEUnary::eval_tree_real_()
return res;