mirror of https://github.com/YosysHQ/yosys.git
proc_arst: Add special-casing of clock signal in conditionals.
The already-existing special case for conditionals on clock has been remade as follows: - now triggered for the last remaining edge trigger after all others have been converted to async reset, not just when there is only one sync rule in the first place - does not require all contained assignments to be constant, as opposed to a reset conditional — merely const-folds the condition In addition, the code has been refactored a bit; as a bonus, the priority order of async resets found is now preserved in resulting sync rule ordering (though this is not yet respected by proc_dff). Fixes #2656.
This commit is contained in:
parent
3af871f969
commit
a55bf6375b
|
@ -179,22 +179,35 @@ RTLIL::SigSpec apply_reset(RTLIL::Module *mod, RTLIL::Process *proc, RTLIL::Sync
|
||||||
|
|
||||||
void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
|
void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
|
||||||
{
|
{
|
||||||
restart_proc_arst:
|
std::vector<RTLIL::SyncRule *> arst_syncs;
|
||||||
if (proc->root_case.switches.size() != 1)
|
std::vector<RTLIL::SyncRule *> edge_syncs;
|
||||||
return;
|
std::vector<RTLIL::SyncRule *> other_syncs;
|
||||||
|
|
||||||
RTLIL::SigSpec root_sig = proc->root_case.switches[0]->signal;
|
|
||||||
|
|
||||||
for (auto &sync : proc->syncs) {
|
for (auto &sync : proc->syncs) {
|
||||||
if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
|
if (sync->type == RTLIL::SyncType::ST0 || sync->type == RTLIL::SyncType::ST1) {
|
||||||
|
arst_syncs.push_back(sync);
|
||||||
|
} else if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
|
||||||
|
edge_syncs.push_back(sync);
|
||||||
|
} else {
|
||||||
|
other_syncs.push_back(sync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool did_something = false;
|
||||||
|
|
||||||
|
while (proc->root_case.switches.size() == 1) {
|
||||||
|
RTLIL::SigSpec root_sig = proc->root_case.switches[0]->signal;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (auto it = edge_syncs.begin(); it != edge_syncs.end(); ++it) {
|
||||||
|
auto sync = *it;
|
||||||
bool polarity = sync->type == RTLIL::SyncType::STp;
|
bool polarity = sync->type == RTLIL::SyncType::STp;
|
||||||
if (check_signal(mod, root_sig, sync->signal, polarity)) {
|
if (check_signal(mod, root_sig, sync->signal, polarity)) {
|
||||||
if (proc->syncs.size() == 1) {
|
if (edge_syncs.size() > 1) {
|
||||||
log("Found VHDL-style edge-trigger %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
|
|
||||||
} else {
|
|
||||||
log("Found async reset %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
|
log("Found async reset %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
|
||||||
sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0;
|
sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0;
|
||||||
}
|
arst_syncs.push_back(sync);
|
||||||
|
edge_syncs.erase(it);
|
||||||
for (auto &action : sync->actions) {
|
for (auto &action : sync->actions) {
|
||||||
action.second = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, action.second, action.first);
|
action.second = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, action.second, action.first);
|
||||||
}
|
}
|
||||||
|
@ -209,9 +222,24 @@ restart_proc_arst:
|
||||||
}
|
}
|
||||||
sync->mem_write_actions.clear();
|
sync->mem_write_actions.clear();
|
||||||
eliminate_const(mod, &proc->root_case, root_sig, polarity);
|
eliminate_const(mod, &proc->root_case, root_sig, polarity);
|
||||||
goto restart_proc_arst;
|
} else {
|
||||||
|
log("Found VHDL-style edge-trigger %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
|
||||||
|
eliminate_const(mod, &proc->root_case, root_sig, !polarity);
|
||||||
|
}
|
||||||
|
did_something = true;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (did_something) {
|
||||||
|
proc->syncs.clear();
|
||||||
|
proc->syncs.insert(proc->syncs.end(), arst_syncs.begin(), arst_syncs.end());
|
||||||
|
proc->syncs.insert(proc->syncs.end(), edge_syncs.begin(), edge_syncs.end());
|
||||||
|
proc->syncs.insert(proc->syncs.end(), other_syncs.begin(), other_syncs.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
read_verilog <<EOT
|
||||||
|
module top (...);
|
||||||
|
|
||||||
|
input clk, rst, d1, d2;
|
||||||
|
output q1, q2;
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
if (clk)
|
||||||
|
q1 <= d1;
|
||||||
|
|
||||||
|
always @(posedge clk, posedge rst)
|
||||||
|
if (rst)
|
||||||
|
q2 <= 0;
|
||||||
|
else if (clk)
|
||||||
|
q2 <= d2;
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
proc
|
||||||
|
opt
|
||||||
|
|
||||||
|
select -assert-count 1 t:$dff
|
||||||
|
select -assert-count 1 w:clk %a %co t:$dff %i
|
||||||
|
select -assert-count 1 w:d1 %a %co t:$dff %i
|
||||||
|
select -assert-count 1 w:q1 %a %ci t:$dff %i
|
||||||
|
select -assert-count 1 t:$adff
|
||||||
|
select -assert-count 1 w:clk %a %co t:$adff %i
|
||||||
|
select -assert-count 1 w:rst %a %co t:$adff %i
|
||||||
|
select -assert-count 1 w:d2 %a %co t:$adff %i
|
||||||
|
select -assert-count 1 w:q2 %a %ci t:$adff %i
|
Loading…
Reference in New Issue