Skip to content

Commit

Permalink
functional backend: topological sort starts with the output and next …
Browse files Browse the repository at this point in the history
…states nodes, other nodes get deleted
  • Loading branch information
aiju committed Jul 25, 2024
1 parent 4a860a0 commit 5ba566a
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 28 deletions.
10 changes: 4 additions & 6 deletions backends/functional/test_generic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,24 @@ struct FunctionalTestGeneric : public Pass

size_t argidx = 1;
extra_args(args, argidx, design);

/*
MemContentsTest test(8, 16);
std::random_device seed_dev;
std::mt19937 rnd(23); //seed_dev());
test.run(rnd, 1000);

/*
*/

for (auto module : design->selected_modules()) {
log("Dumping module `%s'.\n", module->name.c_str());
auto fir = FunctionalIR::from_module(module);
for(auto node : fir)
std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n";
for(auto [name, sort] : fir.outputs())
std::cout << RTLIL::unescape_id(name) << " = " << RTLIL::unescape_id(fir.get_output_node(name).name()) << "\n";
std::cout << "output " << RTLIL::unescape_id(name) << " = " << RTLIL::unescape_id(fir.get_output_node(name).name()) << "\n";
for(auto [name, sort] : fir.state())
std::cout << RTLIL::unescape_id(name) << " = " << RTLIL::unescape_id(fir.get_state_next_node(name).name()) << "\n";
std::cout << "state " << RTLIL::unescape_id(name) << " = " << RTLIL::unescape_id(fir.get_state_next_node(name).name()) << "\n";
}
*/
}
} FunctionalCxxBackend;

Expand Down
18 changes: 17 additions & 1 deletion kernel/functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,19 @@ struct ComputeGraph
return added;
}

void compact_args()
{
std::vector<int> new_args;
for (auto &node : nodes)
{
int new_offset = GetSize(new_args);
for (int i = 0; i < node.arg_count; i++)
new_args.push_back(args[node.arg_offset + i]);
node.arg_offset = new_offset;
}
std::swap(args, new_args);
}

void permute(std::vector<int> const &perm)
{
log_assert(perm.size() <= nodes.size());
Expand All @@ -276,7 +289,7 @@ struct ComputeGraph
for (int i = 0; i < GetSize(perm); ++i)
{
int j = perm[i];
log_assert(j >= 0 && j < GetSize(perm));
log_assert(j >= 0 && j < GetSize(nodes));
log_assert(inv_perm[j] == -1);
inv_perm[j] = i;
}
Expand All @@ -301,15 +314,18 @@ struct ComputeGraph
std::swap(nodes, new_nodes);
std::swap(sparse_attrs, new_sparse_attrs);

compact_args();
for (int &arg : args)
{
log_assert(arg < GetSize(inv_perm));
log_assert(inv_perm[arg] >= 0);
arg = inv_perm[arg];
}

for (auto &key : keys_)
{
log_assert(key.second < GetSize(inv_perm));
log_assert(inv_perm[key.second] >= 0);
key.second = inv_perm[key.second];
}
}
Expand Down
20 changes: 14 additions & 6 deletions kernel/functionalir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -657,19 +657,27 @@ void FunctionalIR::topological_sort() {
Graph::SccAdaptor compute_graph_scc(_graph);
bool scc = false;
std::vector<int> perm;
topo_sorted_sccs(compute_graph_scc, [&](int *begin, int *end) {
TopoSortedSccs toposort(compute_graph_scc, [&](int *begin, int *end) {
perm.insert(perm.end(), begin, end);
if (end > begin + 1)
{
log_warning("SCC:");
for (int *i = begin; i != end; ++i)
log(" %d", *i);
log_warning("Combinational loop:\n");
for (int *i = begin; i != end; ++i) {
Node node(_graph[*i]);
log("- %s = %s\n", RTLIL::unescape_id(node.name()).c_str(), node.to_string().c_str());
}
log("\n");
scc = true;
}
}, /* sources_first */ true);
});
for(const auto &[name, sort]: _state_sorts)
toposort.process(get_state_next_node(name).id());
for(const auto &[name, sort]: _output_sorts)
toposort.process(get_output_node(name).id());
// any nodes untouched by this point are dead code and will be removed by permute
_graph.permute(perm);
if(scc) log_error("combinational loops, aborting\n");
if(scc) log_error("The design contains combinational loops. This is not supported by the functional backend. "
"Try `scc -select; simplemap; select -clear` to avoid this error.\n");
}

