Further support for constant functions.

Add support for case, forever, and repeat statements in constant
functions. Also fix a bug in the constant function implementation
of NetESelect when used for zero/sign extension.
This commit is contained in:
Martin Whitaker 2013-04-07 19:13:30 +01:00
parent 6da71fdf56
commit 23dbfabb1e
3 changed files with 195 additions and 4 deletions

View File

@ -2924,6 +2924,15 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
context_width += 1;
}
if (debug_elaborate) {
cerr << get_fileline() << ": debug: case context is ";
if (context_is_real) {
cerr << "real" << endl;
} else {
cerr << (context_unsigned ? "unsigned" : "signed")
<< " vector, width=" << context_width << endl;
}
}
NetExpr*expr = elab_and_eval_case(des, scope, expr_,
context_is_real,
context_unsigned,

View File

@ -236,6 +236,121 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
return flag;
}
bool NetCase::evaluate_function_vect_(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
{
NetExpr*case_expr = expr_->evaluate_function(loc, context_map);
if (case_expr == 0)
return false;
NetEConst*case_const = dynamic_cast<NetEConst*> (case_expr);
ivl_assert(loc, case_const);
verinum case_val = case_const->value();
delete case_expr;
NetProc*default_statement = 0;
for (unsigned cnt = 0 ; cnt < nitems_ ; cnt += 1) {
Item*item = &items_[cnt];
if (item->guard == 0) {
default_statement = item->statement;
continue;
}
NetExpr*item_expr = item->guard->evaluate_function(loc, context_map);
if (item_expr == 0)
return false;
NetEConst*item_const = dynamic_cast<NetEConst*> (item_expr);
ivl_assert(loc, item_const);
verinum item_val = item_const->value();
delete item_expr;
ivl_assert(loc, item_val.len() == case_val.len());
bool match = true;
for (unsigned idx = 0 ; idx < item_val.len() ; idx += 1) {
verinum::V bit_a = case_val.get(idx);
verinum::V bit_b = item_val.get(idx);
if (bit_a == verinum::Vx && type_ == EQX) continue;
if (bit_b == verinum::Vx && type_ == EQX) continue;
if (bit_a == verinum::Vz && type_ != EQ) continue;
if (bit_b == verinum::Vz && type_ != EQ) continue;
if (bit_a != bit_b) {
match = false;
break;
}
}
if (!match) continue;
return item->statement->evaluate_function(loc, context_map);
}
if (default_statement)
return default_statement->evaluate_function(loc, context_map);
return true;
}
bool NetCase::evaluate_function_real_(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
{
NetExpr*case_expr = expr_->evaluate_function(loc, context_map);
if (case_expr == 0)
return false;
NetECReal*case_const = dynamic_cast<NetECReal*> (case_expr);
ivl_assert(loc, case_const);
double case_val = case_const->value().as_double();
delete case_expr;
NetProc*default_statement = 0;
for (unsigned cnt = 0 ; cnt < nitems_ ; cnt += 1) {
Item*item = &items_[cnt];
if (item->guard == 0) {
default_statement = item->statement;
continue;
}
NetExpr*item_expr = item->guard->evaluate_function(loc, context_map);
if (item_expr == 0)
return false;
NetECReal*item_const = dynamic_cast<NetECReal*> (item_expr);
ivl_assert(loc, item_const);
double item_val = item_const->value().as_double();
delete item_expr;
if (item_val != case_val) continue;
return item->statement->evaluate_function(loc, context_map);
}
if (default_statement)
return default_statement->evaluate_function(loc, context_map);
return true;
}
bool NetCase::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
{
if (expr_->expr_type() == IVL_VT_REAL)
return evaluate_function_real_(loc, context_map);
else
return evaluate_function_vect_(loc, context_map);
}
bool NetCondit::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
{
@ -264,6 +379,62 @@ bool NetDisable::evaluate_function(const LineInfo&,
return true;
}
bool NetForever::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
{
bool flag = true;
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: NetForever::evaluate_function: "
<< "Start loop" << endl;
}
while (flag && !disable) {
flag = flag && statement_->evaluate_function(loc, context_map);
}
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: NetForever::evaluate_function: "
<< "Done loop" << endl;
}
return flag;
}
bool NetRepeat::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
{
bool flag = true;
// Evaluate the condition expression to try and get the
// condition for the loop.
NetExpr*count_expr = expr_->evaluate_function(loc, context_map);
if (count_expr == 0) return false;
NetEConst*count_const = dynamic_cast<NetEConst*> (count_expr);
ivl_assert(loc, count_const);
long count = count_const->value().as_long();
delete count_expr;
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: NetRepeat::evaluate_function: "
<< "Repeating " << count << " times." << endl;
}
while ((count > 0) && flag && !disable) {
flag = flag && statement_->evaluate_function(loc, context_map);
count -= 1;
}
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: NetRepeat::evaluate_function: "
<< "Finished loop" << endl;
}
return flag;
}
bool NetSTask::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&) const
{
@ -399,6 +570,7 @@ NetExpr* NetESelect::evaluate_function(const LineInfo&loc,
base = base_const->value().as_long();
delete base_val;
} else {
sub.has_sign(has_sign());
sub = pad_to_width(sub, expr_width());
}

View File

@ -2692,8 +2692,14 @@ class NetCase : public NetProc {
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual bool evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
private:
bool evaluate_function_vect_(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
bool evaluate_function_real_(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
TYPE type_;
@ -3083,6 +3089,8 @@ class NetForever : public NetProc {
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual bool evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
private:
NetProc*statement_;
@ -3204,6 +3212,8 @@ class NetRepeat : public NetProc {
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual bool evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
private:
NetExpr*expr_;