HAL
plugin_dataflow.cpp
Go to the documentation of this file.
2 
8 
9 #include <chrono>
10 #include <thread>
11 
12 namespace hal
13 {
14  extern std::unique_ptr<BasePluginInterface> create_plugin_instance()
15  {
16  return std::make_unique<DataflowPlugin>();
17  }
18 
19  std::string DataflowPlugin::get_name() const
20  {
21  return std::string("dataflow");
22  }
23 
24  std::string DataflowPlugin::get_version() const
25  {
26  return std::string("0.3");
27  }
28 
29  std::string DataflowPlugin::get_description() const
30  {
31  return "Dataflow analysis tool DANA to recover word-level structures such as registers from gate-level netlists.";
32  }
33 
34  std::set<std::string> DataflowPlugin::get_dependencies() const
35  {
36  return {};
37  }
38 
40  {
41  m_extensions.push_back(new CliExtensionDataflow());
42  m_extensions.push_back(new GuiExtensionDataflow());
43  }
44 
46  {
47  ProgramOptions description;
48 
49  description.add("--dataflow", "execute the dataflow plugin");
50 
51  description.add("--path", "specify output path", {""});
52 
53  description.add("--sizes", "(optional) specify sizes to be prioritized", {""});
54 
55  description.add("--bad_group_size", "(optional) specify the bad group size", {""});
56 
57  return description;
58  }
59 
61  {
62  UNUSED(args);
63 
64  dataflow::Configuration config(nl);
65  std::string path;
66 
67  if (args.is_option_set("--path"))
68  {
69  if (args.get_parameter("--path").back() == '/')
70  path = args.get_parameter("--path");
71  else
72  path = args.get_parameter("--path") + "/";
73  }
74  else
75  {
76  log_error("dataflow", "path parameter not set");
77  }
78 
79  if (args.is_option_set("--sizes"))
80  {
81  std::istringstream f(args.get_parameter("--sizes"));
82  std::string s;
83  while (std::getline(f, s, ','))
84  {
85  config.expected_sizes.push_back(std::stoi(s));
86  }
87  }
88 
89  if (args.is_option_set("--bad_group_size"))
90  {
91  std::istringstream f(args.get_parameter("--bad_group_size"));
92  std::string s;
93  while (std::getline(f, s, ','))
94  {
95  config.min_group_size = std::stoi(s);
96  }
97  }
98 
99  auto grouping_res = dataflow::analyze(config);
100  if (grouping_res.is_error())
101  {
102  log_error("dataflow", "dataflow analysis failed:\n{}", grouping_res.get_error().get());
103  return false;
104  }
105 
106  return true;
107  }
108 
109  std::vector<PluginParameter> GuiExtensionDataflow::get_parameter() const
110  {
111  std::vector<PluginParameter> retval;
112  retval.push_back(PluginParameter(PluginParameter::String, "sizes", "Expected register size (optional)", "8,16,32"));
113  retval.push_back(PluginParameter(PluginParameter::Integer, "min_group_size", "Minimum size of a group, smaller groups will be penalized (default: 8)", "8"));
114  retval.push_back(PluginParameter(PluginParameter::ExistingDir, "output", "Directory for results (required)"));
115  retval.push_back(PluginParameter(PluginParameter::Boolean, "register_stage_identification", "Enable register stage identification (default: off)", "false"));
116  retval.push_back(PluginParameter(PluginParameter::Boolean, "write_txt", "Write a .txt file containing analysis results (default: on)", "true"));
117  retval.push_back(PluginParameter(PluginParameter::Boolean, "create_modules", "Create modules for all registers (default: on)", "true"));
118  retval.push_back(PluginParameter(PluginParameter::Boolean, "write_dot", "Write a .dot file describing the dataflow graph (not recommended for large netlist; default: off)", "false"));
119  retval.push_back(PluginParameter(PluginParameter::PushButton, "exec", "Execute dataflow analysis"));
120  return retval;
121  }
122 
123  void GuiExtensionDataflow::set_parameter(const std::vector<PluginParameter>& params)
124  {
125  for (const PluginParameter& par : params)
126  {
127  if (par.get_tagname() == "sizes")
128  {
129  std::istringstream f(par.get_value());
130  std::string s;
131  while (std::getline(f, s, ','))
132  {
133  m_expected_sizes.emplace_back(std::stoi(s));
134  }
135  }
136  else if (par.get_tagname() == "min_group_size")
137  {
138  m_min_group_size = atoi(par.get_value().c_str());
139  }
140  else if (par.get_tagname() == "write_txt")
141  {
142  m_write_txt = (par.get_value() == "true");
143  }
144  else if (par.get_tagname() == "write_dot")
145  {
146  m_write_dot = (par.get_value() == "true");
147  }
148  else if (par.get_tagname() == "output")
149  {
150  m_output_path = par.get_value();
151  }
152  else if (par.get_tagname() == "create_modules")
153  {
154  m_create_modules = (par.get_value() == "true");
155  }
156  else if (par.get_tagname() == "register_stage_identification")
157  {
158  m_enable_stages = (par.get_value() == "true");
159  }
160  else if (par.get_tagname() == "exec")
161  {
162  m_button_clicked = (par.get_value() == "clicked");
163  }
164  }
165  }
166 
167  void GuiExtensionDataflow::execute_function(std::string tag, Netlist* nl, const std::vector<u32>&, const std::vector<u32>&, const std::vector<u32>&)
168  {
169  UNUSED(tag);
170 
171  if (!m_button_clicked)
172  return;
173  if (!nl)
174  {
175  log_warning("dataflow", "Error setting paramater: no netlist loaded.");
176  return;
177  }
178 
180  {
181  GuiExtensionDataflow::s_progress_indicator_function(0, "dataflow analysis running ...");
182  }
183 
185 
186  auto config = dataflow::Configuration(nl)
187  .with_expected_sizes(m_expected_sizes)
188  .with_min_group_size(m_min_group_size)
189  .with_stage_identification(m_enable_stages)
191  .with_gate_types({GateTypeProperty::ff});
192  auto grouping_res = dataflow::analyze(config);
193  if (grouping_res.is_error())
194  {
195  log_error("dataflow", "dataflow analysis failed:\n{}", grouping_res.get_error().get());
196  return;
197  }
198  auto grouping = grouping_res.get();
199 
200  if (m_write_dot)
201  {
202  if (const auto res = grouping.write_dot(m_output_path); res.is_error())
203  {
204  log_error("dataflow", "could not write .dot file:\n{}", res.get_error().get());
205  }
206  }
207 
208  if (m_write_txt)
209  {
210  if (const auto res = grouping.write_txt(m_output_path); res.is_error())
211  {
212  log_error("dataflow", "could not write .txt file:\n{}", res.get_error().get());
213  }
214  }
215 
216  if (m_create_modules)
217  {
218  if (const auto res = grouping.create_modules(); res.is_error())
219  {
220  log_error("dataflow", "could not create modules:\n{}", res.get_error().get());
221  }
222  }
223 
225  {
226  GuiExtensionDataflow::s_progress_indicator_function(100, "dataflow analysis finished");
227  }
228  }
229 
230  std::function<void(int, const std::string&)> GuiExtensionDataflow::s_progress_indicator_function = nullptr;
231 
232  void GuiExtensionDataflow::register_progress_indicator(std::function<void(int, const std::string&)> pif)
233  {
235  }
236 
237 } // namespace hal
std::vector< AbstractExtensionInterface * > m_extensions
virtual bool handle_cli_call(Netlist *netlist, ProgramArguments &args) override
virtual ProgramOptions get_cli_options() const override
DataflowPlugin()
Constructor for DataflowPlugin.
std::string get_name() const override
Get the name of the plugin.
std::set< std::string > get_dependencies() const override
Get the plugin dependencies.
std::string get_version() const override
Get the version of the plugin.
std::string get_description() const override
Get a short description of the plugin.
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 plugin on the given netlist.
virtual void register_progress_indicator(std::function< void(int, const std::string &)> pif) override
std::vector< PluginParameter > get_parameter() const override
Get a vector of configurable parameters.
void set_parameter(const std::vector< PluginParameter > &params) override
Set values for a vector of configurable parameters.
static std::function< void(int, const std::string &)> s_progress_indicator_function
bool add(const std::string &flag, const std::string &description, const std::initializer_list< std::string > &parameters={})
#define UNUSED(expr)
Definition: defines.h:49
#define log_error(channel,...)
Definition: log.h:78
#define log_warning(channel,...)
Definition: log.h:76
hal::Result< dataflow::Result > analyze(const Configuration &config)
Analyze the gate-level netlist to identify word-level structures such as registers.
Definition: dataflow.cpp:12
std::unique_ptr< BasePluginInterface > create_plugin_instance()
Definition: plugin_gui.cpp:71
This file contains the class that holds all information of a dataflow analysis grouping.
Configuration of a dataflow analysis run.
Definition: configuration.h:61
std::vector< u32 > expected_sizes
Expected group sizes. Groups of these sizes will be prioritized. Defaults to an empty vector.
Definition: configuration.h:82
Configuration & with_control_pin_types(const std::set< PinType > &types, bool overwrite=false)
Set the pin types of the pins to be considered control pins by dataflow analysis.
Configuration & with_stage_identification(bool enable=true)
Enable stage identification as part of dataflow analysis.
u32 min_group_size
Minimum size of a group. Smaller groups will be penalized during analysis. Defaults to 8.
Definition: configuration.h:77
Configuration & with_expected_sizes(const std::vector< u32 > &sizes)
Set the expected group sizes. Groups of these sizes will be prioritized.
Configuration & with_min_group_size(u32 size)
Set the minimum size of a group. Smaller groups will be penalized during analysis.