static IdString merge_name(IdString a, IdString b) {
Expand Down
38 changes: 25 additions & 13 deletions kernel/topo_scc.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ class IntGraph {
};

template<typename G, typename ComponentCallback>
void topo_sorted_sccs(G &graph, ComponentCallback component, bool sources_first = false)
class TopoSortedSccs
{
typedef typename G::node_enumerator node_enumerator;
typedef typename G::successor_enumerator successor_enumerator;
Expand All @@ -210,14 +210,20 @@ void topo_sorted_sccs(G &graph, ComponentCallback component, bool sources_first
{}
};

G &graph;
ComponentCallback component;

std::vector<dfs_entry> dfs_stack;
std::vector<node_type> component_stack;
int next_index = 0;

public:
TopoSortedSccs(G &graph, ComponentCallback component)
: graph(graph), component(component) {}

node_enumerator nodes = graph.enumerate_nodes();

if (sources_first) {
// process all sources (nodes without a successor)
TopoSortedSccs &process_sources() {
node_enumerator nodes = graph.enumerate_nodes();
while (!nodes.finished()) {
node_type node = nodes.next();
successor_enumerator successors = graph.enumerate_successors(node);
Expand All @@ -231,16 +237,23 @@ void topo_sorted_sccs(G &graph, ComponentCallback component, bool sources_first
graph.dfs_index(node) = INT_MAX;
}
}
nodes = graph.enumerate_nodes();
return *this;
}

// iterate over all nodes to ensure we process the whole graph
while (!nodes.finished()) {
node_type node = nodes.next();
// process all remaining nodes in the graph
TopoSortedSccs &process_all() {
node_enumerator nodes = graph.enumerate_nodes();
// iterate over all nodes to ensure we process the whole graph
while (!nodes.finished())
process(nodes.next());
return *this;
}

// process all nodes that are reachable from a given start node
TopoSortedSccs &process(node_type node) {
// only start a new search if the node wasn't visited yet
if (graph.dfs_index(node) >= 0)
continue;

return *this;
while (true) {
// at this point we're visiting the node for the first time during
// the DFS search
Expand Down Expand Up @@ -299,7 +312,7 @@ void topo_sorted_sccs(G &graph, ComponentCallback component, bool sources_first
// continues the search at the parent node or returns to
// the outer loop if we already are at the root node.
if (dfs_stack.empty())
goto next_search;
return *this;
auto &dfs_top = dfs_stack.back();

node = dfs_top.node;
Expand Down Expand Up @@ -336,9 +349,8 @@ void topo_sorted_sccs(G &graph, ComponentCallback component, bool sources_first
}
}
}
next_search:;
}
}
};

YOSYS_NAMESPACE_END

Expand Down
4 changes: 2 additions & 2 deletions passes/cmds/example_dt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ struct ExampleDtPass : public Pass


std::vector<int> perm;
topo_sorted_sccs(compute_graph_scc, [&](int *begin, int *end) {
TopoSortedSccs(compute_graph_scc, [&](int *begin, int *end) {
perm.insert(perm.end(), begin, end);
if (end > begin + 1)
{
Expand All @@ -192,7 +192,7 @@ struct ExampleDtPass : public Pass
log(" %d", *i);
log("\n");
}
}, /* sources_first */ true);
}).process_sources().process_all();
compute_graph.permute(perm);


Expand Down

0 comments on commit 5ba566a

Please sign in to comment.