mirror of
https://github.com/YosysHQ/yosys
synced 2026-03-23 04:49:15 +00:00
genrtlil: even faster removeSignalFromCaseTree
This commit is contained in:
parent
27737c6e2e
commit
ad7a776d73
1 changed files with 68 additions and 4 deletions
|
|
@ -342,6 +342,9 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
// The most recently assigned $print or $check cell \PRIORITY.
|
||||
int last_effect_priority;
|
||||
|
||||
// Track which signals have been assigned in current_case to avoid unnecessary removeSignalFromCaseTree calls
|
||||
pool<RTLIL::SigBit> current_case_assigned_bits;
|
||||
|
||||
ProcessGenerator(std::unique_ptr<AstNode> a, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(std::move(a)), initSyncSignals(initSyncSignalsArg), last_effect_priority(0)
|
||||
{
|
||||
// rewrite lookahead references
|
||||
|
|
@ -430,6 +433,10 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
subst_rvalue_map = subst_lvalue_from.to_sigbit_dict(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from)));
|
||||
} else {
|
||||
addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from);
|
||||
// Track initial assignments
|
||||
for (auto &bit : subst_lvalue_to)
|
||||
if (bit.wire != NULL)
|
||||
current_case_assigned_bits.insert(bit);
|
||||
}
|
||||
|
||||
// process the AST
|
||||
|
|
@ -559,8 +566,26 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
// the third assignment.
|
||||
void removeSignalFromCaseTree(const pool<RTLIL::SigBit> &pattern_bits, RTLIL::CaseRule *cs)
|
||||
{
|
||||
for (auto it = cs->actions.begin(); it != cs->actions.end(); it++)
|
||||
it->first.remove2(pattern_bits, &it->second);
|
||||
// Optimization: check actions in reverse order and stop early if we've found all pattern bits
|
||||
pool<RTLIL::SigBit> remaining_bits = pattern_bits;
|
||||
|
||||
for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ++it) {
|
||||
bool has_pattern = false;
|
||||
for (auto &bit : it->first) {
|
||||
if (bit.wire != NULL && remaining_bits.count(bit)) {
|
||||
has_pattern = true;
|
||||
remaining_bits.erase(bit);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_pattern) {
|
||||
it->first.remove2(pattern_bits, &it->second);
|
||||
}
|
||||
|
||||
// Early exit if we've processed all bits in pattern
|
||||
if (remaining_bits.empty())
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
|
||||
for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
|
||||
|
|
@ -633,7 +658,23 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
subst_rvalue_map.set(unmapped_lvalue[i], rvalue[i]);
|
||||
}
|
||||
|
||||
removeSignalFromCaseTree(lvalue, current_case);
|
||||
// Check if any bits in lvalue have been assigned before in current_case
|
||||
bool has_overlap = false;
|
||||
for (auto &bit : lvalue) {
|
||||
if (bit.wire != NULL && current_case_assigned_bits.count(bit)) {
|
||||
has_overlap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_overlap)
|
||||
removeSignalFromCaseTree(lvalue, current_case);
|
||||
|
||||
// Track newly assigned bits
|
||||
for (auto &bit : lvalue)
|
||||
if (bit.wire != NULL)
|
||||
current_case_assigned_bits.insert(bit);
|
||||
|
||||
remove_unwanted_lvalue_bits(lvalue, rvalue);
|
||||
current_case->actions.push_back(RTLIL::SigSig(lvalue, rvalue));
|
||||
}
|
||||
|
|
@ -680,9 +721,15 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
|
||||
RTLIL::CaseRule *backup_case = current_case;
|
||||
current_case = new RTLIL::CaseRule;
|
||||
pool<RTLIL::SigBit> backup_assigned_bits = std::move(current_case_assigned_bits);
|
||||
current_case_assigned_bits.clear();
|
||||
set_src_attr(current_case, child.get());
|
||||
last_generated_case = current_case;
|
||||
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
|
||||
// Track temp assignments
|
||||
for (auto &bit : this_case_eq_ltemp)
|
||||
if (bit.wire != NULL)
|
||||
current_case_assigned_bits.insert(bit);
|
||||
for (auto& node : child->children) {
|
||||
if (node->type == AST_DEFAULT)
|
||||
default_case = current_case;
|
||||
|
|
@ -696,6 +743,7 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
else
|
||||
log_assert(current_case->compare.size() == 0);
|
||||
current_case = backup_case;
|
||||
current_case_assigned_bits = std::move(backup_assigned_bits);
|
||||
|
||||
subst_lvalue_map.restore();
|
||||
subst_rvalue_map.restore();
|
||||
|
|
@ -724,8 +772,24 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
subst_rvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
|
||||
|
||||
this_case_eq_lvalue.replace(subst_lvalue_map.stdmap());
|
||||
removeSignalFromCaseTree(this_case_eq_lvalue, current_case);
|
||||
|
||||
// Check if any bits in lvalue have been assigned before in current_case
|
||||
bool has_overlap = false;
|
||||
for (auto &bit : this_case_eq_lvalue) {
|
||||
if (bit.wire != NULL && current_case_assigned_bits.count(bit)) {
|
||||
has_overlap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_overlap)
|
||||
removeSignalFromCaseTree(this_case_eq_lvalue, current_case);
|
||||
|
||||
addChunkActions(current_case->actions, this_case_eq_lvalue, this_case_eq_ltemp);
|
||||
// Track newly assigned bits
|
||||
for (auto &bit : this_case_eq_lvalue)
|
||||
if (bit.wire != NULL)
|
||||
current_case_assigned_bits.insert(bit);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue