HAL  v4.5.0-133-g64838ea8d
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
plugin_xilinx_toolbox.cpp
Go to the documentation of this file.
2 
8 
9 #include <unordered_set>
10 
11 namespace hal
12 {
14  {
15  m_extensions.push_back(new GuiExtensionXilinxToolbox());
16  }
17 
18  extern std::unique_ptr<BasePluginInterface> create_plugin_instance()
19  {
20  return std::make_unique<XilinxToolboxPlugin>();
21  }
22 
23  std::string XilinxToolboxPlugin::get_name() const
24  {
25  return std::string("xilinx_toolbox");
26  }
27 
29  {
30  return std::string("0.1");
31  }
32 
34  {
35  return "A collection of functions specifically designed to operate on Xilinx FPGA netlists.";
36  }
37 
38  std::set<std::string> XilinxToolboxPlugin::get_dependencies() const
39  {
40  return {};
41  }
42 
43  namespace
44  {
49  std::vector<Gate*> gates_from_selection(Netlist* nl, const std::vector<u32>& mods, const std::vector<u32>& gats)
50  {
51  std::vector<Gate*> res;
52  std::unordered_set<Gate*> seen;
53 
54  const auto collect = [&res, &seen](Gate* g) {
55  if (g != nullptr && seen.insert(g).second)
56  {
57  res.push_back(g);
58  }
59  };
60 
61  for (u32 id : gats)
62  {
63  collect(nl->get_gate_by_id(id));
64  }
65 
66  for (u32 id : mods)
67  {
68  if (const Module* m = nl->get_module_by_id(id); m != nullptr)
69  {
70  for (Gate* g : m->get_gates(nullptr, true))
71  {
72  collect(g);
73  }
74  }
75  }
76 
77  return res;
78  }
79  } // namespace
80 
81  std::vector<ContextMenuContribution> GuiExtensionXilinxToolbox::get_context_contribution(const Netlist*, const std::vector<u32>& mods, const std::vector<u32>& gats, const std::vector<u32>& nets)
82  {
83  std::vector<ContextMenuContribution> retval;
84 
85  const auto add = [this, &retval](const std::string& tag, const std::string& entry) {
87  cmc.mContributer = this;
88  cmc.mTagname = tag;
89  cmc.mEntry = entry;
90  retval.push_back(cmc);
91  };
92 
93  // a selection is what the user is pointing at, so do not offer to run on the entire netlist next to it
94  if (!mods.empty() || !gats.empty())
95  {
96  add("split_luts_selection", "Split LUTs of selection");
97  add("split_shift_registers_selection", "Split shift registers of selection");
98  }
99  else if (!nets.empty())
100  {
101  add("remove_no_load_wires_selection", "Remove no load wires of selection");
102  }
103  else
104  {
105  add("split_luts_netlist", "Split LUTs of netlist");
106  add("split_shift_registers_netlist", "Split shift registers of netlist");
107  add("remove_no_load_wires_netlist", "Remove no load wires of netlist");
108  }
109 
110  return retval;
111  }
112 
113  void GuiExtensionXilinxToolbox::execute_function(std::string tag, Netlist* nl, const std::vector<u32>& mods, const std::vector<u32>& gats, const std::vector<u32>& nets)
114  {
115  if (nl == nullptr)
116  {
117  log_warning("xilinx_toolbox", "cannot run preprocessing: no netlist loaded.");
118  return;
119  }
120 
121  // deleting or replacing a gate makes the GUI re-layout its graph views, which would otherwise happen once
122  // per gate and dominate the runtime of the preprocessing itself
123  const xilinx_toolbox::GuiLayoutLocker layout_locker;
124 
125  // an empty scope makes the preprocessing functions consider the entire netlist
126  std::vector<Gate*> scope;
127  if (tag == "split_luts_selection" || tag == "split_shift_registers_selection")
128  {
129  scope = gates_from_selection(nl, mods, gats);
130  if (scope.empty())
131  {
132  log_warning("xilinx_toolbox", "cannot run preprocessing on the selection: no gates selected.");
133  return;
134  }
135  }
136 
137  if (tag == "split_luts_selection" || tag == "split_luts_netlist")
138  {
139  if (const auto res = xilinx_toolbox::split_luts(nl, scope); res.is_error())
140  {
141  log_error("xilinx_toolbox", "failed to split LUTs: {}", res.get_error().get());
142  }
143  else
144  {
145  log_info("xilinx_toolbox", "split {} LUTs.", res.get());
146  }
147  }
148  else if (tag == "split_shift_registers_selection" || tag == "split_shift_registers_netlist")
149  {
150  if (const auto res = xilinx_toolbox::split_shift_registers(nl, scope); res.is_error())
151  {
152  log_error("xilinx_toolbox", "failed to split shift registers: {}", res.get_error().get());
153  }
154  else
155  {
156  log_info("xilinx_toolbox", "split {} shift registers.", res.get());
157  }
158  }
159  else if (tag == "remove_no_load_wires_selection" || tag == "remove_no_load_wires_netlist")
160  {
161  std::vector<Net*> net_scope;
162  if (tag == "remove_no_load_wires_selection")
163  {
164  for (u32 id : nets)
165  {
166  if (Net* n = nl->get_net_by_id(id); n != nullptr)
167  {
168  net_scope.push_back(n);
169  }
170  }
171  if (net_scope.empty())
172  {
173  log_warning("xilinx_toolbox", "cannot remove no load wires of the selection: no nets selected.");
174  return;
175  }
176  }
177 
178  if (const auto res = xilinx_toolbox::remove_no_load_wires(nl, net_scope); res.is_error())
179  {
180  log_error("xilinx_toolbox", "failed to remove no load wires: {}", res.get_error().get());
181  }
182  else
183  {
184  log_info("xilinx_toolbox", "removed {} no load wires.", res.get());
185  }
186  }
187  else
188  {
189  log_warning("xilinx_toolbox", "unknown context menu tag '{}'.", tag);
190  }
191  }
192 } // namespace hal
std::vector< AbstractExtensionInterface * > m_extensions
Definition: gate.h:58
GUI extension interface for the Xilinx toolbox plugin.
std::vector< ContextMenuContribution > get_context_contribution(const Netlist *nl, const std::vector< u32 > &mods, const std::vector< u32 > &gats, const std::vector< u32 > &nets) override
Get the context menu entries contributed for the given selection.
void execute_function(std::string tag, Netlist *nl, const std::vector< u32 > &mods, const std::vector< u32 > &gats, const std::vector< u32 > &nets) override
Execute the context menu entry identified by the given tag.
Definition: net.h:58
Gate * get_gate_by_id(const u32 gate_id) const
Definition: netlist.cpp:195
Module * get_module_by_id(u32 module_id) const
Definition: netlist.cpp:615
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:355
XilinxToolboxPlugin()
Constructor for XilinxToolboxPlugin that registers the GUI extension.
std::string get_name() const override
Get the name of the plugin.
std::string get_version() const override
Get the version of the plugin.
std::set< std::string > get_dependencies() const override
Get the plugin dependencies.
std::string get_description() const override
Get a short description of the plugin.
Suppresses layout updates of the GUI for as long as the object exists.
uint32_t u32
Definition: defines.h:41
#define log_error(channel,...)
Definition: log.h:78
#define log_info(channel,...)
Definition: log.h:70
#define log_warning(channel,...)
Definition: log.h:76
Result< u32 > remove_no_load_wires(Netlist *nl, const std::vector< Net * > &nets={})
Remove the "no load wire" nets that Vivado writes for unused output pins.
Result< u32 > split_luts(Netlist *nl, const std::vector< Gate * > &gates={})
Split LUTs with two outputs into two separate LUT gates.
Result< u32 > split_shift_registers(Netlist *nl, const std::vector< Gate * > &gates={})
Split shift register primitives and replaces them with equivalent flip-flops chains.
Definition: defines.h:45
std::unique_ptr< BasePluginInterface > create_plugin_instance()
This file contains all functions related to the HAL plugin API.
This file contains functions specifically designed to preprocess Xilinx FPGA netlists.
GuiExtensionInterface * mContributer
This file contains a helper that suppresses layout updates of the GUI.