mirror of https://github.com/YosysHQ/yosys.git
cxxrtl: emit debug information for alias wires.
Alias wires can represent a significant chunk of the design in highly hierarchical designs; in Minerva SRAM, there are 273 member wires and 527 alias wires. Showing them in every hierarchy level significantly improves usability.
This commit is contained in:
parent
a0466e1a96
commit
9b39c6f744
|
@ -539,6 +539,7 @@ struct CxxrtlWorker {
|
||||||
dict<const RTLIL::Wire*, FlowGraph::Node> elided_wires;
|
dict<const RTLIL::Wire*, FlowGraph::Node> elided_wires;
|
||||||
dict<const RTLIL::Module*, std::vector<FlowGraph::Node>> schedule;
|
dict<const RTLIL::Module*, std::vector<FlowGraph::Node>> schedule;
|
||||||
pool<const RTLIL::Wire*> localized_wires;
|
pool<const RTLIL::Wire*> localized_wires;
|
||||||
|
dict<const RTLIL::Wire*, const RTLIL::Wire*> debug_alias_wires;
|
||||||
dict<const RTLIL::Module*, pool<std::string>> blackbox_specializations;
|
dict<const RTLIL::Module*, pool<std::string>> blackbox_specializations;
|
||||||
dict<const RTLIL::Module*, bool> eval_converges;
|
dict<const RTLIL::Module*, bool> eval_converges;
|
||||||
|
|
||||||
|
@ -1606,15 +1607,29 @@ struct CxxrtlWorker {
|
||||||
|
|
||||||
void dump_debug_info_method(RTLIL::Module *module)
|
void dump_debug_info_method(RTLIL::Module *module)
|
||||||
{
|
{
|
||||||
|
size_t count_member_wires = 0;
|
||||||
|
size_t count_alias_wires = 0;
|
||||||
|
size_t count_skipped_wires = 0;
|
||||||
inc_indent();
|
inc_indent();
|
||||||
f << indent << "assert(path.empty() || path[path.size() - 1] == ' ');\n";
|
f << indent << "assert(path.empty() || path[path.size() - 1] == ' ');\n";
|
||||||
for (auto wire : module->wires()) {
|
for (auto wire : module->wires()) {
|
||||||
if (wire->name[0] != '\\')
|
if (wire->name[0] != '\\')
|
||||||
continue;
|
continue;
|
||||||
if (localized_wires.count(wire))
|
if (debug_alias_wires.count(wire)) {
|
||||||
|
// Alias of a member wire
|
||||||
|
f << indent << "items.emplace(path + " << escape_cxx_string(get_hdl_name(wire));
|
||||||
|
f << ", debug_item(" << mangle(debug_alias_wires[wire]) << "));\n";
|
||||||
|
count_alias_wires++;
|
||||||
continue;
|
continue;
|
||||||
f << indent << "items.emplace(path + " << escape_cxx_string(get_hdl_name(wire));
|
}
|
||||||
f << ", debug_item(" << mangle(wire) << "));\n";
|
if (!localized_wires.count(wire)) {
|
||||||
|
// Member wire
|
||||||
|
f << indent << "items.emplace(path + " << escape_cxx_string(get_hdl_name(wire));
|
||||||
|
f << ", debug_item(" << mangle(wire) << "));\n";
|
||||||
|
count_member_wires++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
count_skipped_wires++;
|
||||||
}
|
}
|
||||||
for (auto &memory_it : module->memories) {
|
for (auto &memory_it : module->memories) {
|
||||||
if (memory_it.first[0] != '\\')
|
if (memory_it.first[0] != '\\')
|
||||||
|
@ -1630,6 +1645,11 @@ struct CxxrtlWorker {
|
||||||
f << "path + " << escape_cxx_string(get_hdl_name(cell) + ' ') << ");\n";
|
f << "path + " << escape_cxx_string(get_hdl_name(cell) + ' ') << ");\n";
|
||||||
}
|
}
|
||||||
dec_indent();
|
dec_indent();
|
||||||
|
|
||||||
|
log_debug("Debug information statistics for module %s:\n", log_id(module));
|
||||||
|
log_debug(" Member wires: %zu\n", count_member_wires);
|
||||||
|
log_debug(" Alias wires: %zu\n", count_alias_wires);
|
||||||
|
log_debug(" Other wires: %zu (no debug information)\n", count_skipped_wires);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map)
|
void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map)
|
||||||
|
@ -2141,6 +2161,38 @@ struct CxxrtlWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_converges[module] = feedback_wires.empty() && buffered_wires.empty();
|
eval_converges[module] = feedback_wires.empty() && buffered_wires.empty();
|
||||||
|
|
||||||
|
if (debug_info) {
|
||||||
|
// Find wires that alias other wires; debug information can be enriched with these at essentially zero
|
||||||
|
// additional cost.
|
||||||
|
//
|
||||||
|
// Note that the information collected here can't be used for optimizing the netlist: debug information queries
|
||||||
|
// are pure and run on a design in a stable state, which allows assumptions that do not otherwise hold.
|
||||||
|
for (auto wire : module->wires()) {
|
||||||
|
if (wire->name[0] != '\\')
|
||||||
|
continue;
|
||||||
|
if (!localized_wires[wire])
|
||||||
|
continue;
|
||||||
|
const RTLIL::Wire *wire_it = wire;
|
||||||
|
while (1) {
|
||||||
|
if (!(flow.wire_def_elidable.count(wire_it) && flow.wire_def_elidable[wire_it]))
|
||||||
|
break; // not an alias: complex def
|
||||||
|
log_assert(flow.wire_comb_defs[wire_it].size() == 1);
|
||||||
|
FlowGraph::Node *node = *flow.wire_comb_defs[wire_it].begin();
|
||||||
|
if (node->connect.second.is_wire()) {
|
||||||
|
RTLIL::Wire *rhs_wire = node->connect.second.as_wire();
|
||||||
|
if (localized_wires[rhs_wire]) {
|
||||||
|
wire_it = rhs_wire; // maybe an alias
|
||||||
|
} else {
|
||||||
|
debug_alias_wires[wire] = rhs_wire; // is an alias
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break; // not an alias: complex rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (has_feedback_arcs || has_buffered_wires) {
|
if (has_feedback_arcs || has_buffered_wires) {
|
||||||
// Although both non-feedback buffered combinatorial wires and apparent feedback wires may be eliminated
|
// Although both non-feedback buffered combinatorial wires and apparent feedback wires may be eliminated
|
||||||
|
|
Loading…
Reference in New Issue