26 namespace pre_processing
30 void identify_all_target_gates(
const dataflow::Configuration& config, NetlistAbstraction& netlist_abstr)
32 log_info(
"dataflow",
"identifying target gates");
33 netlist_abstr.target_gates = netlist_abstr.nl->get_gates([config](
auto g) {
return config.gate_types.find(g->get_type()) != config.gate_types.end(); });
34 std::sort(netlist_abstr.target_gates.begin(), netlist_abstr.target_gates.end(), [](
const Gate* g1,
const Gate* g2) { return g1->get_id() < g2->get_id(); });
35 log_info(
"dataflow",
" #gates: {}", netlist_abstr.nl->get_gates().size());
36 log_info(
"dataflow",
" #target gates: {}", netlist_abstr.target_gates.size());
39 void identify_all_control_signals(
const dataflow::Configuration& config, NetlistAbstraction& netlist_abstr)
41 auto begin_time = std::chrono::high_resolution_clock::now();
42 log_info(
"dataflow",
"identifying control signals");
43 for (
auto sg : netlist_abstr.target_gates)
45 std::vector<u32> fingerprint;
46 auto id = sg->get_id();
48 for (
auto type : config.control_pin_types)
53 netlist_abstr.gate_to_control_signals[
id][
type].insert(
net->get_id());
54 fingerprint.push_back(
net->get_id());
58 netlist_abstr.gate_to_fingerprint[
id] = fingerprint;
64 void identify_known_groups(
const dataflow::Configuration& config, NetlistAbstraction& netlist_abstr, std::vector<std::vector<Gate*>>& known_target_groups)
67 for (
const auto& gates : config.known_gate_groups)
70 gates.begin(), gates.end(), [&netlist_abstr](
const Gate* g) { return netlist_abstr.gate_to_fingerprint.find(g->get_id()) != netlist_abstr.gate_to_fingerprint.end(); }))
72 known_target_groups.push_back(gates);
77 "known group containing gate '{}' with ID {} contains gates that are not of the target gate type, known group will be ignored...",
78 gates.front()->get_name(),
79 gates.front()->get_id());
85 void identify_successors_predecessors(
const dataflow::Configuration& config, NetlistAbstraction& netlist_abstr)
87 log_info(
"dataflow",
"identifying successors and predecessors of sequential gates...");
88 measure_block_time(
"identifying successors and predecessors of sequential gates") user_feedback::ProgressPrinter progress_bar("dataflow: preprocessing …");
92 std::unordered_map<const Net*,
u32> net_to_group_index;
93 for (
u32 i = 0; i < config.known_net_groups.
size(); i++)
95 const auto& net_group = config.known_net_groups.at(i);
96 if (net_group.size() < config.min_group_size)
101 for (
const auto*
net : net_group)
103 net_to_group_index[
net] = i;
108 std::unordered_map<const Net*, std::pair<std::unordered_set<Gate*>, std::unordered_set<u32>>> suc_cache;
109 std::unordered_map<const Net*, std::unordered_set<u32>> pred_cache;
117 const auto on_path = [](
const Net*
net,
const Net* current,
const std::vector<const Net*>& previous) {
118 return net == current || std::find(previous.cbegin(), previous.cend(),
net) != previous.cend();
120 const auto pass_on_successors = [&suc_cache, &on_path](
const Net* visited_net,
const Net* current,
const std::vector<const Net*>& previous) {
121 const auto it = suc_cache.find(visited_net);
122 if (it == suc_cache.end() || on_path(visited_net, current, previous))
127 const auto& [cached_gates, cached_net_groups] = it->second;
128 for (
const Net* n : previous)
130 auto& entry = suc_cache[n];
131 std::get<0>(entry).insert(cached_gates.cbegin(), cached_gates.cend());
132 std::get<1>(entry).insert(cached_net_groups.cbegin(), cached_net_groups.cend());
134 auto& entry = suc_cache[current];
135 std::get<0>(entry).insert(cached_gates.cbegin(), cached_gates.cend());
136 std::get<1>(entry).insert(cached_net_groups.cbegin(), cached_net_groups.cend());
138 const auto pass_on_predecessors = [&pred_cache, &on_path](
const Net* visited_net,
const Net* current,
const std::vector<const Net*>& previous) {
139 const auto it = pred_cache.find(visited_net);
140 if (it == pred_cache.end() || on_path(visited_net, current, previous))
144 const auto& cached_net_groups = it->second;
145 for (
const Net* n : previous)
147 pred_cache[n].insert(cached_net_groups.cbegin(), cached_net_groups.cend());
149 pred_cache[current].insert(cached_net_groups.cbegin(), cached_net_groups.cend());
152 for (
const auto& gate : netlist_abstr.target_gates)
155 progress_bar.report(cnt / netlist_abstr.target_gates.size());
158 if (netlist_abstr.gate_to_successors.find(gate->get_id()) == netlist_abstr.gate_to_successors.end())
160 netlist_abstr.gate_to_successors[gate->get_id()] = std::unordered_set<u32>();
162 if (netlist_abstr.gate_to_predecessors.find(gate->get_id()) == netlist_abstr.gate_to_predecessors.end())
164 netlist_abstr.gate_to_predecessors[gate->get_id()] = std::unordered_set<u32>();
166 if (netlist_abstr.gate_to_known_successor_groups.find(gate->get_id()) == netlist_abstr.gate_to_known_successor_groups.end())
168 netlist_abstr.gate_to_known_successor_groups[gate->get_id()] = std::unordered_set<u32>();
170 if (netlist_abstr.gate_to_known_predecessor_groups.find(gate->get_id()) == netlist_abstr.gate_to_known_predecessor_groups.end())
172 netlist_abstr.gate_to_known_predecessor_groups[gate->get_id()] = std::unordered_set<u32>();
175 const auto& start_fan_out_nets = gate->get_fan_out_nets();
176 std::vector<const Net*> stack(start_fan_out_nets.cbegin(), start_fan_out_nets.cend());
177 std::unordered_set<const Net*> visited;
178 std::vector<const Net*> previous;
179 while (!stack.empty())
181 const Net* current = stack.back();
183 if (!previous.empty() && current == previous.back())
191 visited.insert(current);
193 if (
const auto suc_cache_it = suc_cache.find(current); suc_cache_it != suc_cache.end())
195 auto& suc_cache_current = std::get<1>(*suc_cache_it);
196 const auto& suc_cached_gates = std::get<0>(suc_cache_current);
197 const auto& suc_cached_net_groups = std::get<1>(suc_cache_current);
200 for (
const auto* n : previous)
202 auto& suc_cache_n = suc_cache[n];
203 std::get<0>(suc_cache_n).insert(suc_cached_gates.cbegin(), suc_cached_gates.cend());
204 std::get<1>(suc_cache_n).insert(suc_cached_net_groups.cbegin(), suc_cached_net_groups.cend());
208 netlist_abstr.gate_to_known_successor_groups[gate->get_id()].insert(suc_cached_net_groups.cbegin(), suc_cached_net_groups.cend());
214 if (
const auto group_it = net_to_group_index.find(current); group_it != net_to_group_index.end())
216 std::get<1>(suc_cache[current]).insert(group_it->second);
217 for (
const auto* n : previous)
219 std::get<1>(suc_cache[n]).insert(group_it->second);
221 netlist_abstr.gate_to_known_successor_groups[gate->get_id()].insert(group_it->second);
225 for (
const auto* ep : current->get_destinations())
227 auto* g = ep->get_gate();
228 if (config.gate_types.find(g->get_type()) != config.gate_types.end())
231 auto& suc_cache_current = suc_cache[current];
232 std::get<0>(suc_cache_current).insert(g);
233 for (
const auto* n : previous)
235 std::get<0>(suc_cache[n]).insert(g);
241 for (
const auto* n : g->get_fan_out_nets())
243 if (visited.find(n) == visited.end())
250 pass_on_successors(n, current, previous);
259 previous.push_back(current);
269 const auto& start_fan_in_nets = gate->get_fan_in_nets();
270 stack = std::vector<const Net*>(start_fan_in_nets.begin(), start_fan_in_nets.end());
273 while (!stack.empty())
275 const Net* current = stack.back();
277 if (!previous.empty() && current == previous.back())
285 visited.insert(current);
287 if (
const auto pred_cache_it = pred_cache.find(current); pred_cache_it != pred_cache.end())
289 auto& pred_cached_net_groups = std::get<1>(*pred_cache_it);
292 for (
const auto* n : previous)
294 pred_cache[n].insert(pred_cached_net_groups.cbegin(), pred_cached_net_groups.cend());
298 netlist_abstr.gate_to_known_predecessor_groups[gate->get_id()].insert(pred_cached_net_groups.cbegin(), pred_cached_net_groups.cend());
304 if (
const auto group_it = net_to_group_index.find(current); group_it != net_to_group_index.end())
306 pred_cache[current].insert(group_it->second);
307 for (
const auto* n : previous)
309 pred_cache[n].insert(group_it->second);
311 netlist_abstr.gate_to_known_predecessor_groups[gate->get_id()].insert(group_it->second);
315 for (
const auto* ep : current->get_sources())
317 auto* g = ep->get_gate();
318 if (config.gate_types.find(g->get_type()) == config.gate_types.end())
321 for (
const auto* n : g->get_fan_in_nets())
323 if (visited.find(n) == visited.end())
330 pass_on_predecessors(n, current, previous);
339 previous.push_back(current);
350 std::unordered_set<Gate*> next_target_gates;
351 for (
const auto* n : start_fan_out_nets)
353 if (
const auto it = suc_cache.find(n); it != suc_cache.end())
355 const auto& cached_gates = std::get<0>(std::get<1>(*it));
356 next_target_gates.insert(cached_gates.cbegin(), cached_gates.cend());
360 for (
const auto& suc : next_target_gates)
362 netlist_abstr.gate_to_successors[gate->get_id()].insert(suc->get_id());
363 netlist_abstr.gate_to_predecessors[suc->get_id()].insert(gate->get_id());
366 progress_bar.clear();
372 log_info(
"dataflow",
"pre-processing netlist...");
375 std::vector<std::vector<Gate*>> known_target_groups;
376 std::vector<std::vector<Net*>> known_net_groups;
377 identify_all_target_gates(config, netlist_abstr);
378 identify_all_control_signals(config, netlist_abstr);
379 identify_known_groups(config, netlist_abstr, known_target_groups);
380 identify_successors_predecessors(config, netlist_abstr);
387 initial_grouping = std::make_shared<dataflow::Grouping>(netlist_abstr, known_target_groups);
389 return netlist_abstr;
This file contains the struct that holds all information on a dataflow analysis configuration.
#define log_info(channel,...)
#define log_warning(channel,...)
void identify_register_stages(NetlistAbstraction &netlist_abstr)
NetlistAbstraction run(const dataflow::Configuration &config, std::shared_ptr< dataflow::Grouping > &initial_grouping)
std::vector< Net * > get_nets_at_pins(Gate *gate, std::vector< GatePin * > pins)
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.
Configuration of a dataflow analysis run.
bool enable_stages
Enable stage identification as part of dataflow analysis. Defaults to false.
Netlist * netlist
The netlist to be analyzed.
The abstraction of the netlist that only contains gates of a specified type, e.g.,...
#define measure_block_time(X)