Handle some cases of self-determined repeat concatenations.
The test_width for repeat-concatenations is tricky because it requires the evaluated value for the repeat expression. It should be OK to call elab_and_eval on that expression even during the test_width for the containing expression. We'll see.
This commit is contained in:
parent
5ae86bd6b4
commit
d94e65de4f
2
PExpr.h
2
PExpr.h
|
|
@ -183,7 +183,7 @@ class PEConcat : public PExpr {
|
||||||
std::valarray<unsigned>tested_widths_;
|
std::valarray<unsigned>tested_widths_;
|
||||||
|
|
||||||
PExpr*repeat_;
|
PExpr*repeat_;
|
||||||
|
NetExpr*repeat_expr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
34
elab_expr.cc
34
elab_expr.cc
|
|
@ -1523,17 +1523,35 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repeat_) {
|
if (repeat_) {
|
||||||
// The repeat expression is self-determined and its own type.
|
unsigned repeat_count = 1;
|
||||||
|
|
||||||
|
// The repeat expression is self-determined and
|
||||||
|
// its own type.
|
||||||
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
|
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
|
||||||
bool tmp_flag = false;
|
bool tmp_flag = false;
|
||||||
repeat_->test_width(des, scope, 0, 0, tmp_type, tmp_flag);
|
repeat_->test_width(des, scope, 0, 0, tmp_type, tmp_flag);
|
||||||
|
|
||||||
count_width = 0;
|
// Try to evaluate the repeat expression now, so
|
||||||
|
// that we can give the caller an accurate
|
||||||
|
// expression width.
|
||||||
|
repeat_expr_ = elab_and_eval(des, scope, repeat_, -1);
|
||||||
|
if (NetEConst*tmp_c = dynamic_cast<NetEConst*> (repeat_expr_)) {
|
||||||
|
repeat_count = tmp_c->value().as_ulong();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Gack! Can't evaluate expression yet!
|
||||||
|
// Unfortunately, it is possible that this
|
||||||
|
// expression may turn out to be constant later in
|
||||||
|
// elaboration, so we can't really get away with
|
||||||
|
// reporting an error.
|
||||||
|
repeat_count = 1;
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
<< "CONCAT MISSING TEST_WIDTH WHEN REPEAT IS PRESENT!"
|
<< "CONCAT MISSING TEST_WIDTH WHEN REPEAT IS PRESENT!"
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
count_width *= repeat_count;
|
||||||
|
}
|
||||||
|
|
||||||
expr_type__ = expr_type_;
|
expr_type__ = expr_type_;
|
||||||
unsized_flag = false;
|
unsized_flag = false;
|
||||||
|
|
@ -1557,8 +1575,18 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
/* If there is a repeat expression, then evaluate the constant
|
/* If there is a repeat expression, then evaluate the constant
|
||||||
value and set the repeat count. */
|
value and set the repeat count. */
|
||||||
if (repeat_) {
|
if (repeat_) {
|
||||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1);
|
NetExpr*tmp;
|
||||||
|
if (repeat_expr_ == 0) {
|
||||||
|
// If the expression has not yet been elaborated,
|
||||||
|
// then try now.
|
||||||
|
tmp = elab_and_eval(des, scope, repeat_, -1);
|
||||||
assert(tmp);
|
assert(tmp);
|
||||||
|
} else {
|
||||||
|
// If it has been elaborated, make sure it is
|
||||||
|
// fully evaluated.
|
||||||
|
tmp = repeat_expr_;
|
||||||
|
eval_expr(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
if (tmp->expr_type() == IVL_VT_REAL) {
|
if (tmp->expr_type() == IVL_VT_REAL) {
|
||||||
cerr << tmp->get_fileline() << ": error: concatenation "
|
cerr << tmp->get_fileline() << ": error: concatenation "
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue