diff --git a/passes/hierarchy/flatten.cc b/passes/hierarchy/flatten.cc index 29e7205ee..06ce6aa15 100644 --- a/passes/hierarchy/flatten.cc +++ b/passes/hierarchy/flatten.cc @@ -77,6 +77,7 @@ struct FlattenWorker bool create_scopeinfo = true; bool create_scopename = false; std::string separator = "."; + bool barriers = false; template void map_attributes(RTLIL::Cell *cell, T *object, IdString orig_object_name) @@ -263,7 +264,27 @@ struct FlattenWorker log_error("Cell port %s.%s.%s is driving constant bits: %s <= %s\n", module, cell, port_it.first.unescape(), log_signal(new_conn.first), log_signal(new_conn.second)); - module->connect(new_conn); + if (barriers) { + // Drive public output wires with barriers and the rest with + // connections + RTLIL::SigSig skip_conn, barrier_conn; + + for (int i = 0; i < GetSize(new_conn.first); i++) { + const auto lhs = new_conn.first[i], rhs = new_conn.second[i]; + auto& sigsig = !lhs.is_wire() || !lhs.wire->name.isPublic() ? skip_conn : barrier_conn; + sigsig.first.append(lhs); + sigsig.second.append(rhs); + } + + if (!skip_conn.first.empty()) + module->connect(skip_conn); + + if (!barrier_conn.first.empty()) + module->addBarrier(NEW_ID, barrier_conn.second, barrier_conn.first); + } else { + module->connect(new_conn); + } + sigmap.add(new_conn.first, new_conn.second); } @@ -369,6 +390,10 @@ struct FlattenPass : public Pass { log(" Don't remove unused submodules, leave a flattened version of each\n"); log(" submodule in the design.\n"); log("\n"); + log(" -barriers\n"); + log(" Introduce an optimization barrier (a $barrier cell) when a flattened\n"); + log(" module drives a public wire.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { @@ -402,6 +427,9 @@ struct FlattenPass : public Pass { } if (args[argidx] == "-nocleanup") { cleanup = false; + } + if (args[argidx] == "-barriers") { + worker.barriers = true; continue; } break;