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).
This commit is contained in:
Martin Whitaker 2013-02-06 09:33:29 +00:00 committed by Cary R
parent 5abd939655
commit 89244e0f70
3 changed files with 51 additions and 10 deletions

View File

@ -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<NetExpr*>&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<NetEConst*>(parms_[idx-1]);
for (unsigned idx = vals.size() ; idx > 0 ; idx -= 1) {
const NetEConst*expr = dynamic_cast<NetEConst*>(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;
}

View File

@ -55,8 +55,10 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
// fills in the context_map with local variables held by the scope.
scope_->evaluate_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<perm_string,NetExpr*>&context_map) const
{
vector<NetExpr*>vals(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<perm_string,NetExpr*>&) const
{

View File

@ -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<perm_string,NetExpr*>&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::vector<NetExpr*>parms_;
unsigned repeat_;
ivl_variable_type_t expr_type_;
NetEConst* eval_arguments_(const vector<NetExpr*>&vals, unsigned gap) const;
};