mirror of https://github.com/YosysHQ/yosys.git
Collect chains via TopoSort.
This commit is contained in:
parent
c5d47334f4
commit
e20909bb3b
|
|
@ -22,7 +22,6 @@
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/utils.h"
|
#include "kernel/utils.h"
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
@ -82,26 +81,6 @@ struct OptBalanceTreeWorker {
|
||||||
return drv;
|
return drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the driver graph reachable from head contains a cycle,
|
|
||||||
// following the same edges as the backward chain traversal
|
|
||||||
bool has_cycle(Cell *head, IdString cell_type) {
|
|
||||||
TopoSort<Cell*, IdString::compare_ptr_by_name<Cell>> toposort;
|
|
||||||
toposort.analyze_loops = false;
|
|
||||||
vector<Cell*> queue = {head};
|
|
||||||
while (!queue.empty())
|
|
||||||
{
|
|
||||||
Cell *c = queue.back();
|
|
||||||
queue.pop_back();
|
|
||||||
for (IdString port: {ID::A, ID::B})
|
|
||||||
if (Cell *drv = chain_driver(c, port, cell_type)) {
|
|
||||||
if (!toposort.has_node(drv))
|
|
||||||
queue.push_back(drv);
|
|
||||||
toposort.edge(drv, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !toposort.sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a balanced binary tree from a vector of source signals
|
// Create a balanced binary tree from a vector of source signals
|
||||||
SigSpec create_balanced_tree(vector<SigSpec> &sources, IdString cell_type, Cell* cell) {
|
SigSpec create_balanced_tree(vector<SigSpec> &sources, IdString cell_type, Cell* cell) {
|
||||||
// Base case: if we have no sources, return an empty signal
|
// Base case: if we have no sources, return an empty signal
|
||||||
|
|
@ -288,28 +267,45 @@ struct OptBalanceTreeWorker {
|
||||||
if (consumed_cells.count(head_cell))
|
if (consumed_cells.count(head_cell))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Collect the chain cone into a topological sort
|
||||||
|
TopoSort<Cell*, IdString::compare_ptr_by_name<Cell>> toposort;
|
||||||
|
toposort.analyze_loops = false;
|
||||||
|
toposort.node(head_cell);
|
||||||
|
vector<Cell*> queue = {head_cell};
|
||||||
|
while (!queue.empty())
|
||||||
|
{
|
||||||
|
Cell *x = queue.back();
|
||||||
|
queue.pop_back();
|
||||||
|
for (IdString port: {ID::A, ID::B})
|
||||||
|
if (Cell *drv = chain_driver(x, port, cell_type)) {
|
||||||
|
if (!toposort.has_node(drv))
|
||||||
|
queue.push_back(drv);
|
||||||
|
toposort.edge(drv, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Abandon chains containing combinational loops, since
|
// Abandon chains containing combinational loops, since
|
||||||
// rebalancing them is not sound (and would not terminate)
|
// rebalancing them is not sound (and would not terminate)
|
||||||
if (has_cycle(head_cell, cell_type))
|
if (!toposort.sort())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get sources of the chain
|
// Get sources of the chain: process cells from head to
|
||||||
|
// drivers, counting the paths leading back to the head so
|
||||||
|
// reconvergent sources are counted with multiplicity
|
||||||
dict<SigSpec, int> sources;
|
dict<SigSpec, int> sources;
|
||||||
dict<SigSpec, bool> signeds;
|
dict<SigSpec, bool> signeds;
|
||||||
int inner_cells = 0;
|
int inner_cells = GetSize(toposort.sorted) - 1;
|
||||||
std::deque<Cell*> bfs_queue = {head_cell};
|
dict<Cell*, int> reach;
|
||||||
while (bfs_queue.size())
|
reach[head_cell] = 1;
|
||||||
|
for (int i = GetSize(toposort.sorted); i-- > 0; )
|
||||||
{
|
{
|
||||||
Cell* x = bfs_queue.front();
|
Cell* x = toposort.sorted[i];
|
||||||
bfs_queue.pop_front();
|
|
||||||
|
|
||||||
for (IdString port: {ID::A, ID::B}) {
|
for (IdString port: {ID::A, ID::B}) {
|
||||||
if (Cell *drv = chain_driver(x, port, cell_type)) {
|
if (Cell *drv = chain_driver(x, port, cell_type)) {
|
||||||
inner_cells++;
|
reach[drv] += reach[x];
|
||||||
bfs_queue.push_back(drv);
|
|
||||||
} else {
|
} else {
|
||||||
auto sig = sigmap(x->getPort(port));
|
auto sig = sigmap(x->getPort(port));
|
||||||
sources[sig]++;
|
sources[sig] += reach[x];
|
||||||
signeds[sig] = x->getParam(port == ID::A ? ID::A_SIGNED : ID::B_SIGNED).as_bool();
|
signeds[sig] = x->getParam(port == ID::A ? ID::A_SIGNED : ID::B_SIGNED).as_bool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue