More expression types supported during constant function evaluation.
This commit is contained in:
parent
a5a7050120
commit
62b67c1843
35
eval_tree.cc
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;
|
||||
|
|
|
|||
147
net_func_eval.cc
147
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);
|
||||
|
||||
ivl_assert(loc, lval->word() == 0);
|
||||
ivl_assert(loc, lval->get_base() == 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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
|||
17
netlist.h
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_;
|
||||
|
|
|
|||
Loading…
Reference in New Issue