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:
Martin Whitaker 2014-11-09 20:11:03 +00:00
parent 4e94b81a4b
commit 754899c99e
1 changed files with 37 additions and 23 deletions

View File

@ -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;
} }