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;
|
double lval;
|
||||||
verireal rval;
|
double rval;
|
||||||
|
|
||||||
bool flag = get_real_arguments_(lval, rval);
|
bool flag = get_real_arguments(l, r, lval, rval);
|
||||||
if (! flag) return 0;
|
if (! flag) return 0;
|
||||||
|
|
||||||
NetECReal*res = new NetECReal(lval * rval);
|
NetECReal*res = new NetECReal( verireal(lval * rval) );
|
||||||
ivl_assert(*this, res);
|
ivl_assert(*this, res);
|
||||||
res->set_line(*this);
|
res->set_line(*this);
|
||||||
|
|
||||||
|
|
@ -978,11 +978,16 @@ NetExpr* NetEBMult::eval_tree()
|
||||||
eval_expr(left_);
|
eval_expr(left_);
|
||||||
eval_expr(right_);
|
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);
|
assert(expr_type() == IVL_VT_LOGIC);
|
||||||
|
|
||||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||||
if (lc == 0 || rc == 0) return 0;
|
if (lc == 0 || rc == 0) return 0;
|
||||||
|
|
||||||
verinum lval = lc->value();
|
verinum lval = lc->value();
|
||||||
|
|
@ -1338,12 +1343,18 @@ NetExpr* NetETernary::eval_tree()
|
||||||
eval_expr(true_val_);
|
eval_expr(true_val_);
|
||||||
eval_expr(false_val_);
|
eval_expr(false_val_);
|
||||||
|
|
||||||
NetEConst*t = dynamic_cast<NetEConst*>(true_val_);
|
return blended_arguments_(true_val_, false_val_);
|
||||||
NetEConst*f = dynamic_cast<NetEConst*>(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) {
|
if (t == 0 || f == 0) {
|
||||||
verireal tv, fv;
|
verireal tv, fv;
|
||||||
if (!get_real_arg_(true_val_, tv)) return 0;
|
if (!get_real_arg_(te, tv)) return 0;
|
||||||
if (!get_real_arg_(false_val_, fv)) return 0;
|
if (!get_real_arg_(te, fv)) return 0;
|
||||||
|
|
||||||
verireal val = verireal(0.0);
|
verireal val = verireal(0.0);
|
||||||
if (tv.as_double() == fv.as_double()) val = tv;
|
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 "netlist.h"
|
||||||
|
# include "netmisc.h"
|
||||||
# include "compiler.h"
|
# include "compiler.h"
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
# include "ivl_assert.h"
|
# 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...
|
// Put the return value into the map...
|
||||||
context_map[scope_->basename()] = 0;
|
context_map[scope_->basename()] = 0;
|
||||||
|
|
||||||
// Load the input ports into the map...
|
// Load the input ports into the map...
|
||||||
ivl_assert(loc, ports_.size() == args.size());
|
ivl_assert(loc, ports_.size() == args.size());
|
||||||
for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) {
|
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
|
// Perform the evaluation
|
||||||
bool flag = statement_->evaluate_function(loc, context_map);
|
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;
|
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&,
|
NetExpr* NetExpr::evaluate_function(const LineInfo&,
|
||||||
map<perm_string,NetExpr*>&) const
|
map<perm_string,NetExpr*>&) const
|
||||||
{
|
{
|
||||||
|
|
@ -101,14 +127,50 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
|
||||||
|
|
||||||
const NetAssign_*lval = l_val(0);
|
const NetAssign_*lval = l_val(0);
|
||||||
|
|
||||||
ivl_assert(loc, lval->word() == 0);
|
map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
|
||||||
ivl_assert(loc, lval->get_base() == 0);
|
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);
|
NetExpr*rval_result = rval()->evaluate_function(loc, context_map);
|
||||||
if (rval_result == 0)
|
if (rval_result == 0)
|
||||||
return false;
|
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)
|
if (ptr->second)
|
||||||
delete ptr->second;
|
delete ptr->second;
|
||||||
|
|
||||||
|
|
@ -221,6 +283,24 @@ NetExpr* NetEBAdd::evaluate_function(const LineInfo&loc,
|
||||||
return res;
|
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,
|
NetExpr* NetEBShift::evaluate_function(const LineInfo&loc,
|
||||||
map<perm_string,NetExpr*>&context_map) const
|
map<perm_string,NetExpr*>&context_map) const
|
||||||
{
|
{
|
||||||
|
|
@ -247,6 +327,40 @@ NetExpr* NetEConst::evaluate_function(const LineInfo&,
|
||||||
return res;
|
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&,
|
NetExpr* NetESignal::evaluate_function(const LineInfo&,
|
||||||
map<perm_string,NetExpr*>&context_map) const
|
map<perm_string,NetExpr*>&context_map) const
|
||||||
{
|
{
|
||||||
|
|
@ -264,3 +378,30 @@ NetExpr* NetESignal::evaluate_function(const LineInfo&,
|
||||||
|
|
||||||
return ptr->second->dup_expr();
|
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();
|
NetTaskDef* task_def();
|
||||||
NetFuncDef* func_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,
|
void set_line(perm_string file, perm_string def_file,
|
||||||
unsigned lineno, unsigned def_lineno);
|
unsigned lineno, unsigned def_lineno);
|
||||||
void set_line(perm_string file, unsigned lineno);
|
void set_line(perm_string file, unsigned lineno);
|
||||||
|
|
@ -3607,10 +3612,13 @@ class NetEBMult : public NetEBinary {
|
||||||
|
|
||||||
virtual NetEBMult* dup_expr() const;
|
virtual NetEBMult* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree();
|
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);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
||||||
private:
|
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 bool has_width() const;
|
||||||
virtual void expr_scan(struct expr_scan_t*) const;
|
virtual void expr_scan(struct expr_scan_t*) const;
|
||||||
virtual NetEConst* eval_tree();
|
virtual NetEConst* eval_tree();
|
||||||
|
virtual NetExpr*evaluate_function(const LineInfo&loc,
|
||||||
|
std::map<perm_string,NetExpr*>&ctx) const;
|
||||||
virtual NetESelect* dup_expr() const;
|
virtual NetESelect* dup_expr() const;
|
||||||
virtual NetNet*synthesize(Design*des, NetScope*scope, NetExpr*root);
|
virtual NetNet*synthesize(Design*des, NetScope*scope, NetExpr*root);
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
|
|
@ -3866,6 +3876,9 @@ class NetETernary : public NetExpr {
|
||||||
virtual NetETernary* dup_expr() const;
|
virtual NetETernary* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree();
|
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 ivl_variable_type_t expr_type() const;
|
||||||
virtual NexusSet* nex_input(bool rem_out = true);
|
virtual NexusSet* nex_input(bool rem_out = true);
|
||||||
virtual void expr_scan(struct expr_scan_t*) const;
|
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);
|
static bool test_operand_compat(ivl_variable_type_t tru, ivl_variable_type_t fal);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NetExpr* blended_arguments_(const NetExpr*t, const NetExpr*f) const;
|
||||||
|
|
||||||
NetExpr*cond_;
|
NetExpr*cond_;
|
||||||
NetExpr*true_val_;
|
NetExpr*true_val_;
|
||||||
NetExpr*false_val_;
|
NetExpr*false_val_;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue