mirror of https://github.com/YosysHQ/yosys.git
Fixed topological ordering in freduce pass
This commit is contained in:
parent
e729857647
commit
56e01ce389
|
@ -46,14 +46,11 @@ struct FreduceHelper
|
||||||
SigPool inputs, nodes;
|
SigPool inputs, nodes;
|
||||||
RTLIL::SigSpec input_sigs;
|
RTLIL::SigSpec input_sigs;
|
||||||
|
|
||||||
SigSet<RTLIL::SigSpec> driver_inputs;
|
SigSet<RTLIL::SigSpec> source_signals;
|
||||||
std::vector<RTLIL::Const> test_vectors;
|
std::vector<RTLIL::Const> test_vectors;
|
||||||
std::map<RTLIL::SigSpec, RTLIL::Const> node_to_data;
|
std::map<RTLIL::SigSpec, RTLIL::Const> node_to_data;
|
||||||
std::map<RTLIL::SigSpec, RTLIL::SigSpec> node_result;
|
std::map<RTLIL::SigSpec, RTLIL::SigSpec> node_result;
|
||||||
|
|
||||||
std::vector<RTLIL::SigSig> result_groups;
|
|
||||||
SigPool groups_unlink;
|
|
||||||
|
|
||||||
uint32_t xorshift32_state;
|
uint32_t xorshift32_state;
|
||||||
|
|
||||||
uint32_t xorshift32() {
|
uint32_t xorshift32() {
|
||||||
|
@ -93,8 +90,9 @@ struct FreduceHelper
|
||||||
int max_node_len = 20;
|
int max_node_len = 20;
|
||||||
for (auto &it : node_to_data)
|
for (auto &it : node_to_data)
|
||||||
max_node_len = std::max(max_node_len, int(strlen(log_signal(it.first))));
|
max_node_len = std::max(max_node_len, int(strlen(log_signal(it.first))));
|
||||||
|
log(" full node fingerprints:\n");
|
||||||
for (auto &it : node_to_data)
|
for (auto &it : node_to_data)
|
||||||
log(" %-*s %s\n", max_node_len+5, log_signal(it.first), log_signal(it.second));
|
log(" %-*s %s\n", max_node_len+5, log_signal(it.first), log_signal(it.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(RTLIL::SigSpec sig1, RTLIL::SigSpec sig2)
|
void check(RTLIL::SigSpec sig1, RTLIL::SigSpec sig2)
|
||||||
|
@ -165,16 +163,20 @@ struct FreduceHelper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool topsort_helper(RTLIL::SigSpec cursor, RTLIL::SigSpec stoplist)
|
bool toproot_helper(RTLIL::SigSpec cursor, RTLIL::SigSpec stoplist, int level)
|
||||||
{
|
{
|
||||||
if (stoplist.extract(cursor).width != 0)
|
// log(" %*schecking %s: %s\n", level*2, "", log_signal(cursor), log_signal(stoplist));
|
||||||
|
|
||||||
|
if (stoplist.extract(cursor).width != 0) {
|
||||||
|
// log(" %*s STOP\n", level*2, "");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
stoplist.append(cursor);
|
stoplist.append(cursor);
|
||||||
std::set<RTLIL::SigSpec> next = driver_inputs.find(cursor);
|
std::set<RTLIL::SigSpec> next = source_signals.find(cursor);
|
||||||
|
|
||||||
for (auto &it : next)
|
for (auto &it : next)
|
||||||
if (!topsort_helper(it, stoplist))
|
if (!toproot_helper(it, stoplist, level+1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -182,18 +184,61 @@ struct FreduceHelper
|
||||||
|
|
||||||
// KISS topological sort of bits in signal. return one element of sig
|
// KISS topological sort of bits in signal. return one element of sig
|
||||||
// without dependencies to the others (or empty if input is not a DAG).
|
// without dependencies to the others (or empty if input is not a DAG).
|
||||||
RTLIL::SigSpec topsort(RTLIL::SigSpec sig)
|
RTLIL::SigSpec toproot(RTLIL::SigSpec sig)
|
||||||
{
|
{
|
||||||
sig.expand();
|
sig.expand();
|
||||||
|
// log(" finding topological root in %s:\n", log_signal(sig));
|
||||||
for (auto &c : sig.chunks) {
|
for (auto &c : sig.chunks) {
|
||||||
RTLIL::SigSpec stoplist = sig;
|
RTLIL::SigSpec stoplist = sig;
|
||||||
stoplist.remove(c);
|
stoplist.remove(c);
|
||||||
if (topsort_helper(c, stoplist))
|
// log(" testing %s as root:\n", log_signal(c));
|
||||||
|
if (toproot_helper(c, stoplist, 0))
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
return RTLIL::SigSpec();
|
return RTLIL::SigSpec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_design_for_group(RTLIL::SigSpec root, RTLIL::SigSpec rest)
|
||||||
|
{
|
||||||
|
SigPool unlink;
|
||||||
|
unlink.add(rest);
|
||||||
|
|
||||||
|
for (auto &cell_it : module->cells) {
|
||||||
|
RTLIL::Cell *cell = cell_it.second;
|
||||||
|
if (!ct.cell_known(cell->type))
|
||||||
|
continue;
|
||||||
|
for (auto &conn : cell->connections)
|
||||||
|
if (ct.cell_output(cell->type, conn.first)) {
|
||||||
|
RTLIL::SigSpec sig = sigmap(conn.second);
|
||||||
|
sig.expand();
|
||||||
|
bool did_something = false;
|
||||||
|
for (auto &c : sig.chunks) {
|
||||||
|
if (c.wire == NULL || !unlink.check_any(c))
|
||||||
|
continue;
|
||||||
|
c.wire = new RTLIL::Wire;
|
||||||
|
c.wire->name = NEW_ID;
|
||||||
|
module->add(c.wire);
|
||||||
|
assert(c.width == 1);
|
||||||
|
c.offset = 0;
|
||||||
|
did_something = true;
|
||||||
|
}
|
||||||
|
if (did_something) {
|
||||||
|
sig.optimize();
|
||||||
|
conn.second = sig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rest.expand();
|
||||||
|
for (auto &c : rest.chunks) {
|
||||||
|
if (c.wire != NULL && !root.is_fully_const()) {
|
||||||
|
source_signals.erase(c);
|
||||||
|
source_signals.insert(c, root);
|
||||||
|
}
|
||||||
|
module->connections.push_back(RTLIL::SigSig(c, root));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void analyze_groups()
|
void analyze_groups()
|
||||||
{
|
{
|
||||||
SigMap to_group_major;
|
SigMap to_group_major;
|
||||||
|
@ -212,15 +257,19 @@ struct FreduceHelper
|
||||||
RTLIL::SigSig group = it;
|
RTLIL::SigSig group = it;
|
||||||
|
|
||||||
if (!it.first.is_fully_const()) {
|
if (!it.first.is_fully_const()) {
|
||||||
group.first = topsort(it.second);
|
group.first = toproot(it.second);
|
||||||
if (group.first.width == 0)
|
if (group.first.width == 0) {
|
||||||
log_error("Operating on non-DAG input: failed to find topological root for `%s'.\n", log_signal(it.second));
|
log("Operating on non-DAG input: failed to find topological root for `%s'.\n", log_signal(it.second));
|
||||||
|
return;
|
||||||
|
}
|
||||||
group.second.remove(group.first);
|
group.second.remove(group.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
group.first.optimize();
|
group.first.optimize();
|
||||||
group.second.sort_and_unify();
|
group.second.sort_and_unify();
|
||||||
result_groups.push_back(group);
|
|
||||||
|
log(" found group: %s -> %s\n", log_signal(group.first), log_signal(group.second));
|
||||||
|
update_design_for_group(group.first, group.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +298,7 @@ struct FreduceHelper
|
||||||
cell_inputs.expand();
|
cell_inputs.expand();
|
||||||
for (auto &c : cell_inputs.chunks)
|
for (auto &c : cell_inputs.chunks)
|
||||||
if (c.wire != NULL)
|
if (c.wire != NULL)
|
||||||
driver_inputs.insert(cell_outputs, c);
|
source_signals.insert(cell_outputs, c);
|
||||||
if (!satgen.importCell(cell))
|
if (!satgen.importCell(cell))
|
||||||
log_error("Failed to import cell to SAT solver: %s (%s)\n",
|
log_error("Failed to import cell to SAT solver: %s (%s)\n",
|
||||||
RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
|
RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
|
||||||
|
@ -276,7 +325,7 @@ struct FreduceHelper
|
||||||
for (auto &test_vec : test_vectors)
|
for (auto &test_vec : test_vectors)
|
||||||
run_test(test_vec);
|
run_test(test_vec);
|
||||||
|
|
||||||
// run the analysis
|
// run the analysis and update design
|
||||||
|
|
||||||
analyze_const();
|
analyze_const();
|
||||||
analyze_alias();
|
analyze_alias();
|
||||||
|
@ -285,44 +334,8 @@ struct FreduceHelper
|
||||||
for (auto &test_vec : test_vectors)
|
for (auto &test_vec : test_vectors)
|
||||||
log(" test vector: %s\n", log_signal(test_vec));
|
log(" test vector: %s\n", log_signal(test_vec));
|
||||||
|
|
||||||
|
dump_node_data();
|
||||||
analyze_groups();
|
analyze_groups();
|
||||||
|
|
||||||
for (auto &it : result_groups) {
|
|
||||||
log(" found group: %s -> %s\n", log_signal(it.first), log_signal(it.second));
|
|
||||||
groups_unlink.add(it.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &cell_it : module->cells) {
|
|
||||||
RTLIL::Cell *cell = cell_it.second;
|
|
||||||
if (!ct.cell_known(cell->type))
|
|
||||||
continue;
|
|
||||||
for (auto &conn : cell->connections)
|
|
||||||
if (ct.cell_output(cell->type, conn.first)) {
|
|
||||||
RTLIL::SigSpec sig = sigmap(conn.second);
|
|
||||||
sig.expand();
|
|
||||||
bool did_something = false;
|
|
||||||
for (auto &c : sig.chunks) {
|
|
||||||
if (c.wire == NULL || !groups_unlink.check_any(c))
|
|
||||||
continue;
|
|
||||||
c.wire = new RTLIL::Wire;
|
|
||||||
c.wire->name = NEW_ID;
|
|
||||||
module->add(c.wire);
|
|
||||||
assert(c.width == 1);
|
|
||||||
c.offset = 0;
|
|
||||||
did_something = true;
|
|
||||||
}
|
|
||||||
if (did_something) {
|
|
||||||
sig.optimize();
|
|
||||||
conn.second = sig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &it : result_groups) {
|
|
||||||
it.second.expand();
|
|
||||||
for (auto &c : it.second.chunks)
|
|
||||||
module->connections.push_back(RTLIL::SigSig(c, it.first));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue