cxxrtl: allow `always` sync rules in debug_eval.

These can be produced from `always @*` processes, if `-noproc`
is used.
This commit is contained in:
whitequark 2021-03-07 14:28:45 +00:00
parent 3d2aef0bde
commit d1de08e38a
1 changed files with 25 additions and 17 deletions

View File

@ -1415,30 +1415,30 @@ struct CxxrtlWorker {
collect_sigspec_rhs(port.second, for_debug, cells); collect_sigspec_rhs(port.second, for_debug, cells);
} }
void dump_assign(const RTLIL::SigSig &sigsig) void dump_assign(const RTLIL::SigSig &sigsig, bool for_debug = false)
{ {
f << indent; f << indent;
dump_sigspec_lhs(sigsig.first); dump_sigspec_lhs(sigsig.first, for_debug);
f << " = "; f << " = ";
dump_sigspec_rhs(sigsig.second); dump_sigspec_rhs(sigsig.second, for_debug);
f << ";\n"; f << ";\n";
} }
void dump_case_rule(const RTLIL::CaseRule *rule) void dump_case_rule(const RTLIL::CaseRule *rule, bool for_debug = false)
{ {
for (auto action : rule->actions) for (auto action : rule->actions)
dump_assign(action); dump_assign(action, for_debug);
for (auto switch_ : rule->switches) for (auto switch_ : rule->switches)
dump_switch_rule(switch_); dump_switch_rule(switch_, for_debug);
} }
void dump_switch_rule(const RTLIL::SwitchRule *rule) void dump_switch_rule(const RTLIL::SwitchRule *rule, bool for_debug = false)
{ {
// The switch attributes are printed before the switch condition is captured. // The switch attributes are printed before the switch condition is captured.
dump_attrs(rule); dump_attrs(rule);
std::string signal_temp = fresh_temporary(); std::string signal_temp = fresh_temporary();
f << indent << "const value<" << rule->signal.size() << "> &" << signal_temp << " = "; f << indent << "const value<" << rule->signal.size() << "> &" << signal_temp << " = ";
dump_sigspec(rule->signal, /*is_lhs=*/false); dump_sigspec(rule->signal, /*is_lhs=*/false, for_debug);
f << ";\n"; f << ";\n";
bool first = true; bool first = true;
@ -1458,7 +1458,7 @@ struct CxxrtlWorker {
first = false; first = false;
if (compare.is_fully_def()) { if (compare.is_fully_def()) {
f << signal_temp << " == "; f << signal_temp << " == ";
dump_sigspec(compare, /*is_lhs=*/false); dump_sigspec(compare, /*is_lhs=*/false, for_debug);
} else if (compare.is_fully_const()) { } else if (compare.is_fully_const()) {
RTLIL::Const compare_mask, compare_value; RTLIL::Const compare_mask, compare_value;
for (auto bit : compare.as_const()) { for (auto bit : compare.as_const()) {
@ -1492,26 +1492,28 @@ struct CxxrtlWorker {
} }
f << "{\n"; f << "{\n";
inc_indent(); inc_indent();
dump_case_rule(case_); dump_case_rule(case_, for_debug);
dec_indent(); dec_indent();
} }
f << indent << "}\n"; f << indent << "}\n";
} }
void dump_process_case(const RTLIL::Process *proc) void dump_process_case(const RTLIL::Process *proc, bool for_debug = false)
{ {
dump_attrs(proc); dump_attrs(proc);
f << indent << "// process " << proc->name.str() << " case\n"; f << indent << "// process " << proc->name.str() << " case\n";
// The case attributes (for root case) are always empty. // The case attributes (for root case) are always empty.
log_assert(proc->root_case.attributes.empty()); log_assert(proc->root_case.attributes.empty());
dump_case_rule(&proc->root_case); dump_case_rule(&proc->root_case, for_debug);
} }
void dump_process_syncs(const RTLIL::Process *proc) void dump_process_syncs(const RTLIL::Process *proc, bool for_debug = false)
{ {
dump_attrs(proc); dump_attrs(proc);
f << indent << "// process " << proc->name.str() << " syncs\n"; f << indent << "// process " << proc->name.str() << " syncs\n";
for (auto sync : proc->syncs) { for (auto sync : proc->syncs) {
log_assert(!for_debug || sync->type == RTLIL::STa);
RTLIL::SigBit sync_bit; RTLIL::SigBit sync_bit;
if (!sync->signal.empty()) { if (!sync->signal.empty()) {
sync_bit = sync->signal[0]; sync_bit = sync->signal[0];
@ -1556,7 +1558,7 @@ struct CxxrtlWorker {
f << ") {\n"; f << ") {\n";
inc_indent(); inc_indent();
for (auto action : sync->actions) for (auto action : sync->actions)
dump_assign(action); dump_assign(action, for_debug);
dec_indent(); dec_indent();
f << indent << "}\n"; f << indent << "}\n";
} }
@ -1725,12 +1727,12 @@ struct CxxrtlWorker {
case FlowGraph::Node::Type::CELL_EVAL: case FlowGraph::Node::Type::CELL_EVAL:
dump_cell_eval(node.cell); dump_cell_eval(node.cell);
break; break;
case FlowGraph::Node::Type::PROCESS_SYNC:
dump_process_syncs(node.process);
break;
case FlowGraph::Node::Type::PROCESS_CASE: case FlowGraph::Node::Type::PROCESS_CASE:
dump_process_case(node.process); dump_process_case(node.process);
break; break;
case FlowGraph::Node::Type::PROCESS_SYNC:
dump_process_syncs(node.process);
break;
} }
} }
} }
@ -1754,6 +1756,12 @@ struct CxxrtlWorker {
case FlowGraph::Node::Type::CELL_EVAL: case FlowGraph::Node::Type::CELL_EVAL:
dump_cell_eval(node.cell, /*for_debug=*/true); dump_cell_eval(node.cell, /*for_debug=*/true);
break; break;
case FlowGraph::Node::Type::PROCESS_CASE:
dump_process_case(node.process, /*for_debug=*/true);
break;
case FlowGraph::Node::Type::PROCESS_SYNC:
dump_process_syncs(node.process, /*for_debug=*/true);
break;
default: default:
log_abort(); log_abort();
} }