diff --git a/passes/opt/opt_dff.cc b/passes/opt/opt_dff.cc index 4ed4b0cb6..210c4828f 100644 --- a/passes/opt/opt_dff.cc +++ b/passes/opt/opt_dff.cc @@ -170,9 +170,62 @@ struct OptDffWorker return ret; } - void simplify_patterns(patterns_t&) + void simplify_patterns(patterns_t& patterns) { - // TBD + auto new_patterns = patterns; + auto find_comp = [](const auto& left, const auto& right) -> std::optional { + std::optional ret; + for (const auto &pt: left) + if (right.count(pt.first) == 0) + return {}; + else if (right.at(pt.first) == pt.second) + continue; + else + if (ret) + return {}; + else + ret = pt.first; + return ret; + }; + + // remove complimentary patterns + bool optimized; + do { + optimized = false; + for (auto i = patterns.begin(); i != patterns.end(); i++) { + for (auto j = std::next(i, 1); j != patterns.end(); j++) { + const auto& left = (GetSize(*j) <= GetSize(*i)) ? *j : *i; + auto right = (GetSize(*i) < GetSize(*j)) ? *j : *i; + + const auto complimentary_var = find_comp(left, right); + + if (complimentary_var) { + new_patterns.erase(right); + right.erase(complimentary_var.value()); + new_patterns.insert(right); + optimized = true; + } + } + } + patterns = new_patterns; + } while(optimized); + + // remove redundant patterns + for (auto i = patterns.begin(); i != patterns.end(); ++i) { + for (auto j = std::next(i, 1); j != patterns.end(); ++j) { + const auto& left = (GetSize(*j) <= GetSize(*i)) ? *j : *i; + const auto& right = (GetSize(*i) < GetSize(*j)) ? *j : *i; + + bool redundant = true; + + for (const auto& pt : left) + if (right.count(pt.first) == 0 || right.at(pt.first) != pt.second) + redundant = false; + if (redundant) + new_patterns.erase(right); + } + } + patterns = std::move(new_patterns); } ctrl_t make_patterns_logic(const patterns_t &patterns, const ctrls_t &ctrls, bool make_gates) diff --git a/tests/arch/quicklogic/pp3/fsm.ys b/tests/arch/quicklogic/pp3/fsm.ys index 418db8025..9679628e9 100644 --- a/tests/arch/quicklogic/pp3/fsm.ys +++ b/tests/arch/quicklogic/pp3/fsm.ys @@ -11,8 +11,8 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd fsm # Constrain all select calls below inside the top module -select -assert-count 1 t:LUT2 -select -assert-count 9 t:LUT3 +select -assert-count 2 t:LUT2 +select -assert-count 4 t:LUT3 select -assert-count 4 t:dffepc select -assert-count 1 t:logic_0 select -assert-count 1 t:logic_1 @@ -20,4 +20,4 @@ select -assert-count 3 t:inpad select -assert-count 2 t:outpad select -assert-count 1 t:ckpad -select -assert-none t:LUT2 t:LUT3 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D +select -assert-none t:LUT2 t:LUT3 t:LUT4 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D