14 void copy_in_eps_of_gate(Netlist* new_nl,
const Gate* old_g, Gate* new_g, std::set<Net*>* add_to_set =
nullptr)
16 for (
const auto* in_ep : old_g->get_fan_in_endpoints())
18 Net* old_n = in_ep->get_net();
20 if (new_n = new_nl->get_net_by_id(old_n->get_id()); new_n ==
nullptr)
22 new_n = new_nl->create_net(old_n->get_id(), old_n->get_name());
24 new_n->add_destination(new_g, in_ep->get_pin());
28 add_to_set->insert(new_n);
33 void copy_out_eps_of_gate(Netlist* new_nl,
const Gate* old_g, Gate* new_g, std::set<Net*>* add_to_set =
nullptr)
35 for (
const auto* out_ep : old_g->get_fan_out_endpoints())
37 Net* old_n = out_ep->get_net();
39 if (new_n = new_nl->get_net_by_id(old_n->get_id()); new_n ==
nullptr)
41 new_n = new_nl->create_net(old_n->get_id(), old_n->get_name());
43 new_n->add_source(new_g, out_ep->get_pin());
47 add_to_set->insert(new_n);
55 std::set<Gate*> state_logic;
56 std::set<Net*> state_inputs, state_outputs, control_inputs, other_inputs;
58 log_info(
"hawkeye",
"start constructing round function candidate from state register candidate...");
59 auto start = std::chrono::system_clock::now();
65 for (
const auto* out_ff : state_output_reg)
69 if (ff_data_predecessors.size() != 1)
74 const auto* pred_ep = ff_data_predecessors.at(0);
75 auto* first_comb_gate = pred_ep->get_gate();
80 state_outputs.insert(pred_ep->get_net());
82 std::unordered_set<Gate*> visited;
83 std::vector<Gate*> stack = {first_comb_gate};
84 std::vector<Gate*> previous;
85 while (!stack.empty())
87 auto* current_gate = stack.back();
90 if (!previous.empty() && previous.back() == current_gate)
97 visited.insert(current_gate);
101 for (
auto* next_predecessor : current_gate->get_predecessors())
103 auto* predecessor_gate = next_predecessor->get_gate();
107 if (state_input_reg.find(predecessor_gate) != state_input_reg.end())
109 state_inputs.insert(next_predecessor->get_net());
110 state_logic.insert(current_gate);
111 state_logic.insert(previous.begin(), previous.end());
116 if (visited.find(predecessor_gate) == visited.end())
119 stack.push_back(predecessor_gate);
122 else if (state_logic.find(predecessor_gate) != state_logic.end())
124 state_logic.insert(current_gate);
125 state_logic.insert(previous.begin(), previous.end());
133 previous.push_back(current_gate);
143 std::set<Net*> visited;
144 for (
auto* gate : state_logic)
147 for (
auto* in_net : gate->get_fan_in_nets())
149 if (visited.find(in_net) != visited.end())
154 visited.insert(in_net);
156 if (in_net->get_num_of_sources() != 1)
161 if (state_inputs.find(in_net) != state_inputs.end())
166 auto* src_gate = in_net->get_sources().at(0)->get_gate();
167 if (state_logic.find(src_gate) != state_logic.end())
172 u32 num_state_destinations = in_net->get_num_of_destinations([&state_logic](
const Endpoint* ep) {
return state_logic.find(ep->
get_gate()) != state_logic.end(); });
173 if (num_state_destinations > candidate->
get_size() / 2)
175 control_inputs.insert(in_net);
179 other_inputs.insert(in_net);
185 auto round_cand = std::make_unique<RoundCandidate>();
187 auto* copied_nl = round_cand->m_netlist.get();
189 round_cand->m_size = candidate->
get_size();
191 for (
const auto* g : state_input_reg)
193 auto* new_g = copied_nl->create_gate(g->get_id(), g->get_type(), g->get_name());
194 round_cand->m_in_reg.insert(new_g);
196 copy_out_eps_of_gate(copied_nl, g, new_g);
199 for (
const auto* g : state_logic)
201 auto* new_g = copied_nl->create_gate(g->get_id(), g->get_type(), g->get_name());
202 new_g->set_data_map(g->get_data_map());
203 round_cand->m_state_logic.insert(new_g);
205 copy_in_eps_of_gate(copied_nl, g, new_g);
206 copy_out_eps_of_gate(copied_nl, g, new_g);
209 if (state_input_reg != state_output_reg)
211 for (
const auto* g : state_output_reg)
213 auto* new_g = copied_nl->create_gate(g->get_id(), g->get_type(), g->get_name());
214 round_cand->m_out_reg.insert(new_g);
216 copy_in_eps_of_gate(copied_nl, g, new_g);
222 for (
const auto* g : state_output_reg)
225 auto* new_g = copied_nl->create_gate(g->get_type(), g->get_name() +
"_OUT");
226 round_cand->m_out_reg.insert(new_g);
228 copy_in_eps_of_gate(copied_nl, g, new_g);
232 for (
const auto* state_in_net : state_inputs)
234 round_cand->m_state_inputs.insert(copied_nl->get_net_by_id(state_in_net->get_id()));
237 for (
const auto* state_out_net : state_outputs)
239 round_cand->m_state_outputs.insert(copied_nl->get_net_by_id(state_out_net->get_id()));
242 for (
const auto* control_net : control_inputs)
244 round_cand->m_control_inputs.insert(copied_nl->get_net_by_id(control_net->get_id()));
247 for (
const auto* other_net : other_inputs)
249 round_cand->m_other_inputs.insert(copied_nl->get_net_by_id(other_net->get_id()));
253 if (nl_graph_res.is_error())
255 return ERR(nl_graph_res.get_error());
257 round_cand->m_graph = std::move(nl_graph_res.get());
260 std::map<Gate*, u32> gate_to_longest_distance;
261 for (
auto* in_ff : round_cand->m_in_reg)
263 std::vector<Gate*> stack = {in_ff};
264 std::vector<Gate*> previous;
265 while (!stack.empty())
267 auto* current_gate = stack.back();
270 if (!previous.empty() && previous.back() == current_gate)
277 round_cand->m_input_ffs_of_gate[current_gate].insert(in_ff);
281 for (
auto* next_successor : current_gate->get_successors())
283 auto* successor_gate = next_successor->get_gate();
287 if (round_cand->m_out_reg.find(successor_gate) != round_cand->m_out_reg.end())
289 round_cand->m_input_ffs_of_gate[successor_gate].insert(in_ff);
295 if (round_cand->m_state_logic.find(successor_gate) != round_cand->m_state_logic.end())
297 stack.push_back(successor_gate);
300 u32 current_distance = previous.size() + 1;
301 if (
const auto dist_it = gate_to_longest_distance.find(successor_gate); dist_it != gate_to_longest_distance.end())
303 u32 stored_distance = dist_it->second;
304 if (stored_distance < current_distance)
306 gate_to_longest_distance[successor_gate] = current_distance;
311 gate_to_longest_distance[successor_gate] = current_distance;
320 previous.push_back(current_gate);
331 for (
const auto& [gate, distance] : gate_to_longest_distance)
333 round_cand->m_longest_distance_to_gate[distance].insert(gate);
336 auto duration_in_seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - start).count();
337 log_info(
"hawkeye",
"successfully constructed round function candidate from state register candidate in {:.2f} seconds", duration_in_seconds);
339 return OK(std::move(round_cand));
344 return m_netlist.get();
349 return m_graph.get();
369 return m_state_logic;
374 return m_state_inputs;
379 return m_control_inputs;
384 return m_other_inputs;
389 return m_state_outputs;
394 return m_input_ffs_of_gate;
399 return m_longest_distance_to_gate;
const GateLibrary * get_gate_library() const
A directed graph corresponding to a netlist.
static Result< std::unique_ptr< NetlistGraph > > from_netlist(Netlist *nl, bool create_dummy_vertices=false, const std::function< bool(const Net *)> &filter=nullptr)
Create a directed graph from a netlist.
A register candidate discovered by HAWKEYE.
Netlist * get_netlist() const
Get the netlist associated with the candidate.
u32 get_size() const
Get the size of the candidate, i.e., the width of its registers.
const std::set< Gate * > & get_input_reg() const
Get the candidate's input register.
const std::set< Gate * > & get_output_reg() const
Get the candidate's output register.
const std::set< Gate * > & get_state_logic() const
Get the candidate's combinational logic computing the next state.
const std::set< Net * > & get_other_inputs() const
Get the candidate's other inputs to the logic computing the next state.
const std::set< Net * > & get_control_inputs() const
Get the candidate's control inputs to the logic computing the next state.
u32 get_size() const
Get the size of the candidate, i.e., the width of its registers.
const std::map< Gate *, std::set< Gate * > > & get_input_ffs_of_gate() const
Get a map from each combinational gate of the round function to all the input flip-flops it depends o...
const std::set< Net * > & get_state_outputs() const
Get the candidate's state outputs from the logic computing the next state.
static Result< std::unique_ptr< RoundCandidate > > from_register_candidate(RegisterCandidate *candidate)
Compute a round candidate from a previously identified register candidate.
const std::map< u32, std::set< Gate * > > & get_longest_distance_to_gate() const
Get a map from an integer distance to all gates that are reachable within at most that distance when ...
const std::set< Gate * > & get_output_reg() const
Get the candidate's output register.
Netlist * get_netlist() const
Get the netlist of the round candidate. The netlist is a partial copy of the netlist of the register ...
graph_algorithm::NetlistGraph * get_graph() const
Get the netlist graph of the round candidate.
const std::set< Gate * > & get_input_reg() const
Get the candidate's input register.
const std::set< Net * > & get_state_inputs() const
Get the candidate's state inputs to the logic computing the next state.
#define log_info(channel,...)
std::unique_ptr< Netlist > create_netlist(const GateLibrary *gate_library)
Create a new empty netlist using the specified gate library.
This file contains various functions to create and load netlists.
This file contains the class that holds all information on a round candidate.