dict<const RTLIL::Module*, std::vector<FlowGraph::Node>> schedule;
pool<const RTLIL::Wire*> localized_wires;
dict<const RTLIL::Module*, pool<std::string>> blackbox_specializations;
+ dict<const RTLIL::Module*, bool> eval_converges;
void inc_indent() {
indent += "\t";
dump_sigspec_rhs(conn.second);
f << ";\n";
}
- f << indent << mangle(cell) << access << "eval();\n";
+ f << indent << "converged &= " << mangle(cell) << access << "eval();\n";
for (auto conn : cell->connections()) {
if (conn.second.is_wire()) {
RTLIL::Wire *wire = conn.second.as_wire();
void dump_eval_method(RTLIL::Module *module)
{
inc_indent();
+ f << indent << "bool converged = " << (eval_converges.at(module) ? "true" : "false") << ";\n";
if (!module->get_bool_attribute(ID(cxxrtl.blackbox))) {
for (auto wire : module->wires())
dump_wire(wire, /*is_local_context=*/true);
}
}
}
+ f << indent << "return converged;\n";
dec_indent();
}
dump_wire(wire, /*is_local_context=*/false);
}
f << "\n";
- f << indent << "void eval() override {\n";
+ f << indent << "bool eval() override {\n";
dump_eval_method(module);
f << indent << "}\n";
f << "\n";
}
if (has_cells)
f << "\n";
- f << indent << "void eval() override;\n";
+ f << indent << "bool eval() override;\n";
f << indent << "bool commit() override;\n";
dec_indent();
f << indent << "}; // struct " << mangle(module) << "\n";
{
if (module->get_bool_attribute(ID(cxxrtl.blackbox)))
return;
- f << indent << "void " << mangle(module) << "::eval() {\n";
+ f << indent << "bool " << mangle(module) << "::eval() {\n";
dump_eval_method(module);
f << indent << "}\n";
f << "\n";
}
}
}
+
+ // Black boxes converge by default, since their implementations are quite unlikely to require
+ // internal propagation of comb signals.
+ eval_converges[module] = true;
continue;
}
// it is possible that a design with no feedback arcs would end up with doubly buffered wires in such cases
// as a wire with multiple drivers where one of them is combinatorial and the other is synchronous. Such designs
// also require more than one delta cycle to converge.
- pool<RTLIL::Wire*> buffered_wires;
+ pool<const RTLIL::Wire*> buffered_wires;
for (auto wire : module->wires()) {
if (flow.wire_comb_defs[wire].size() > 0 && !elided_wires.count(wire) && !localized_wires[wire]) {
if (!feedback_wires[wire])
for (auto wire : buffered_wires)
log(" %s\n", wire->name.c_str());
}
+
+ eval_converges[module] = feedback_wires.empty() && buffered_wires.empty();
}
if (has_feedback_arcs || has_buffered_wires) {
// Although both non-feedback buffered combinatorial wires and apparent feedback wires may be eliminated
log(" value<8> p_i_data;\n");
log(" wire<8> p_o_data;\n");
log("\n");
- log(" void eval() override;\n");
+ log(" bool eval() override;\n");
log(" bool commit() override;\n");
log("\n");
log(" static std::unique_ptr<bb_p_debug>\n");
log(" namespace cxxrtl_design {\n");
log("\n");
log(" struct stderr_debug : public bb_p_debug {\n");
- log(" void eval() override {\n");
+ log(" bool eval() override {\n");
log(" if (posedge_p_clk() && p_en)\n");
log(" fprintf(stderr, \"debug: %%02x\\n\", p_i_data.data[0]);\n");
log(" p_o_data.next = p_i_data;\n");
- log(" bb_p_debug::eval();\n");
+ log(" return bb_p_debug::eval();\n");
log(" }\n");
log(" };\n");
log("\n");