Make asynchronous case statement synthesis more robust.
Added various error/warning messages for behaviour not supported in synthesis. Also give correct behaviour when multiple case item expressions evaluate to the same constant value.
This commit is contained in:
parent
4e94b81a4b
commit
754899c99e
60
synth2.cc
60
synth2.cc
|
|
@ -384,7 +384,6 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||||
index of the mux value, and the statement is bound to that
|
index of the mux value, and the statement is bound to that
|
||||||
index. */
|
index. */
|
||||||
|
|
||||||
unsigned long max_guard_value = 0;
|
|
||||||
map<unsigned long,NetProc*>statement_map;
|
map<unsigned long,NetProc*>statement_map;
|
||||||
NetProc*statement_default = 0;
|
NetProc*statement_default = 0;
|
||||||
|
|
||||||
|
|
@ -395,28 +394,48 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEConst*ge = dynamic_cast<NetEConst*>(items_[item].guard);
|
NetEConst*ge = dynamic_cast<NetEConst*>(items_[item].guard);
|
||||||
|
if (ge == 0) {
|
||||||
|
cerr << items_[item].guard->get_fileline() << ": sorry: "
|
||||||
|
<< "variable case item expressions with a variable "
|
||||||
|
<< "case select expression are not supported in "
|
||||||
|
<< "synthesis. " << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ivl_assert(*this, ge);
|
ivl_assert(*this, ge);
|
||||||
verinum gval = ge->value();
|
verinum gval = ge->value();
|
||||||
|
|
||||||
unsigned sel_idx = gval.as_ulong();
|
unsigned long sel_idx = gval.as_ulong();
|
||||||
|
|
||||||
assert(items_[item].statement);
|
if (statement_map[sel_idx]) {
|
||||||
|
cerr << ge->get_fileline() << ": warning: duplicate case "
|
||||||
|
<< "value '" << sel_idx << "' detected. This case is "
|
||||||
|
<< "unreachable." << endl;
|
||||||
|
delete items_[item].statement;
|
||||||
|
items_[item].statement = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ivl_assert(*this, items_[item].statement);
|
||||||
statement_map[sel_idx] = items_[item].statement;
|
statement_map[sel_idx] = items_[item].statement;
|
||||||
|
|
||||||
if (sel_idx > max_guard_value)
|
|
||||||
max_guard_value = sel_idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The mux_size is the number of inputs that are selected.
|
if (!statement_default && (statement_map.size() != ((size_t)1 << sel_width))) {
|
||||||
unsigned mux_size = max_guard_value + 1;
|
cerr << get_fileline() << ": sorry: Latch inferred from "
|
||||||
|
<< "incomplete case statement. This is not supported "
|
||||||
// If the sel_width can select more than just the explicit
|
<< "in synthesis." << endl;
|
||||||
// guard values, and there is a default statement, then adjust
|
des->errors += 1;
|
||||||
// the mux size to allow for the implicit selections.
|
return false;
|
||||||
if (statement_default && ((1U<<sel_width) > mux_size)) {
|
|
||||||
mux_size = 1<<sel_width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sel_width >= 8*sizeof(unsigned)) {
|
||||||
|
cerr << get_fileline() << ": sorry: mux select width of "
|
||||||
|
<< sel_width << " bits is too large for synthesis." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned mux_size = 1U << sel_width;
|
||||||
|
|
||||||
/* If there is a default clause, synthesize it once and we'll
|
/* If there is a default clause, synthesize it once and we'll
|
||||||
link it in wherever it is needed. */
|
link it in wherever it is needed. */
|
||||||
|
|
@ -481,12 +500,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (stmt == 0) {
|
ivl_assert(*this, stmt);
|
||||||
cerr << get_fileline() << ": error: case " << idx
|
|
||||||
<< " is not accounted for in asynchronous mux." << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetBus accumulated_tmp (scope, nex_map.size());
|
NetBus accumulated_tmp (scope, nex_map.size());
|
||||||
for (unsigned pin = 0 ; pin < nex_map.size() ; pin += 1)
|
for (unsigned pin = 0 ; pin < nex_map.size() ; pin += 1)
|
||||||
|
|
@ -1785,9 +1799,9 @@ void synth2_f::process(Design*des, NetProcTop*top)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! top->synth_async(des)) {
|
if (! top->synth_async(des)) {
|
||||||
cerr << top->get_fileline() << ": internal error: "
|
cerr << top->get_fileline() << ": error: "
|
||||||
<< "is_asynchronous does not match "
|
<< "failed to synthesize asynchronous "
|
||||||
<< "sync_async results." << endl;
|
<< "logic for this process." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue