mirror of https://github.com/YosysHQ/yosys.git
proc_prune: promote assigns to module connections when legal.
This can pave the way for further transformations by exposing identities that were previously hidden in a process to any pass that uses SigMap. Indeed, this commit removes some ad-hoc logic from proc_init that appears to have been tailored to the output of genrtlil in favor of using `SigMap.apply()`. (This removal is not optional, as the ad-hoc logic cannot cope with the result of running proc_prune; a similar issue was fixed in proc_arst.)
This commit is contained in:
parent
5fe0ffe30f
commit
44bcb7a187
|
@ -172,7 +172,7 @@ restart_proc_arst:
|
|||
sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0;
|
||||
}
|
||||
for (auto &action : sync->actions) {
|
||||
RTLIL::SigSpec rspec = action.second;
|
||||
RTLIL::SigSpec rspec = assign_map(action.second);
|
||||
RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size());
|
||||
for (int i = 0; i < GetSize(rspec); i++)
|
||||
if (rspec[i].wire == NULL)
|
||||
|
|
|
@ -26,21 +26,7 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
void proc_get_const(RTLIL::SigSpec &sig, RTLIL::CaseRule &rule)
|
||||
{
|
||||
log_assert(rule.compare.size() == 0);
|
||||
|
||||
while (1) {
|
||||
RTLIL::SigSpec tmp = sig;
|
||||
for (auto &it : rule.actions)
|
||||
tmp.replace(it.first, it.second);
|
||||
if (tmp == sig)
|
||||
break;
|
||||
sig = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void proc_init(RTLIL::Module *mod, RTLIL::Process *proc)
|
||||
void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc)
|
||||
{
|
||||
bool found_init = false;
|
||||
|
||||
|
@ -53,9 +39,7 @@ void proc_init(RTLIL::Module *mod, RTLIL::Process *proc)
|
|||
for (auto &action : sync->actions)
|
||||
{
|
||||
RTLIL::SigSpec lhs = action.first;
|
||||
RTLIL::SigSpec rhs = action.second;
|
||||
|
||||
proc_get_const(rhs, proc->root_case);
|
||||
RTLIL::SigSpec rhs = sigmap(action.second);
|
||||
|
||||
if (!rhs.is_fully_const())
|
||||
log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs), log_signal(rhs));
|
||||
|
@ -120,10 +104,12 @@ struct ProcInitPass : public Pass {
|
|||
extra_args(args, 1, design);
|
||||
|
||||
for (auto mod : design->modules())
|
||||
if (design->selected(mod))
|
||||
if (design->selected(mod)) {
|
||||
SigMap sigmap(mod);
|
||||
for (auto &proc_it : mod->processes)
|
||||
if (design->selected(mod, proc_it.second))
|
||||
proc_init(mod, proc_it.second);
|
||||
proc_init(mod, sigmap, proc_it.second);
|
||||
}
|
||||
}
|
||||
} ProcInitPass;
|
||||
|
||||
|
|
|
@ -31,11 +31,11 @@ struct PruneWorker
|
|||
RTLIL::Module *module;
|
||||
SigMap sigmap;
|
||||
|
||||
int count = 0;
|
||||
int removed_count = 0, promoted_count = 0;
|
||||
|
||||
PruneWorker(RTLIL::Module *mod) : module(mod), sigmap(mod) {}
|
||||
|
||||
pool<RTLIL::SigBit> do_switch(RTLIL::SwitchRule *sw, pool<RTLIL::SigBit> assigned)
|
||||
pool<RTLIL::SigBit> do_switch(RTLIL::SwitchRule *sw, pool<RTLIL::SigBit> assigned, pool<RTLIL::SigBit> &affected)
|
||||
{
|
||||
pool<RTLIL::SigBit> all_assigned;
|
||||
bool full_case = sw->get_bool_attribute("\\full_case");
|
||||
|
@ -43,7 +43,7 @@ struct PruneWorker
|
|||
for (auto it : sw->cases) {
|
||||
if (it->compare.empty())
|
||||
full_case = true;
|
||||
pool<RTLIL::SigBit> case_assigned = do_case(it, assigned);
|
||||
pool<RTLIL::SigBit> case_assigned = do_case(it, assigned, affected);
|
||||
if (first) {
|
||||
first = false;
|
||||
all_assigned = case_assigned;
|
||||
|
@ -58,10 +58,11 @@ struct PruneWorker
|
|||
return assigned;
|
||||
}
|
||||
|
||||
pool<RTLIL::SigBit> do_case(RTLIL::CaseRule *cs, pool<RTLIL::SigBit> assigned)
|
||||
pool<RTLIL::SigBit> do_case(RTLIL::CaseRule *cs, pool<RTLIL::SigBit> assigned, pool<RTLIL::SigBit> &affected,
|
||||
bool root = false)
|
||||
{
|
||||
for (auto it = cs->switches.rbegin(); it != cs->switches.rend(); ++it) {
|
||||
pool<RTLIL::SigBit> sw_assigned = do_switch((*it), assigned);
|
||||
pool<RTLIL::SigBit> sw_assigned = do_switch((*it), assigned, affected);
|
||||
assigned.insert(sw_assigned.begin(), sw_assigned.end());
|
||||
}
|
||||
pool<RTLIL::SigSig> remove;
|
||||
|
@ -74,18 +75,35 @@ struct PruneWorker
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (redundant)
|
||||
if (redundant) {
|
||||
removed_count++;
|
||||
remove.insert(*it);
|
||||
else {
|
||||
} else {
|
||||
if (root) {
|
||||
bool promotable = true;
|
||||
for (auto &bit : lhs) {
|
||||
if (bit.wire && affected[bit]) {
|
||||
promotable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (promotable) {
|
||||
promoted_count++;
|
||||
module->connect(*it);
|
||||
remove.insert(*it);
|
||||
}
|
||||
}
|
||||
for (auto &bit : lhs)
|
||||
if (bit.wire)
|
||||
assigned.insert(bit);
|
||||
for (auto &bit : lhs)
|
||||
if (bit.wire)
|
||||
affected.insert(bit);
|
||||
}
|
||||
}
|
||||
for (auto it = cs->actions.begin(); it != cs->actions.end(); ) {
|
||||
if (remove[*it]) {
|
||||
it = cs->actions.erase(it);
|
||||
count++;
|
||||
} else it++;
|
||||
}
|
||||
return assigned;
|
||||
|
@ -93,7 +111,8 @@ struct PruneWorker
|
|||
|
||||
void do_process(RTLIL::Process *pr)
|
||||
{
|
||||
do_case(&pr->root_case, {});
|
||||
pool<RTLIL::SigBit> affected;
|
||||
do_case(&pr->root_case, {}, affected, /*root=*/true);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -111,7 +130,7 @@ struct ProcPrunePass : public Pass {
|
|||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
int total_count = 0;
|
||||
int total_removed_count = 0, total_promoted_count = 0;
|
||||
log_header(design, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n");
|
||||
|
||||
extra_args(args, 1, design);
|
||||
|
@ -125,10 +144,14 @@ struct ProcPrunePass : public Pass {
|
|||
continue;
|
||||
worker.do_process(proc_it.second);
|
||||
}
|
||||
total_count += worker.count;
|
||||
total_removed_count += worker.removed_count;
|
||||
total_promoted_count += worker.promoted_count;
|
||||
}
|
||||
|
||||
log("Removed %d redundant assignment%s.\n", total_count, total_count == 1 ? "" : "s");
|
||||
log("Removed %d redundant assignment%s.\n",
|
||||
total_removed_count, total_removed_count == 1 ? "" : "s");
|
||||
log("Promoted %d assignment%s to connection%s.\n",
|
||||
total_promoted_count, total_promoted_count == 1 ? "" : "s", total_promoted_count == 1 ? "" : "s");
|
||||
}
|
||||
} ProcPrunePass;
|
||||
|
||||
|
|
Loading…
Reference in New Issue