22 using scoring = std::map<std::set<u32>,
float>;
28 std::map<std::set<u32>,
float> results_by_vote;
32 for (
const auto& it :
state->gates_of_group)
34 std::set<u32> sorted_gates(it.second.begin(), it.second.end());
39 return results_by_vote;
42 std::shared_ptr<Grouping> generate_output(
const Configuration& config,
const std::shared_ptr<Grouping>& initial_grouping,
scoring& scores)
45 const auto& netlist_abstr = initial_grouping->netlist_abstr;
51 const std::set<u32>* group;
56 std::vector<u32> unassigned_gates;
57 unassigned_gates.reserve(netlist_abstr.target_gates.size());
58 std::transform(netlist_abstr.target_gates.begin(), netlist_abstr.target_gates.end(), std::back_inserter(unassigned_gates), [](
auto&
g) { return g->get_id(); });
61 std::sort(unassigned_gates.begin(), unassigned_gates.end());
63 std::shared_ptr<Grouping>
output = std::make_shared<Grouping>(netlist_abstr);
68 for (
const auto& [group_id, gates] : initial_grouping->gates_of_group)
70 if (!initial_grouping->operations_on_group_allowed.at(group_id))
72 u32 new_group_id = ++id_counter;
74 output->group_control_fingerprint_map[new_group_id] = initial_grouping->netlist_abstr.gate_to_fingerprint.at(*gates.begin());
75 output->operations_on_group_allowed[new_group_id] =
false;
77 output->gates_of_group[new_group_id].insert(gates.begin(), gates.end());
78 for (
const auto& sg : gates)
80 output->parent_group_of_gate[sg] = new_group_id;
83 std::set<u32> sorted_gates(gates.begin(), gates.end());
84 scores.erase(sorted_gates);
85 unassigned_gates.erase(std::remove_if(unassigned_gates.begin(), unassigned_gates.end(), [&sorted_gates](
auto id) { return sorted_gates.find(id) != sorted_gates.end(); }),
86 unassigned_gates.end());
90 std::vector<candidate> sorted_results;
94 sorted_results.reserve(scores.size());
95 std::transform(scores.begin(), scores.end(), std::back_inserter(sorted_results), [](
auto& it) { return candidate{&it.first, it.second}; });
96 std::sort(sorted_results.begin(), sorted_results.end(), [&](
auto a,
auto b) {
97 auto a_prio = std::find(config.prioritized_sizes.begin(), config.prioritized_sizes.end(), a.group->size());
98 auto b_prio = std::find(config.prioritized_sizes.begin(), config.prioritized_sizes.end(), b.group->size());
109 auto a_is_bad = a.group->size() < min_group_size;
110 auto b_is_bad = b.group->size() < min_group_size;
112 if (!a_is_bad && b_is_bad)
116 if (!b_is_bad && a_is_bad)
121 return a.score > b.score;
124 const float percent_scan = 0.1f;
126 log_info(
"dataflow",
"got {} voting groups", sorted_results.size());
129 float original_size = sorted_results.size();
131 while (!sorted_results.empty())
133 progress_bar.
print_progress((original_size - sorted_results.size()) / original_size);
136 std::unordered_map<u32, u32> max_group_size_of_gate;
137 std::unordered_map<u32, std::vector<u32>> groups_of_gate;
139 for (
auto g : unassigned_gates)
141 max_group_size_of_gate.emplace(
g, 0);
142 groups_of_gate.emplace(
g, std::vector<u32>{});
145 for (
u32 i = 0; i < sorted_results.size(); ++i)
147 auto size = (
u32)sorted_results[i].group->size();
148 for (
auto g : *sorted_results[i].group)
150 auto it = max_group_size_of_gate.find(
g);
151 it->second = std::max(it->second, size);
152 groups_of_gate.at(
g).push_back(i);
158 bool first_is_bad = sorted_results.front().group->size() < min_group_size;
159 bool first_is_preferred = std::find(config.prioritized_sizes.begin(), config.prioritized_sizes.end(), sorted_results.front().group->size()) != config.prioritized_sizes.end();
160 float lower_score_bound = sorted_results.front().score * (1.f - percent_scan);
162 u32 num_scanned_groups = 0;
163 for (; num_scanned_groups < sorted_results.size(); ++num_scanned_groups)
165 if (sorted_results[num_scanned_groups].score < lower_score_bound)
170 auto scanned_group_size = sorted_results[num_scanned_groups].group->size();
172 if (!first_is_bad && scanned_group_size < min_group_size)
176 if (first_is_preferred && std::find(config.prioritized_sizes.begin(), config.prioritized_sizes.end(), scanned_group_size) == config.prioritized_sizes.end())
183 std::vector<float> badness_score_of_group(num_scanned_groups, 0.0f);
186 auto& scanned_group = *sorted_results[scanned_group_idx].group;
188 std::vector<u32> unaffected_gates;
189 unaffected_gates.reserve(unassigned_gates.size() - scanned_group.size());
190 std::set_difference(unassigned_gates.begin(), unassigned_gates.end(), scanned_group.begin(), scanned_group.end(), std::back_inserter(unaffected_gates));
196 std::unordered_set<u32> affected_groups;
198 for (
auto g : scanned_group)
200 auto& gg = groups_of_gate.at(
g);
201 affected_groups.insert(gg.begin(), gg.end());
203 affected_groups.erase(scanned_group_idx);
205 for (
auto gr : affected_groups)
207 if (std::find(config.prioritized_sizes.begin(), config.prioritized_sizes.end(), sorted_results[gr].group->size()) != config.prioritized_sizes.end())
214 for (
auto g : unaffected_gates)
216 if (max_group_size_of_gate.at(
g) < min_group_size)
224 badness_score_of_group[scanned_group_idx] = score;
230 u32 best_choice = std::distance(badness_score_of_group.begin(), std::min_element(badness_score_of_group.begin(), badness_score_of_group.end()));
231 auto best_group = *sorted_results[best_choice].group;
235 u32 new_group_id = ++id_counter;
237 output->group_control_fingerprint_map[new_group_id] = netlist_abstr.gate_to_fingerprint.at(*best_group.begin());
238 output->operations_on_group_allowed[new_group_id] =
true;
240 output->gates_of_group[new_group_id].insert(best_group.begin(), best_group.end());
241 for (
const auto& sg : best_group)
243 output->parent_group_of_gate[sg] = new_group_id;
247 unassigned_gates.erase(std::remove_if(unassigned_gates.begin(), unassigned_gates.end(), [&best_group](
auto id) { return best_group.find(id) != best_group.end(); }),
248 unassigned_gates.end());
251 sorted_results.erase(std::remove_if(sorted_results.begin(),
252 sorted_results.end(),
253 [&best_group](
auto check_group) {
254 return std::any_of(check_group.group->begin(), check_group.group->end(), [&best_group](auto check_group_gate) {
255 return best_group.find(check_group_gate) != best_group.end();
258 sorted_results.end());
260 progress_bar.
clear();
262 for (
auto g : unassigned_gates)
264 u32 new_group_id = ++id_counter;
266 output->group_control_fingerprint_map[new_group_id] = netlist_abstr.gate_to_fingerprint.at(
g);
267 output->operations_on_group_allowed[new_group_id] =
true;
269 output->gates_of_group[new_group_id].insert(
g);
270 output->parent_group_of_gate[
g] = new_group_id;
281 output.is_final_result =
false;
283 auto scores = compute_scores(result);
285 output.merged_result = generate_output(config, initial_grouping, scores);
291 log_info(
"dataflow",
"result does not improve anymore");
295 log_info(
"dataflow",
"found a cycle");
298 output.is_final_result =
true;
299 log_info(
"dataflow",
"voting done");
void print_progress(float progress, const std::string &message="")
#define log_info(channel,...)
std::map< std::set< u32 >, float > scoring
evaluation::Result run(const Configuration &config, Context &ctx, const std::shared_ptr< Grouping > &initial_grouping, const processing::Result &result)
void parallel_for_each(u32 begin, u32 end, R func)
This file contains the struct that holds all information on the netlist abstraction used for dataflow...
This file contains the class that holds all information of a dataflow analysis grouping.
if(BUILD_TESTS) include_directories($
std::vector< std::shared_ptr< Grouping > > partial_results
std::map< std::shared_ptr< Grouping >, std::vector< std::vector< pass_id > > > pass_combinations_leading_to_grouping
std::vector< std::shared_ptr< Grouping > > unique_groupings
#define measure_block_time(X)