46 #include "config_PANDA_DATA_INSTALLDIR.hpp" 65 #define XST_NUMBER_OF_SLICE_REGISTERS "XST_NUMBER_OF_SLICE_REGISTERS" 66 #define XST_NUMBER_OF_SLICE_LUTS "XST_NUMBER_OF_SLICE_LUTS" 67 #define XST_NUMBER_OF_LUT_FLIP_FLOP_PAIRS_USED "XST_NUMBER_OF_LUT_FLIP_FLOP_PAIRS_USED" 68 #define XST_NUMBER_OF_BLOCK_RAMFIFO "XST_NUMBER_OF_BLOCK_RAMFIFO" 70 #define VIVADO_XILINX_LUT_FLIP_FLOP_PAIRS_USED "XILINX_LUT_FLIP_FLOP_PAIRS_USED" 71 #define VIVADO_XILINX_SLICE "XILINX_SLICE" 72 #define VIVADO_XILINX_SLICE_REGISTERS "XILINX_SLICE_REGISTERS" 73 #define VIVADO_XILINX_SLICE_LUTS "XILINX_SLICE_LUTS" 74 #define VIVADO_XILINX_BLOCK_RAMFIFO "XILINX_BLOCK_RAMFIFO" 75 #define VIVADO_XILINX_IOPIN "XILINX_IOPIN" 76 #define VIVADO_XILINX_DSPS "XILINX_DSPS" 77 #define VIVADO_XILINX_OUTPUT "XILINX_OUTPUT" 78 #define VIVADO_XILINX_POWER "XILINX_POWER" 79 #define VIVADO_XILINX_DESIGN_DELAY "XILINX_DESIGN_DELAY" 80 #define VIVADO_XILINX_URAM "XILINX_URAM" 88 std::filesystem::create_directories(
UCF_SUBDIR);
102 default_data[
"Kintex-Ultrascale-VVD"] =
"Kintex-Ultrascale-VVD.data";
103 default_data[
"Alveo-Ultrascale-VVD"] =
"Alveo-Ultrascale-VVD.data";
106 if(
Param->isOption(OPT_target_device_script))
108 auto xml_file_path =
Param->getOption<std::string>(OPT_target_device_script);
109 if(!std::filesystem::exists(xml_file_path))
111 THROW_ERROR(
"File \"" + xml_file_path +
"\" does not exist!");
118 std::string device_string;
119 if(
device->has_parameter(
"family"))
121 device_string =
device->get_parameter<std::string>(
"family");
125 device_string =
"Zynq-VVD";
128 if(
Param->isOption(OPT_generate_taste_architecture) and
Param->getOption<
bool>(OPT_generate_taste_architecture))
130 device_string = device_string +
"-Taste";
135 THROW_ERROR(
"Device family \"" + device_string +
"\" not supported!");
138 "---Importing default scripts for target device family: " + device_string);
150 std::ifstream output_file(fn.c_str());
151 if(output_file.is_open())
153 while(!output_file.eof())
156 getline(output_file, line);
157 if(line.size() and line.find(
"Number of Slice Registers:") != std::string::npos)
159 std::string tk =
"Number of Slice Registers:";
160 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
161 boost::algorithm::trim(token);
162 token = token.substr(0, token.find(
' '));
163 boost::algorithm::trim(token);
164 boost::replace_all(token,
",",
"");
171 else if(line.size() and line.find(
"Number of Slice Flip Flops:") != std::string::npos)
173 std::string tk =
"Number of Slice Flip Flops:";
174 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
175 boost::algorithm::trim(token);
176 token = token.substr(0, token.find(
' '));
177 boost::algorithm::trim(token);
178 boost::replace_all(token,
",",
"");
185 else if(line.size() and line.find(
"Number of 4 input LUTs:") != std::string::npos)
187 std::string tk =
"Number of 4 input LUTs:";
188 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
189 boost::algorithm::trim(token);
190 token = token.substr(0, token.find(
' '));
191 boost::algorithm::trim(token);
192 boost::replace_all(token,
",",
"");
199 else if(line.size() and line.find(
"Number of Slice LUTs:") != std::string::npos)
201 std::string tk =
"Number of Slice LUTs:";
202 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
203 boost::algorithm::trim(token);
204 token = token.substr(0, token.find(
' '));
205 boost::algorithm::trim(token);
206 boost::replace_all(token,
",",
"");
213 else if(line.size() and line.find(
"Number of occupied Slices:") != std::string::npos)
215 std::string tk =
"Number of occupied Slices:";
216 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
217 boost::algorithm::trim(token);
218 token = token.substr(0, token.find(
' '));
219 boost::algorithm::trim(token);
220 boost::replace_all(token,
",",
"");
227 else if(line.size() and line.find(
"Number of LUT Flip Flop pairs used:") != std::string::npos)
229 std::string tk =
"Number of LUT Flip Flop pairs used:";
230 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
231 boost::algorithm::trim(token);
232 token = token.substr(0, token.find(
' '));
233 boost::algorithm::trim(token);
234 boost::replace_all(token,
",",
"");
242 else if(line.size() and line.find(
"Number of DSP48Es:") != std::string::npos)
244 std::string tk =
"Number of DSP48Es:";
245 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
246 boost::algorithm::trim(token);
247 token = token.substr(0, token.find(
' '));
248 boost::algorithm::trim(token);
249 boost::replace_all(token,
",",
"");
256 else if(line.size() and line.find(
"Number of DSP48E1s:") != std::string::npos)
258 std::string tk =
"Number of DSP48E1s:";
259 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
260 boost::algorithm::trim(token);
261 token = token.substr(0, token.find(
' '));
262 boost::algorithm::trim(token);
263 boost::replace_all(token,
",",
"");
270 else if(line.size() and line.find(
"Number of BlockRAM/FIFO:") != std::string::npos)
272 std::string tk =
"Number of BlockRAM/FIFO:";
273 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
274 boost::algorithm::trim(token);
275 token = token.substr(0, token.find(
' '));
276 boost::algorithm::trim(token);
277 boost::replace_all(token,
",",
"");
284 else if(line.size() and line.find(
"Number of RAMB36E1/FIFO36E1s:") != std::string::npos)
286 std::string tk =
"Number of RAMB36E1/FIFO36E1s:";
287 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
288 boost::algorithm::trim(token);
289 token = token.substr(0, token.find(
' '));
290 boost::algorithm::trim(token);
291 boost::replace_all(token,
",",
"");
298 else if(line.size() and line.find(
"Number of FIFO16/RAMB16s:") != std::string::npos)
300 std::string tk =
"Number of FIFO16/RAMB16s:";
301 std::string token = line.substr(line.find(tk) + tk.size() + 1, line.length());
302 boost::algorithm::trim(token);
303 token = token.substr(0, token.find(
' '));
304 boost::algorithm::trim(token);
305 boost::replace_all(token,
",",
"");
329 for(
const auto& iter_int : list_int)
331 const auto* EnodeC = GetPointer<const xml_element>(iter_int);
337 if(EnodeC->get_name() ==
"application")
340 for(
const auto& iter_sec : list_sec)
342 const auto* nodeS = GetPointer<const xml_element>(iter_sec);
348 if(nodeS->get_name() ==
"section")
350 std::string stringID;
351 if(
CE_XVM(stringID, nodeS))
355 if(stringID ==
"XST_DEVICE_UTILIZATION_SUMMARY")
358 for(
const auto& it_item : list_item)
360 const auto* nodeIt = GetPointer<const xml_element>(it_item);
361 if(!nodeIt or nodeIt->get_name() !=
"item")
366 if(
CE_XVM(stringID, nodeIt))
371 if(stringID !=
"XST_SELECTED_DEVICE")
377 boost::replace_all(value,
",",
"");
415 catch(
const char* msg)
417 std::cerr << msg << std::endl;
419 catch(
const std::string& msg)
421 std::cerr << msg << std::endl;
423 catch(
const std::exception& ex)
425 std::cout <<
"Exception caught: " << ex.what() << std::endl;
429 std::cerr <<
"unknown exception" << std::endl;
431 THROW_ERROR(
"Error during XST report parsing: " + fn);
436 std::ifstream output_file(log_file.c_str());
437 if(output_file.is_open())
439 while(!output_file.eof())
442 getline(output_file, line);
443 if(line.size() and line.find(
"Minimum period:") != std::string::npos)
445 if(line.find(
"No path found") != std::string::npos)
452 std::string token(
"Minimum period:");
453 std::string tk = line.substr(line.find(token) + token.size() + 1, line.size());
455 tk = tk.substr(0, tk.find_first_of(
' '));
456 boost::replace_all(tk,
"ns",
"");
459 if(std::stod(tk) >
Param->getOption<
double>(OPT_clock_period))
461 CopyFile(
Param->getOption<std::string>(OPT_output_directory) +
"/Synthesis/xst/" +
463 Param->getOption<std::string>(OPT_output_directory) +
"/" +
flow_name +
"/" +
480 std::ifstream output_file(log_file.c_str());
481 if(output_file.is_open())
483 while(!output_file.eof())
486 getline(output_file, line);
487 if(line.size() and line.find(
"Number of DSP48Es:") != std::string::npos)
489 std::string token(
"Number of DSP48Es:");
490 std::string tk = line.substr(line.find(token) + token.size() + 1, line.size());
492 tk = tk.substr(0, tk.find_first_of(
' '));
514 for(
const auto& iter_int : list_int)
516 const auto* EnodeC = GetPointer<const xml_element>(iter_int);
521 if(
flow_name ==
"Characterization" and EnodeC->get_name() ==
"twBody" &&
522 EnodeC->CGetDescendants(
"twErrRpt/twConst/twPathRpt/twConstPath/twSlack").size())
524 const auto tw_slacks = EnodeC->CGetDescendants(
"twErrRpt/twConst/twPathRpt/twConstPath/twSlack");
525 if(tw_slacks.size() == 0)
529 if(tw_slacks.size() > 1)
533 const auto tw_slack = *(tw_slacks.begin());
534 THROW_ASSERT(GetPointer<const xml_element>(tw_slack),
"");
535 return GetPointer<const xml_element>(tw_slack)->get_child_text();
537 else if(EnodeC->get_name() ==
"twSum")
540 for(
const auto& iter : list)
542 const auto* Enode = GetPointer<const xml_element>(iter);
547 if(Enode->get_name() ==
"twStats")
550 for(
const auto& iterS : listS)
552 const auto* EnodeS = GetPointer<const xml_element>(iterS);
557 if(EnodeS->get_name() ==
"twMinPer" or EnodeS->get_name() ==
"twMaxCombDel")
559 return EnodeS->get_child_text();
575 catch(
const char* msg)
577 THROW_ERROR(
"Error during TRCE report (" + fn +
") :" + *msg);
579 catch(
const std::string& msg)
581 THROW_ERROR(
"Error during TRCE report (" + fn +
") :" + msg);
583 catch(
const std::exception& ex)
585 THROW_ERROR(
"Error during TRCE report (" + fn +
") :" + ex.what());
589 THROW_ERROR(
"Error during TRCE report (" + fn +
") :" +
"Unknown exception");
596 bool is_vivado =
false;
597 std::string device_string;
598 device_string =
device->get_parameter<std::string>(
"family");
599 if(device_string.find(
"-VVD") != std::string::npos)
621 THROW_ERROR(
"the script does not have a synthesis step");
644 THROW_ERROR(
"the script does not have a timing evaluation step");
673 if(
design_values[VIVADO_XILINX_DESIGN_DELAY] >
Param->getOption<
double>(OPT_clock_period) and
679 Param->getOption<std::string>(OPT_output_directory) +
"/" +
flow_name +
"/" +
689 (
Param->IsParameter(
"DumpingTimingReport") and
Param->GetParameter<
int>(
"DumpingTimingReport"))) and
711 for(
const auto& iter_int : list_int)
713 const auto* EnodeC = GetPointer<const xml_element>(iter_int);
719 if(EnodeC->get_name() ==
"application")
722 for(
const auto& iter_sec : list_sec)
724 const auto* nodeS = GetPointer<const xml_element>(iter_sec);
730 if(nodeS->get_name() ==
"section")
732 std::string stringID;
733 if(
CE_XVM(stringID, nodeS))
737 if(stringID ==
"XILINX_SYNTHESIS_SUMMARY")
740 for(
const auto& it_item : list_item)
742 const auto* nodeIt = GetPointer<const xml_element>(it_item);
743 if(!nodeIt or nodeIt->get_name() !=
"item")
748 if(
CE_XVM(stringID, nodeIt))
757 boost::replace_all(value,
",",
"");
769 catch(
const char* msg)
771 std::cerr << msg << std::endl;
773 catch(
const std::string& msg)
775 std::cerr << msg << std::endl;
777 catch(
const std::exception& ex)
779 std::cout <<
"Exception caught: " << ex.what() << std::endl;
783 std::cerr <<
"unknown exception" << std::endl;
785 THROW_ERROR(
"Error during VIVADO report parsing: " + fn);
790 std::string setupscr;
791 std::string device_string;
792 device_string =
device->get_parameter<std::string>(
"family");
793 if(device_string.find(
"-VVD") != std::string::npos)
796 Param->isOption(OPT_xilinx_vivado_settings) ?
Param->getOption<std::string>(OPT_xilinx_vivado_settings) :
"";
800 setupscr =
Param->isOption(OPT_xilinx_settings) ?
Param->getOption<std::string>(OPT_xilinx_settings) :
"";
802 if(setupscr.size() && setupscr !=
"0")
804 script <<
"#configuration" << std::endl;
807 script << setupscr +
" >& /dev/null; ";
811 script <<
". " << setupscr <<
" >& /dev/null; ";
813 script << std::endl << std::endl;
826 std::string ise_style;
838 bool xpwr_enabled =
false;
839 if(
Param->isOption(
"power_optimization") &&
Param->getOption<
bool>(
"power_optimization"))
844 auto device_name =
device->get_parameter<std::string>(
"model");
845 auto package = device->get_parameter<std::string>("package");
846 auto speed_grade =
device->get_parameter<std::string>(
"speed_grade");
847 std::string device_string = device_name +
package + speed_grade;
850 bool is_vivado =
false;
851 if(
device->get_parameter<std::string>(
"family").find(
"-VVD") != std::string::npos)
860 std::vector<std::string> file_list = string_to_container<std::vector<std::string>>(HDL_files,
";");
861 std::string sources_macro_list;
862 bool has_vhdl_library =
Param->isOption(OPT_VHDL_library);
863 std::string vhdl_library;
866 vhdl_library =
Param->getOption<std::string>(OPT_VHDL_library);
868 for(
unsigned int v = 0; v < file_list.size(); v++)
872 sources_macro_list +=
"\n";
874 std::filesystem::path file_path(file_list[v]);
875 std::string extension = file_path.extension().string();
876 if(extension ==
".vhd" || extension ==
".vhdl" || extension ==
".VHD" || extension ==
".VHDL")
880 sources_macro_list +=
"read_vhdl -library " + vhdl_library +
" " + file_list[v];
884 sources_macro_list +=
"read_vhdl " + file_list[v];
887 else if(extension ==
".v" || extension ==
".V")
889 sources_macro_list +=
"read_verilog " + file_list[v];
891 else if(extension ==
".sv" || extension ==
".SV")
893 sources_macro_list +=
"read_verilog -sv " + file_list[v];
897 THROW_ERROR(
"Extension not recognized! " + extension);
901 if(
Param->isOption(OPT_backend_sdc_extensions))
903 sources_macro_list +=
"\nread_xdc " +
Param->getOption<std::string>(OPT_backend_sdc_extensions);
908 if(
device->get_parameter<std::string>(
"family").find(
"-YOSYS-VVD") != std::string::npos)
910 sources_macro_list =
"";
911 for(
unsigned int v = 0; v < file_list.size(); v++)
915 sources_macro_list +=
" -p ";
917 std::filesystem::path file_path(file_list[v]);
918 std::string extension = file_path.extension().string();
919 if(extension ==
".v" || extension ==
".V")
921 sources_macro_list +=
"\\\"read_verilog -defer " + file_list[v] +
"\\\"";
923 else if(extension ==
".sv" || extension ==
".SV")
925 sources_macro_list +=
"\\\"read_verilog -sv -defer " + file_list[v] +
"\\\"";
929 THROW_ERROR(
"Extension not recognized! " + extension);
940 for(
auto& step :
steps)
952 std::ofstream UCF_file(ucf_filename);
960 UCF_file <<
"BEGIN MODEL \"" << dp->
component_name <<
"\"" << std::endl;
962 UCF_file <<
"END;" << std::endl;
966 <<
" ns HIGH 50%;" << std::endl;
968 else if(
Param->isOption(OPT_connect_iob) && not
Param->getOption<
bool>(OPT_connect_iob))
970 THROW_ERROR(
"ISE needs IOB to perform timing analysis of combinational circuit");
#define PARAM_vivado_report
Wrapper to trce by XILINX.
#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.
void parse_DSPs(const std::string &log_file)
retrieve the number of DSPs from the xst log
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 DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
DesignParametersRef actual_parameters
set of design parameters with the actual values
#define GET_CLASS(obj)
Macro returning the actual type of an object.
#define PARAM_trce_report_post
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)
#define VIVADO_XILINX_LUT_FLIP_FLOP_PAIRS_USED
void xparse_timing(const std::string &fn)
Fixed the parsing of timing results from trce.
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.
~XilinxBackendFlow() override
Destructor.
std::string flow_name
string-based identifier of the flow
void set_resource_value(value_t val, double num)
void parse_timing(const std::string &log_file)
Fixed the parsing of timing results from xst.
void parse_flow(const XMLDomParserRef parser)
Creates the synthesis flow based on the user'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
Wrapper to synthesis tools by Xilinx.
Wrapper to implement a synthesis tools by Xilinx.
#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
#define STR(s)
Macro which performs a lexical_cast to a string.
#define XST_NUMBER_OF_SLICE_REGISTERS
void vivado_xparse_utilization(const std::string &fn)
parse vivado results
void line(int x1, int y1, int x2, int y2, unsigned int color)
Auxiliary methods for manipulating string.
#define VIVADO_XILINX_DSPS
#define XST_NUMBER_OF_SLICE_LUTS
void CheckSynthesisResults() override
Checks the synthesis results and fills the corresponding data-structures.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
bool starts_with(const std::string &str, const std::string &pattern)
map_t parameter_values
Map between the name of the parameter and the corresponding string-based value.
#define STR_CST_synthesis_timing_violation_report
The file containing the timing violation report.
void CopyFile(std::filesystem::path file_source, std::filesystem::path file_target)
Copy file; if target already exist, overwrite.
std::string get_name() const
Get the name of this node.
std::vector< BackendStepRef > steps
ordered list of synthesis steps
virtual void create_cf(const DesignParametersRef dp, bool xst)
Creates the UCF file.
#define VIVADO_XILINX_SLICE_REGISTERS
This file contains the definition of the parameters for the synthesis tools.
refcount< XMLDomParser > XMLDomParserRef
utility function used to read files.
virtual void ExecuteSynthesis()
Executes the synthesis with the implemented flow.
#define VIVADO_XILINX_SLICE
#define VIVADO_XILINX_POWER
void ExecuteSynthesis() override
Checks if the execution can be performed and, in case, performs the synthesis.
XilinxBackendFlow(const ParameterConstRef Param, const std::string &flow_name, const generic_deviceRef _device)
Constructor.
This file collects some utility functions and macros.
void xparse_map_utilization(const std::string &fn)
Parses the utilization file in XML format.
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
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
#define PARAM_xst_log_file
void InitDesignParameters() override
Initializes the parameters.
#define PARAM_vivado_timing_report
#define XST_NUMBER_OF_LUT_FLIP_FLOP_PAIRS_USED
Classes for handling configuration files.
std::map< std::string, double > design_values
results from the synthesis
#define VIVADO_XILINX_SLICE_LUTS
This class describes all classes used to represent a structural object.
static area_infoRef factory(const ParameterConstRef &Param)
Factory method.
std::string component_name
Name of the component.
#define OUTPUT_LEVEL_VERY_PEDANTIC
verbose debugging print is performed.
void WriteFlowConfiguration(std::ostream &script) override
Writes the proper flow configuration in the output script.
unsigned int output_level
verbosity level of the class
#define VIVADO_XILINX_DESIGN_DELAY
void set_area_value(const double &_area_)
Set the nominal value for the area of the component.
std::string get_content() const
Get the text of this content node.
void xparse_xst_utilization(const std::string &fn)
Parses the utilization file in XML format.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
xml_documentRef get_document()
Obtain the parsed document.
#define PARAM_yosys_vivado_sources_macro_list
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...
Wrapper to map by XILINX.
node_list const & get_children()
Obtain the list of child nodes.
Generic device description.
#define PRINT_OUT_MEX(profLevel, curprofLevel, mex)
void CopyStdout(const std::string &filename)
Copy a file to the standard output.
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
std::string relocate_compiler_path(const std::string &path, bool resolve_path=false)
#define VIVADO_XILINX_BLOCK_RAMFIFO
static time_infoRef factory(const ParameterConstRef Param)
#define XST_NUMBER_OF_BLOCK_RAMFIFO
#define PARAM_trce_report_pre
#define PARAM_vivado_sources_macro_list
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...