From 691418e13a086c096373df13f7302323721faf35 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Sep 2020 17:16:10 +0000 Subject: cxxrtl: expose driver kind in debug information. This can be useful to determine whether the wire should be a part of a design checkpoint, whether it can be used to override design state, and whether driving it may cause a conflict. --- backends/cxxrtl/cxxrtl_backend.cc | 68 +++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 7 deletions(-) (limited to 'backends/cxxrtl/cxxrtl_backend.cc') diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 00b2ed315..dfea04409 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -273,6 +273,7 @@ struct FlowGraph { std::vector nodes; dict> wire_comb_defs, wire_sync_defs, wire_uses; dict wire_def_elidable, wire_use_elidable; + dict bit_has_state; ~FlowGraph() { @@ -294,6 +295,8 @@ struct FlowGraph { wire_comb_defs[chunk.wire].insert(node); } } + for (auto bit : sig.bits()) + bit_has_state[bit] |= is_ff; // Only comb defs of an entire wire in the right order can be elided. if (!is_ff && sig.is_wire()) wire_def_elidable[sig.as_wire()] = elidable; @@ -550,6 +553,7 @@ struct CxxrtlWorker { pool localized_wires; dict debug_alias_wires; dict debug_const_wires; + dict bit_has_state; dict> blackbox_specializations; dict eval_converges; @@ -1636,6 +1640,10 @@ struct CxxrtlWorker { size_t count_alias_wires = 0; size_t count_member_wires = 0; size_t count_skipped_wires = 0; + size_t count_driven_sync = 0; + size_t count_driven_comb = 0; + size_t count_undriven = 0; + size_t count_mixed_driver = 0; inc_indent(); f << indent << "assert(path.empty() || path[path.size() - 1] == ' ');\n"; for (auto wire : module->wires()) { @@ -1661,15 +1669,54 @@ struct CxxrtlWorker { count_alias_wires++; } else if (!localized_wires.count(wire)) { // Member wire - f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); - f << ", debug_item(" << mangle(wire) << ", "; - f << wire->start_offset; + std::vector flags; + if (wire->port_input && wire->port_output) - f << ", debug_item::INOUT"; + flags.push_back("INOUT"); else if (wire->port_input) - f << ", debug_item::INPUT"; + flags.push_back("INPUT"); else if (wire->port_output) - f << ", debug_item::OUTPUT"; + flags.push_back("OUTPUT"); + + bool has_driven_sync = false; + bool has_driven_comb = false; + bool has_undriven = false; + SigSpec sig(wire); + for (auto bit : sig.bits()) + if (!bit_has_state.count(bit)) + has_undriven = true; + else if (bit_has_state[bit]) + has_driven_sync = true; + else + has_driven_comb = true; + if (has_driven_sync) + flags.push_back("DRIVEN_SYNC"); + if (has_driven_sync && !has_driven_comb && !has_undriven) + count_driven_sync++; + if (has_driven_comb) + flags.push_back("DRIVEN_COMB"); + if (!has_driven_sync && has_driven_comb && !has_undriven) + count_driven_comb++; + if (has_undriven) + flags.push_back("UNDRIVEN"); + if (!has_driven_sync && !has_driven_comb && has_undriven) + count_undriven++; + if (has_driven_sync + has_driven_comb + has_undriven > 1) + count_mixed_driver++; + + f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); + f << ", debug_item(" << mangle(wire) << ", "; + f << wire->start_offset; + bool first = true; + for (auto flag : flags) { + if (first) { + first = false; + f << ", "; + } else { + f << "|"; + } + f << "debug_item::" << flag; + } f << "));\n"; count_member_wires++; } else { @@ -1698,7 +1745,11 @@ struct CxxrtlWorker { log_debug(" Public wires: %zu, of which:\n", count_public_wires); log_debug(" Const wires: %zu\n", count_const_wires); log_debug(" Alias wires: %zu\n", count_alias_wires); - log_debug(" Member wires: %zu\n", count_member_wires); + log_debug(" Member wires: %zu, of which:\n", count_member_wires); + log_debug(" Driven sync: %zu\n", count_driven_sync); + log_debug(" Driven comb: %zu\n", count_driven_comb); + log_debug(" Undriven: %zu\n", count_undriven); + log_debug(" Mixed driver: %zu\n", count_mixed_driver); log_debug(" Other wires: %zu (no debug information)\n", count_skipped_wires); } @@ -2217,6 +2268,9 @@ struct CxxrtlWorker { eval_converges[module] = feedback_wires.empty() && buffered_comb_wires.empty(); + for (auto item : flow.bit_has_state) + bit_has_state.insert(item); + if (debug_info) { // Find wires that alias other wires or are tied to a constant; debug information can be enriched with these // at essentially zero additional cost. -- cgit v1.2.3