PandA-2024.02
NanoXploreBackendFlow.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
41 
42 #include "config_PANDA_DATA_INSTALLDIR.hpp"
43 
44 #include "DesignParameters.hpp"
45 #include "NanoXploreWrapper.hpp"
46 #include "Parameter.hpp"
47 #include "area_info.hpp"
48 #include "dbgPrintHelper.hpp"
49 #include "fileIO.hpp"
50 #include "generic_device.hpp"
51 #include "string_manipulation.hpp"
52 #include "synthesis_constants.hpp"
53 #include "time_info.hpp"
54 #include "utility.hpp"
55 #include "xml_dom_parser.hpp"
56 #include "xml_script_command.hpp"
57 
58 #define NANOXPLORE_FE "NANOXPLORE_FE"
59 #define NANOXPLORE_LUTS "NANOXPLORE_LUTS"
60 #define NANOXPLORE_SLACK "NANOXPLORE_SLACK"
61 #define NANOXPLORE_REGISTERS "NANOXPLORE_REGISTERS"
62 #define NANOXPLORE_IOPIN "NANOXPLORE_IOPIN"
63 #define NANOXPLORE_DSP "NANOXPLORE_DSPS"
64 #define NANOXPLORE_MEM "NANOXPLORE_MEM"
65 #define NANOXPLORE_POWER "NANOXPLORE_POWER"
66 
67 NanoXploreBackendFlow::NanoXploreBackendFlow(const ParameterConstRef _Param, const std::string& _flow_name,
68  const generic_deviceRef _device)
69  : BackendFlow(_Param, _flow_name, _device)
70 {
71  debug_level = _Param->get_class_debug_level(GET_CLASS(*this));
72  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---Creating NanoXplore Backend Flow ::.");
73  if(!Param->isOption(OPT_nanoxplore_root))
74  {
75  THROW_WARNING("NanoXplore install directory was not specified, fallback on path. Specifying NanoXplore root "
76  "through --nanoxplore-root option is preferred.");
77  }
78  const auto lic_path = std::getenv("LM_LICENSE_FILE");
79  const auto nx_lic_path = std::getenv("NXLMD_LICENSE_FILE");
80  if((!lic_path || std::string(lic_path) == "") && (!nx_lic_path || std::string(nx_lic_path) == ""))
81  {
82  THROW_WARNING("NanoXplore license file has not been specified. User must set LM_LICENSE_FILE or "
83  "NXLMD_LICENSE_FILE variable to point to the license file location.");
84  }
85  const auto bypass_name = std::getenv("NANOXPLORE_BYPASS");
86  if((!bypass_name || std::string(bypass_name) == "") && !Param->isOption(OPT_nanoxplore_bypass))
87  {
88  THROW_WARNING("NanoXplore bypass was not specified. User may set NANOXPLORE_BYPASS variable or use "
89  "--nanoxplore-bypass option.");
90  }
91 
92  default_data["NG-MEDIUM"] = "NG.data";
93  default_data["NG-LARGE"] = "NG.data";
94  default_data["NG-ULTRA"] = "NG.data";
95 
97  if(Param->isOption(OPT_target_device_script))
98  {
99  auto xml_file_path = Param->getOption<std::string>(OPT_target_device_script);
100  if(!std::filesystem::exists(xml_file_path))
101  {
102  THROW_ERROR("File \"" + xml_file_path + "\" does not exist!");
103  }
104  INDENT_OUT_MEX(OUTPUT_LEVEL_VERBOSE, output_level, "---Importing scripts from file: " + xml_file_path);
105  parser = XMLDomParserRef(new XMLDomParser(xml_file_path));
106  }
107  else
108  {
109  std::string device_string;
110  if(device->has_parameter("family"))
111  {
112  device_string = device->get_parameter<std::string>("family");
113  }
114  else
115  {
116  device_string = "NG-MEDIUM";
117  }
118  if(default_data.find(device_string) == default_data.end())
119  {
120  THROW_ERROR("Device family \"" + device_string + "\" not supported!");
121  }
123  "---Importing default scripts for target device family: " + device_string);
124  parser = XMLDomParserRef(
125  new XMLDomParser(relocate_compiler_path(PANDA_DATA_INSTALLDIR "/panda/wrapper/synthesis/nanoxplore/", true) +
126  default_data[device_string]));
127  }
128  parse_flow(parser);
129 }
130 
132 
133 void NanoXploreBackendFlow::xparse_utilization(const std::string& fn)
134 {
135  try
136  {
137  XMLDomParser parser(fn);
138  parser.Exec();
139  if(parser)
140  {
141  // Walk the tree:
142  const xml_element* node = parser.get_document()->get_root_node(); // deleted by DomParser.
143  THROW_ASSERT(node->get_name() == "document", "Wrong root name: " + node->get_name());
144 
145  const xml_node::node_list list_int = node->get_children();
146  for(const auto& iter_int : list_int)
147  {
148  const auto* EnodeC = GetPointer<const xml_element>(iter_int);
149  if(!EnodeC)
150  {
151  continue;
152  }
153 
154  if(EnodeC->get_name() == "application")
155  {
156  const xml_node::node_list list_sec = EnodeC->get_children();
157  for(const auto& iter_sec : list_sec)
158  {
159  const auto* nodeS = GetPointer<const xml_element>(iter_sec);
160  if(!nodeS)
161  {
162  continue;
163  }
164 
165  if(nodeS->get_name() == "section")
166  {
167  std::string stringID;
168  if(CE_XVM(stringID, nodeS))
169  {
170  LOAD_XVM(stringID, nodeS);
171  }
172  if(stringID == "NANOXPLORE_SYNTHESIS_SUMMARY")
173  {
174  const xml_node::node_list list_item = nodeS->get_children();
175  for(const auto& it_item : list_item)
176  {
177  const auto* nodeIt = GetPointer<const xml_element>(it_item);
178  if(!nodeIt or nodeIt->get_name() != "item")
179  {
180  continue;
181  }
182 
183  if(CE_XVM(stringID, nodeIt))
184  {
185  LOAD_XVM(stringID, nodeIt);
186  }
187 
188  std::string value;
189  if(CE_XVM(value, nodeIt))
190  {
191  LOAD_XVM(value, nodeIt);
192  boost::replace_all(value, ",", "");
193  design_values[stringID] = std::stod(value);
194  }
195  }
196  }
197  }
198  }
199  }
200  }
201  return;
202  }
203  }
204  catch(const char* msg)
205  {
206  std::cerr << msg << std::endl;
207  }
208  catch(const std::string& msg)
209  {
210  std::cerr << msg << std::endl;
211  }
212  catch(const std::exception& ex)
213  {
214  std::cout << "Exception caught: " << ex.what() << std::endl;
215  }
216  catch(...)
217  {
218  std::cerr << "unknown exception" << std::endl;
219  }
220  THROW_ERROR("Error during NanoXplore report parsing: " + fn);
221 }
222 
224 {
225  PRINT_OUT_MEX(OUTPUT_LEVEL_VERBOSE, output_level, "Analyzing NanoXplore synthesis results");
226  const auto report_filename = GetPath(actual_parameters->parameter_values[PARAM_nxpython_report]);
227  xparse_utilization(report_filename);
228 
229  THROW_ASSERT(design_values.find(NANOXPLORE_FE) != design_values.end(), "Missing logic elements");
231  area_m->set_area_value(design_values[NANOXPLORE_FE]);
232  area_m->set_resource_value(area_info::FUNCTIONAL_ELEMENTS, design_values[NANOXPLORE_FE]);
233  area_m->set_resource_value(area_info::SLICE_LUTS, design_values[NANOXPLORE_LUTS]);
234  area_m->set_resource_value(area_info::REGISTERS, design_values[NANOXPLORE_REGISTERS]);
235  area_m->set_resource_value(area_info::DSP, design_values[NANOXPLORE_DSP]);
236  area_m->set_resource_value(area_info::BRAM, design_values[NANOXPLORE_MEM]);
237  area_m->set_resource_value(area_info::POWER, design_values[NANOXPLORE_POWER]);
238 
240  if(design_values[NANOXPLORE_SLACK] != 0.0)
241  {
242  auto clk_val = std::stod(actual_parameters->parameter_values[PARAM_clk_period]);
243  auto del_val = design_values[NANOXPLORE_SLACK];
244  double exec_time = clk_val - del_val;
245  if(clk_val < del_val)
246  {
247  THROW_ERROR("the timing analysis is not consistent with the specified clock period");
248  }
249  time_m->set_execution_time(exec_time);
250  }
251  else
252  {
254  }
256  (Param->IsParameter("DumpingTimingReport") && Param->GetParameter<int>("DumpingTimingReport"))) &&
260  {
262  }
263 }
264 
266 {
267  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Writing flow configuration");
268  script << "#configuration" << std::endl;
269  if(Param->isOption(OPT_nanoxplore_root))
270  {
271  const auto nxroot = Param->getOption<std::string>(OPT_nanoxplore_root);
272  script << "export PATH=$PATH:" + nxroot + "/bin" << std::endl << std::endl;
273  }
274  script << "if [ ! -z \"$NXLMD_LICENSE_FILE\" ]; then" << std::endl;
275  script << " if [[ \"$NXLMD_LICENSE_FILE\" != \"$LM_LICENSE_FILE\" ]]; then" << std::endl;
276  script << " export LM_LICENSE_FILE=\"$NXLMD_LICENSE_FILE\"" << std::endl;
277  script << " fi" << std::endl;
278  script << "fi" << std::endl << std::endl;
279  if(Param->isOption(OPT_nanoxplore_bypass))
280  {
281  script << "export NANOXPLORE_BYPASS=\"" << Param->getOption<std::string>(OPT_nanoxplore_bypass) << "\""
282  << std::endl;
283  }
284  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Written flow configuration");
285 }
286 
288 {
290 }
291 
293 {
294  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->NanoXploreBackendFlow - Init Design Parameters");
295 
297  bool xpwr_enabled = false;
298  if(Param->isOption("power_optimization") && Param->getOption<bool>("power_optimization"))
299  {
300  xpwr_enabled = true;
301  }
303  const auto family = device->get_parameter<std::string>("family");
304  const auto device_name = device->get_parameter<std::string>("model");
305  const auto package = device->get_parameter<std::string>("package");
306  const auto speed_grade = device->get_parameter<std::string>("speed_grade");
307  std::string device_string = device_name + package + speed_grade;
310 
311  std::string HDL_files = actual_parameters->parameter_values[PARAM_HDL_files];
312  std::vector<std::string> file_list = string_to_container<std::vector<std::string>>(HDL_files, ";");
313  std::string sources_macro_list;
314  for(unsigned int v = 0; v < file_list.size(); v++)
315  {
316  if(v)
317  {
318  sources_macro_list += ", ";
319  }
320  sources_macro_list += "'" + file_list[v] + "'";
321  }
323 
324  for(auto& step : steps)
325  {
326  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Evaluating variables of step " + step->name);
327  step->tool->EvaluateVariables(actual_parameters);
328  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Evaluated variables of step " + step->name);
329  }
330  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--NanoXploreBackendFlow - Init Design Parameters");
331 }
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
Collect information about resource area.
#define PARAM_target_device
File containing functions and utilities to support the printing of debug messagges.
area_infoRef area_m
pointer to the data structure containing information about the resources
#define PARAM_nxpython_report
Wrapper to NanoXplore synthesis tools *.
#define PARAM_nxpython_timing_report
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
void ExecuteSynthesis() override
Checks if the execution can be performed and, in case, performs the synthesis.
DesignParametersRef actual_parameters
set of design parameters with the actual values
#define GET_CLASS(obj)
Macro returning the actual type of an object.
#define NANOXPLORE_DSP
void WriteFlowConfiguration(std::ostream &script) override
Writes the proper flow configuration in the output script.
constants used in synthesis wrappers
#define INDENT_OUT_MEX(outLevel, curOutLevel, mex)
void set_execution_time(double execution_time, unsigned int cycles=time_info::cycles_time_DEFAULT)
Definition: time_info.cpp:64
Collect information about resource performance.
#define CE_XVM(variable, node)
Check existence XML Value Macro. Check if an XML attribute is present in the XML tree.
Definition: xml_helper.hpp:88
void parse_flow(const XMLDomParserRef parser)
Creates the synthesis flow based on the user&#39;s requirements.
time_infoRef time_m
pointer to the data structure containing timing information
const generic_deviceRef device
information about the target device
int debug_level
debugging level of the class
void CheckSynthesisResults() override
Checks the synthesis results and fills the corresponding data structures.
#define THROW_WARNING(str_expr)
helper function used to throw a warning in a standard way: though it uses PRINT_DBG_MEX, the debug level used is such that the message is always printed
Definition: exceptions.hpp:300
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
void InitDesignParameters() override
Initializes the parameters.
map_t parameter_values
Map between the name of the parameter and the corresponding string-based value.
std::string get_name() const
Get the name of this node.
Definition: xml_node.hpp:132
std::vector< BackendStepRef > steps
ordered list of synthesis steps
#define NANOXPLORE_REGISTERS
This file contains the definition of the parameters for the synthesis tools.
#define PARAM_nxpython_sources_macro_list
NanoXploreBackendFlow(const ParameterConstRef Param, const std::string &flow_name, const generic_deviceRef _device)
Constructor.
refcount< XMLDomParser > XMLDomParserRef
XML DOM parser.
XML DOM parser.
utility function used to read files.
#define NANOXPLORE_MEM
~NanoXploreBackendFlow() override
Destructor.
virtual void ExecuteSynthesis()
Executes the synthesis with the implemented flow.
#define NANOXPLORE_FE
This file collects some utility functions and macros.
void Exec()
Parse an XML document from a file.
const ParameterConstRef Param
class containing all the parameters
std::list< xml_nodeRef > node_list
type for list of xml nodes
Definition: xml_node.hpp:90
std::map< std::string, std::string > default_data
map between the identifiers of the synthesis flows and the corresponding implementations ...
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
#define NANOXPLORE_POWER
Classes for handling configuration files.
Wrapper to synthesis tools by NanoXplore.
static area_infoRef factory(const ParameterConstRef &Param)
Factory method.
Definition: area_info.cpp:52
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
#define PARAM_power_optimization
#define OUTPUT_LEVEL_VERY_PEDANTIC
verbose debugging print is performed.
unsigned int output_level
verbosity level of the class
std::map< std::string, double > design_values
results from the synthesis
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
xml_documentRef get_document()
Obtain the parsed document.
this class is used to manage the command-line or XML options.
#define LOAD_XVM(variable, node)
LOAD XML Value Macro. Set a variable starting from an XML value. Conversion is performed if needed...
Definition: xml_helper.hpp:65
node_list const & get_children()
Obtain the list of child nodes.
Definition: xml_node.hpp:310
#define PARAM_clk_period
Generic device description.
void xparse_utilization(const std::string &fn)
Parses device utilization.
#define PRINT_OUT_MEX(profLevel, curprofLevel, mex)
void CopyStdout(const std::string &filename)
Copy a file to the standard output.
Definition: fileIO.hpp:106
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
#define NANOXPLORE_SLACK
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
std::string relocate_compiler_path(const std::string &path, bool resolve_path=false)
Definition: fileIO.hpp:149
static time_infoRef factory(const ParameterConstRef Param)
Definition: time_info.cpp:110
#define PARAM_target_family
#define NANOXPLORE_LUTS
#define PARAM_HDL_files
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:56 for PandA-2024.02 by doxygen 1.8.13