From 754899c99e9ea73c6edf7f4f5a56fdca228df0ae Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 9 Nov 2014 20:11:03 +0000 Subject: [PATCH] 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. --- synth2.cc | 60 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/synth2.cc b/synth2.cc index dcc80895d..22c191b56 100644 --- a/synth2.cc +++ b/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. */ - unsigned long max_guard_value = 0; mapstatement_map; NetProc*statement_default = 0; @@ -395,28 +394,48 @@ bool NetCase::synth_async(Design*des, NetScope*scope, } NetEConst*ge = dynamic_cast(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); 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; - - if (sel_idx > max_guard_value) - max_guard_value = sel_idx; } - // The mux_size is the number of inputs that are selected. - unsigned mux_size = max_guard_value + 1; - - // If the sel_width can select more than just the explicit - // guard values, and there is a default statement, then adjust - // the mux size to allow for the implicit selections. - if (statement_default && ((1U< mux_size)) { - mux_size = 1<errors += 1; + return false; } + 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 link it in wherever it is needed. */ @@ -481,12 +500,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, continue; } - if (stmt == 0) { - cerr << get_fileline() << ": error: case " << idx - << " is not accounted for in asynchronous mux." << endl; - des->errors += 1; - continue; - } + ivl_assert(*this, stmt); NetBus accumulated_tmp (scope, nex_map.size()); 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)) { - cerr << top->get_fileline() << ": internal error: " - << "is_asynchronous does not match " - << "sync_async results." << endl; + cerr << top->get_fileline() << ": error: " + << "failed to synthesize asynchronous " + << "logic for this process." << endl; des->errors += 1; return; }