From 89244e0f701025500e91b20f828318a3ed51e820 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 6 Feb 2013 09:33:29 +0000 Subject: [PATCH] Add support for concatenation operations in constant functions. Also fix a compiler crash when attempting to evaluate a function which has no valid statement(s) (due to earlier compilation errors). --- eval_tree.cc | 24 ++++++++++++++++-------- net_func_eval.cc | 33 +++++++++++++++++++++++++++++++-- netlist.h | 4 ++++ 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/eval_tree.cc b/eval_tree.cc index 992f18175..fcecd9bea 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1090,14 +1090,8 @@ NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const NetEConst* NetEConcat::eval_tree() { - unsigned repeat_val = repeat(); unsigned local_errors = 0; - if (debug_eval_tree) { - cerr << get_fileline() << ": debug: Evaluating expression:" - << *this << endl; - } - unsigned gap = 0; for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { @@ -1141,6 +1135,14 @@ NetEConst* NetEConcat::eval_tree() if (local_errors > 0) return 0; + return eval_arguments_(parms_, gap); +} + +NetEConst* NetEConcat::eval_arguments_(const vector&vals, + unsigned gap) const +{ + unsigned repeat_val = repeat(); + // At this point, the "gap" is the width of a single repeat of // the concatenation. The total width of the result is the gap // times the repeat count. @@ -1150,8 +1152,8 @@ NetEConst* NetEConcat::eval_tree() unsigned cur = 0; bool is_string_flag = true; - for (unsigned idx = parms_.size() ; idx > 0 ; idx -= 1) { - NetEConst*expr = dynamic_cast(parms_[idx-1]); + for (unsigned idx = vals.size() ; idx > 0 ; idx -= 1) { + const NetEConst*expr = dynamic_cast(vals[idx-1]); if (expr == 0) return 0; @@ -1176,6 +1178,12 @@ NetEConst* NetEConcat::eval_tree() val.has_sign( this->has_sign() ); NetEConst*res = new NetEConst(val); + ivl_assert(*this, res); + res->set_line(*this); + if (debug_eval_tree) { + cerr << get_fileline() << ": debug: Evaluated: " + << *this << " --> " << *res << endl; + } return res; } diff --git a/net_func_eval.cc b/net_func_eval.cc index b156bdc1b..727d469cf 100644 --- a/net_func_eval.cc +++ b/net_func_eval.cc @@ -55,8 +55,10 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vectorevaluate_function_find_locals(loc, context_map); - // Perform the evaluation - bool flag = statement_->evaluate_function(loc, context_map); + // Perform the evaluation. Note that if there were errors + // when compiling the function definition, we may not have + // a valid statement. + bool flag = statement_ && statement_->evaluate_function(loc, context_map); // Extract the result... ptr = context_map.find(scope_->basename()); @@ -295,6 +297,33 @@ NetExpr* NetEBinary::evaluate_function(const LineInfo&loc, return res; } +NetExpr* NetEConcat::evaluate_function(const LineInfo&loc, + map&context_map) const +{ + vectorvals(parms_.size()); + unsigned gap = 0; + + unsigned valid_vals = 0; + for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { + ivl_assert(*this, parms_[idx]); + vals[idx] = parms_[idx]->evaluate_function(loc, context_map); + if (vals[idx] == 0) continue; + + gap += vals[idx]->expr_width(); + + valid_vals += 1; + } + + NetExpr*res = 0; + if (valid_vals == parms_.size()) { + res = eval_arguments_(vals, gap); + } + for (unsigned idx = 0 ; idx < vals.size() ; idx += 1) { + delete vals[idx]; + } + return res; +} + NetExpr* NetEConst::evaluate_function(const LineInfo&, map&) const { diff --git a/netlist.h b/netlist.h index 904ec51f5..60034c049 100644 --- a/netlist.h +++ b/netlist.h @@ -3789,6 +3789,8 @@ class NetEConcat : public NetExpr { virtual bool has_width() const; virtual NetEConcat* dup_expr() const; virtual NetEConst* eval_tree(); + virtual NetExpr* evaluate_function(const LineInfo&loc, + std::map&ctx) const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*root); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -3797,6 +3799,8 @@ class NetEConcat : public NetExpr { std::vectorparms_; unsigned repeat_; ivl_variable_type_t expr_type_; + + NetEConst* eval_arguments_(const vector&vals, unsigned gap) const; };