Skip to content
Browse files

More expression types supported during constant function evaluation.

  • Loading branch information...
1 parent a5a7050 commit 62b67c184370fbe025381c78bddfb6c6287a43c4 @steveicarus committed May 29, 2012
Showing with 182 additions and 15 deletions.
  1. +23 −12 eval_tree.cc
  2. +143 −2 net_func_eval.cc
  3. +16 −1 netlist.h
View
35 eval_tree.cc
@@ -954,15 +954,15 @@ NetEConst* NetEBLogic::eval_tree()
}
-NetExpr* NetEBMult::eval_tree_real_()
+NetExpr* NetEBMult::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
{
- verireal lval;
- verireal rval;
+ double lval;
+ double rval;
- bool flag = get_real_arguments_(lval, rval);
+ bool flag = get_real_arguments(l, r, lval, rval);
if (! flag) return 0;
- NetECReal*res = new NetECReal(lval * rval);
+ NetECReal*res = new NetECReal( verireal(lval * rval) );
ivl_assert(*this, res);
res->set_line(*this);
@@ -978,11 +978,16 @@ NetExpr* NetEBMult::eval_tree()
eval_expr(left_);
eval_expr(right_);
- if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
+ return eval_arguments_(left_, right_);
+}
+
+NetExpr* NetEBMult::eval_arguments_(const NetExpr*l, const NetExpr*r) const
+{
+ if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
assert(expr_type() == IVL_VT_LOGIC);
- NetEConst*lc = dynamic_cast<NetEConst*>(left_);
- NetEConst*rc = dynamic_cast<NetEConst*>(right_);
+ const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
+ const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
if (lc == 0 || rc == 0) return 0;
verinum lval = lc->value();
@@ -1338,12 +1343,18 @@ NetExpr* NetETernary::eval_tree()
eval_expr(true_val_);
eval_expr(false_val_);
- NetEConst*t = dynamic_cast<NetEConst*>(true_val_);
- NetEConst*f = dynamic_cast<NetEConst*>(false_val_);
+ return blended_arguments_(true_val_, false_val_);
+}
+
+NetExpr*NetETernary::blended_arguments_(const NetExpr*te, const NetExpr*fe) const
+{
+
+ const NetEConst*t = dynamic_cast<const NetEConst*>(te);
+ const NetEConst*f = dynamic_cast<const NetEConst*>(fe);
if (t == 0 || f == 0) {
verireal tv, fv;
- if (!get_real_arg_(true_val_, tv)) return 0;
- if (!get_real_arg_(false_val_, fv)) return 0;
+ if (!get_real_arg_(te, tv)) return 0;
+ if (!get_real_arg_(te, fv)) return 0;
verireal val = verireal(0.0);
if (tv.as_double() == fv.as_double()) val = tv;
View
145 net_func_eval.cc
@@ -18,6 +18,7 @@
*/
# include "netlist.h"
+# include "netmisc.h"
# include "compiler.h"
# include <typeinfo>
# include "ivl_assert.h"
@@ -37,6 +38,7 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
// Put the return value into the map...
context_map[scope_->basename()] = 0;
+
// Load the input ports into the map...
ivl_assert(loc, ports_.size() == args.size());
for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) {
@@ -50,6 +52,10 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
}
}
+ // Ask the scope to collect definitions for local values. This
+ // 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);
@@ -72,6 +78,26 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
return 0;
}
+void NetScope::evaluate_function_find_locals(const LineInfo&loc,
+ map<perm_string,NetExpr*>&context_map) const
+{
+ for (map<perm_string,NetNet*>::const_iterator cur = signals_map_.begin()
+ ; cur != signals_map_.end() ; ++cur) {
+
+ const NetNet*tmp = cur->second;
+ // Skip ports, which are handled elsewhere.
+ if (tmp->port_type() != NetNet::NOT_A_PORT)
+ continue;
+
+ context_map[tmp->name()] = 0;
+
+ if (debug_eval_tree) {
+ cerr << loc.get_fileline() << ": debug: "
+ << " (local) " << tmp->name() << endl;
+ }
+ }
+}
+
NetExpr* NetExpr::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&) const
{
@@ -101,14 +127,50 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
const NetAssign_*lval = l_val(0);
+ map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
+ ivl_assert(*this, ptr != context_map.end());
+
+ // Do not support having l-values that are unpacked arrays.
ivl_assert(loc, lval->word() == 0);
- ivl_assert(loc, lval->get_base() == 0);
+ // Evaluate the r-value expression.
NetExpr*rval_result = rval()->evaluate_function(loc, context_map);
if (rval_result == 0)
return false;
- map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
+ if (const NetExpr*base_expr = lval->get_base()) {
+ NetExpr*base_result = base_expr->evaluate_function(loc, context_map);
+ if (base_result == 0) {
+ delete rval_result;
+ return false;
+ }
+
+ NetEConst*base_const = dynamic_cast<NetEConst*>(base_result);
+ ivl_assert(loc, base_const);
+
+ long base = base_const->value().as_long();
+
+ list<long>prefix (0);
+ base = lval->sig()->sb_to_idx(prefix, base);
+
+ if (ptr->second == 0)
+ ptr->second = make_const_x(lval->sig()->vector_width());
+
+ ivl_assert(loc, base + lval->lwidth() <= ptr->second->expr_width());
+
+ NetEConst*ptr_const = dynamic_cast<NetEConst*>(ptr->second);
+ verinum lval_v = ptr_const->value();
+ NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
+ verinum rval_v = cast_to_width(rval_const->value(), lval->lwidth());
+
+ for (unsigned idx = 0 ; idx < rval_v.len() ; idx += 1)
+ lval_v.set(idx+base, rval_v[idx]);
+
+ delete base_result;
+ delete rval_result;
+ rval_result = new NetEConst(lval_v);
+ }
+
if (ptr->second)
delete ptr->second;
@@ -221,6 +283,24 @@ NetExpr* NetEBAdd::evaluate_function(const LineInfo&loc,
return res;
}
+NetExpr* NetEBMult::evaluate_function(const LineInfo&loc,
+ map<perm_string,NetExpr*>&context_map) const
+{
+ NetExpr*lval = left_->evaluate_function(loc, context_map);
+ NetExpr*rval = right_->evaluate_function(loc, context_map);
+
+ if (lval == 0 || rval == 0) {
+ delete lval;
+ delete rval;
+ return 0;
+ }
+
+ NetExpr*res = eval_arguments_(lval, rval);
+ delete lval;
+ delete rval;
+ return res;
+}
+
NetExpr* NetEBShift::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
{
@@ -247,6 +327,40 @@ NetExpr* NetEConst::evaluate_function(const LineInfo&,
return res;
}
+NetExpr* NetESelect::evaluate_function(const LineInfo&loc,
+ map<perm_string,NetExpr*>&context_map) const
+{
+ NetExpr*sub_exp = expr_->evaluate_function(loc, context_map);
+ ivl_assert(loc, sub_exp);
+
+ NetEConst*sub_const = dynamic_cast<NetEConst*> (sub_exp);
+ ivl_assert(loc, sub_exp);
+
+ verinum sub = sub_const->value();
+ delete sub_exp;
+
+ long base = 0;
+ if (base_) {
+ NetExpr*base_val = base_->evaluate_function(loc, context_map);
+ ivl_assert(loc, base_val);
+
+ NetEConst*base_const = dynamic_cast<NetEConst*>(base_val);
+ ivl_assert(loc, base_const);
+
+ base = base_const->value().as_long();
+ delete base_val;
+ } else {
+ sub = pad_to_width(sub, expr_width());
+ }
+
+ verinum res (verinum::Vx, expr_width());
+ for (unsigned idx = 0 ; idx < res.len() ; idx += 1)
+ res.set(idx, sub[base+idx]);
+
+ NetEConst*res_const = new NetEConst(res);
+ return res_const;
+}
+
NetExpr* NetESignal::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&context_map) const
{
@@ -264,3 +378,30 @@ NetExpr* NetESignal::evaluate_function(const LineInfo&,
return ptr->second->dup_expr();
}
+
+NetExpr* NetETernary::evaluate_function(const LineInfo&loc,
+ map<perm_string,NetExpr*>&context_map) const
+{
+ auto_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
+
+ switch (const_logical(cval.get())) {
+
+ case C_0:
+ return false_val_->evaluate_function(loc, context_map);
+ case C_1:
+ return true_val_->evaluate_function(loc, context_map);
+ case C_X:
+ break;
+ default:
+ cerr << get_fileline() << ": error: Condition expression is not constant here." << endl;
+ return 0;
+ }
+
+ NetExpr*tval = true_val_->evaluate_function(loc, context_map);
+ NetExpr*fval = false_val_->evaluate_function(loc, context_map);
+
+ NetExpr*res = blended_arguments_(tval, fval);
+ delete tval;
+ delete fval;
+ return res;
+}
View
17 netlist.h
@@ -816,6 +816,11 @@ class NetScope : public Attrib {
NetTaskDef* task_def();
NetFuncDef* func_def();
+ // This is used by the evaluate_function setup to collect
+ // local variables from the scope.
+ void evaluate_function_find_locals(const LineInfo&loc,
+ map<perm_string,NetExpr*>&context_map) const;
+
void set_line(perm_string file, perm_string def_file,
unsigned lineno, unsigned def_lineno);
void set_line(perm_string file, unsigned lineno);
@@ -3607,10 +3612,13 @@ class NetEBMult : public NetEBinary {
virtual NetEBMult* dup_expr() const;
virtual NetExpr* eval_tree();
+ virtual NetExpr* evaluate_function(const LineInfo&loc,
+ std::map<perm_string,NetExpr*>&ctx) const;
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
private:
- NetExpr* eval_tree_real_();
+ NetExpr* eval_arguments_(const NetExpr*l, const NetExpr*r) const;
+ NetExpr* eval_tree_real_(const NetExpr*l, const NetExpr*r) const;
};
/*
@@ -3729,6 +3737,8 @@ class NetESelect : public NetExpr {
virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEConst* eval_tree();
+ virtual NetExpr*evaluate_function(const LineInfo&loc,
+ std::map<perm_string,NetExpr*>&ctx) const;
virtual NetESelect* dup_expr() const;
virtual NetNet*synthesize(Design*des, NetScope*scope, NetExpr*root);
virtual void dump(ostream&) const;
@@ -3866,6 +3876,9 @@ class NetETernary : public NetExpr {
virtual NetETernary* dup_expr() const;
virtual NetExpr* eval_tree();
+ virtual NetExpr*evaluate_function(const LineInfo&loc,
+ std::map<perm_string,NetExpr*>&ctx) const;
+
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const;
@@ -3876,6 +3889,8 @@ class NetETernary : public NetExpr {
static bool test_operand_compat(ivl_variable_type_t tru, ivl_variable_type_t fal);
private:
+ NetExpr* blended_arguments_(const NetExpr*t, const NetExpr*f) const;
+
NetExpr*cond_;
NetExpr*true_val_;
NetExpr*false_val_;

0 comments on commit 62b67c1

Please sign in to comment.
Something went wrong with that request. Please try again.