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();
132 while (!sorted_results.empty())
138 std::unordered_map<u32, u32> max_group_size_of_gate;
139 std::unordered_map<u32, std::vector<u32>> groups_of_gate;
141 for (
auto g : unassigned_gates)
143 max_group_size_of_gate.emplace(
g, 0);
144 groups_of_gate.emplace(
g, std::vector<u32>{});
147 for (
u32 i = 0; i < sorted_results.size(); ++i)
149 auto size = (
u32)sorted_results[i].group->size();
150 for (
auto g : *sorted_results[i].group)
152 auto it = max_group_size_of_gate.find(
g);
153 it->second = std::max(it->second, size);
154 groups_of_gate.at(
g).push_back(i);
160 bool first_is_bad = sorted_results.front().group->size() < min_group_size;
161 bool first_is_preferred = std::find(config.prioritized_sizes.begin(), config.prioritized_sizes.end(), sorted_results.front().group->size()) != config.prioritized_sizes.end();
162 float lower_score_bound = sorted_results.front().score * (1.f - percent_scan);
164 u32 num_scanned_groups = 0;
165 for (; num_scanned_groups < sorted_results.size(); ++num_scanned_groups)
167 if (sorted_results[num_scanned_groups].score < lower_score_bound)
172 auto scanned_group_size = sorted_results[num_scanned_groups].group->size();
174 if (!first_is_bad && scanned_group_size < min_group_size)
178 if (first_is_preferred && std::find(config.prioritized_sizes.begin(), config.prioritized_sizes.end(), scanned_group_size) == config.prioritized_sizes.end())
185 std::vector<float> badness_score_of_group(num_scanned_groups, 0.0f);
188 auto& scanned_group = *sorted_results[scanned_group_idx].group;
190 std::vector<u32> unaffected_gates;
191 unaffected_gates.reserve(unassigned_gates.size() - scanned_group.size());
192 std::set_difference(unassigned_gates.begin(), unassigned_gates.end(), scanned_group.begin(), scanned_group.end(), std::back_inserter(unaffected_gates));
198 std::unordered_set<u32> affected_groups;
200 for (
auto g : scanned_group)
202 auto& gg = groups_of_gate.at(
g);
203 affected_groups.insert(gg.begin(), gg.end());
205 affected_groups.erase(scanned_group_idx);
207 for (
auto gr : affected_groups)
209 if (std::find(config.prioritized_sizes.begin(), config.prioritized_sizes.end(), sorted_results[gr].group->size()) != config.prioritized_sizes.end())
216 for (
auto g : unaffected_gates)
218 if (max_group_size_of_gate.at(
g) < min_group_size)
226 badness_score_of_group[scanned_group_idx] = score;
232 u32 best_choice = std::distance(badness_score_of_group.begin(), std::min_element(badness_score_of_group.begin(), badness_score_of_group.end()));
233 auto best_group = *sorted_results[best_choice].group;
237 u32 new_group_id = ++id_counter;
239 output->group_control_fingerprint_map[new_group_id] = netlist_abstr.gate_to_fingerprint.at(*best_group.begin());
240 output->operations_on_group_allowed[new_group_id] =
true;
242 output->gates_of_group[new_group_id].insert(best_group.begin(), best_group.end());
243 for (
const auto& sg : best_group)
245 output->parent_group_of_gate[sg] = new_group_id;
249 unassigned_gates.erase(std::remove_if(unassigned_gates.begin(), unassigned_gates.end(), [&best_group](
auto id) { return best_group.find(id) != best_group.end(); }),
250 unassigned_gates.end());
253 sorted_results.erase(std::remove_if(sorted_results.begin(),
254 sorted_results.end(),
255 [&best_group](
auto check_group) {
256 return std::any_of(check_group.group->begin(), check_group.group->end(), [&best_group](auto check_group_gate) {
257 return best_group.find(check_group_gate) != best_group.end();
260 sorted_results.end());
262 progress_bar.
clear();
264 for (
auto g : unassigned_gates)
266 u32 new_group_id = ++id_counter;
268 output->group_control_fingerprint_map[new_group_id] = netlist_abstr.gate_to_fingerprint.at(
g);
269 output->operations_on_group_allowed[new_group_id] =
true;
271 output->gates_of_group[new_group_id].insert(
g);
272 output->parent_group_of_gate[
g] = new_group_id;
283 output.is_final_result =
false;
285 auto scores = compute_scores(result);
287 output.merged_result = generate_output(config, initial_grouping, scores);
293 log_info(
"dataflow",
"result does not improve anymore");
297 log_info(
"dataflow",
"found a cycle");
300 output.is_final_result =
true;
301 log_info(
"dataflow",
"voting done");
void print_message_to_gui(const std::string &message)
void print_progress_to_gui(int percent=-1)
void print_progress_to_stderr(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)