43 #include "config_HAVE_ASSERTS.hpp" 44 #include "config_PANDA_DATA_INSTALLDIR.hpp" 68 return SimulationTool::MODELSIM;
70 else if(str ==
"XSIM")
72 return SimulationTool::XSIM;
74 else if(str ==
"VERILATOR")
76 return SimulationTool::VERILATOR;
82 return SimulationTool::UNKNOWN;
86 const std::string& _inc_dirs)
98 const std::string& suffix,
const std::string&
top_fname,
116 THROW_ERROR(
"Simulation tool currently not supported");
131 THROW_ERROR(
"Simulation script not yet generated");
135 auto result_file =
Param->getOption<std::string>(OPT_simulation_output);
136 if(std::filesystem::exists(result_file))
138 std::filesystem::remove_all(result_file);
140 auto profiling_result_file =
Param->getOption<std::string>(OPT_profiling_output);
141 if(std::filesystem::exists(profiling_result_file))
143 std::filesystem::remove_all(profiling_result_file);
147 std::vector<std::string>
parameters, input_files, output_files;
148 if(
Param->isOption(OPT_testbench_argv))
150 const auto tb_argv =
Param->getOption<std::string>(OPT_testbench_argv);
151 parameters.push_back(tb_argv);
153 tool->
execute(parameters, input_files, output_files,
154 Param->getOption<std::string>(OPT_output_temporary_directory) +
"/simulation_output",
true);
161 unsigned long long int num_cycles = 0;
162 unsigned long long i = 0;
163 const auto sim_period = 2.0l;
164 const auto result_file =
Param->getOption<std::string>(OPT_simulation_output);
165 const auto profiling_result_file =
Param->getOption<std::string>(OPT_profiling_output);
166 const auto discrepancy_enabled =
Param->isOption(OPT_discrepancy) &&
Param->getOption<
bool>(OPT_discrepancy);
167 const auto profiling_enabled = std::filesystem::exists(profiling_result_file);
168 if(!std::filesystem::exists(result_file))
170 THROW_ERROR(
"The simulation does not end correctly");
173 std::ifstream res_file(result_file);
174 if(!res_file.is_open())
180 std::getline(res_file, values);
185 const auto sim_times = string_to_container<std::vector<std::string>>(values,
",");
186 for(
const auto& start_end : sim_times)
188 if(start_end.back() ==
'X')
190 if(discrepancy_enabled)
197 else if(start_end.back() ==
'A')
199 THROW_ERROR(
"Simulation terminated with abort call!");
201 if(!profiling_enabled)
205 unsigned long long start_time = 0, end_time = 0;
206 if(!boost::conversion::try_lexical_convert<unsigned long long>(
times.at(0), start_time) ||
207 !boost::conversion::try_lexical_convert<unsigned long long>(
times.at(1), end_time))
209 THROW_ERROR(
"Unable to parse simulation time report: check simulator output for errors.");
211 THROW_ASSERT(end_time >= start_time,
"Simulation went back in time");
212 const auto sim_time =
static_cast<long double>(end_time - start_time);
213 const auto sim_cycles =
static_cast<unsigned long long int>(std::ceil(sim_time / sim_period));
214 num_cycles += sim_cycles;
217 "Run " << i <<
" execution time " << sim_cycles <<
" cycles;");
221 if(profiling_enabled)
223 std::ifstream profiling_res_file(profiling_result_file.c_str());
224 if(!profiling_res_file.is_open())
226 THROW_ERROR(
"Profiling result file not correctly created");
230 std::getline(profiling_res_file, values);
231 const auto profile_times = string_to_container<std::vector<std::string>>(values,
",");
232 for(
const auto& start_end : profile_times)
236 unsigned long long start_time = 0, end_time = 0;
237 if(!boost::conversion::try_lexical_convert<unsigned long long>(
times.at(0), start_time) ||
238 !boost::conversion::try_lexical_convert<unsigned long long>(
times.at(1), end_time))
240 THROW_ERROR(
"Unable to parse simulation time report: check simulator output for errors.");
242 THROW_ASSERT(end_time >= start_time,
"Profiling went back in time");
243 const auto sim_time =
static_cast<long double>(end_time - start_time);
244 const auto sim_cycles =
static_cast<unsigned long long int>(std::ceil(sim_time / sim_period));
245 num_cycles += sim_cycles;
248 "Run " << i <<
" profiled execution time " << sim_cycles <<
" cycles;");
252 std::getline(res_file, values);
253 if(values.back() ==
'A')
260 cosim_retval = std::stoi(values);
264 THROW_ERROR(
"Co-simulation completed unexpectedly.");
269 THROW_ERROR(
"Co-simulation main returned non-zero value: " + values);
274 THROW_ERROR(
"Expected a number of cycles different from zero. Something wrong happened during the simulation!");
276 accum_cycles = num_cycles;
286 std::filesystem::perms::owner_exec | std::filesystem::perms::group_exec |
287 std::filesystem::perms::others_exec,
289 script <<
"#!/bin/bash\n" 290 <<
"##########################################################\n" 291 <<
"# Automatically generated by the PandA framework #\n" 292 <<
"##########################################################\n" 293 <<
"# Simulation script for COMPONENT: " << top_filename <<
"\n" 296 <<
"if [ ! -z \"$APPDIR\" ]; then LD_LIBRARY_PATH=\"\"; fi\n";
300 const auto has_user_elf =
Param->isOption(OPT_testbench_input_file) &&
301 starts_with(
Param->getOption<std::string>(OPT_testbench_input_file),
"elf:");
305 const auto sim_dir =
Param->getOption<std::string>(OPT_output_directory) +
"/simulation/";
306 auto compiler_env = std::regex_replace(
"\n" + compiler_wrapper->GetCompiler().gcc,
307 std::regex(
"([\\w\\d]+=(\".*\"|[^\\s]+))\\s*"),
"export $1\n");
308 boost::replace_last(compiler_env,
"\n",
"\nCC=\"");
309 compiler_env +=
"\"";
311 script << compiler_env <<
"\n";
315 script <<
"SYS_ELF=\"" <<
Param->getOption<std::string>(OPT_testbench_input_file).substr(4) <<
"\"\n";
319 script <<
"SYS_ELF=\"" << sim_dir <<
"/testbench\"\n";
322 script <<
"SIM_DIR=\"" << sim_dir <<
"\"\n" 323 <<
"OUT_LVL=\"" <<
Param->getOption<
int>(OPT_output_level) <<
"\"\n\n" 324 <<
"### Do not edit below\n\n" 325 <<
"M_IPC_FILENAME=\"${SIM_DIR}/panda_sock\"\n";
328 boost::replace_all(sim_cmd,
"\"",
"\\\"");
330 <<
"export M_IPC_SIM_CMD=\"" << sim_cmd <<
"; exit \\${PIPESTATUS[0]};\"\n\n" 331 <<
"if [ -f ${SYS_ELF} ]; then\n" 332 <<
" function get_class { readelf -h $1 | grep Class: | sed -E 's/.*Class:\\s*(\\w+)/\\1/'; }\n" 333 <<
" sys_elf_class=\"$(get_class ${SYS_ELF})\"\n" 334 <<
" driver_elf_class=\"$(get_class ${SIM_DIR}/libmdpi_driver.so)\"\n" 335 <<
" if [ \"${sys_elf_class}\" != \"${driver_elf_class}\" ]; then\n" 336 <<
" echo \"ERROR: Wrong system application ELF class: ${sys_elf_class} != ${driver_elf_class}\"; exit 1;\n" 338 <<
" echo \"Launch user testbench with args: $@\"\n ";
341 script <<
"LD_PRELOAD=${SIM_DIR}/libmdpi_driver.so ";
343 script <<
"${SYS_ELF} \"$@\" 2>&1 | tee ${SIM_DIR}/$(basename ${SYS_ELF}).log\n" 344 <<
" exit ${PIPESTATUS[0]}\n" 352 std::string& beh_cflags)
const 358 const auto extra_compiler_flags = [&]() {
359 std::string flags =
" -fwrapv -ffloat-store -flax-vector-conversions -msse2 -mfpmath=sse -fno-strict-aliasing " 360 "-D__builtin_bambu_time_start\\(\\)= -D__builtin_bambu_time_stop\\(\\)= -D__BAMBU_SIM__";
362 if(!
Param->isOption(OPT_input_format) ||
365 flags +=
" -fexcess-precision=standard";
367 if(
Param->isOption(OPT_gcc_optimizations))
370 if(gcc_parameters.find(
"tree-vectorize") != gcc_parameters.end())
372 boost::replace_all(flags,
"-msse2",
"");
378 auto cflags = compiler_wrapper->GetCompilerParameters(extra_compiler_flags);
380 std::string kill_printf;
381 if(std::regex_search(cflags.c_str(), what, std::regex(
"\\s*(\\-D'?printf[^=]*='?)'*")))
383 kill_printf.append(what[1].first, what[1].second);
384 cflags.erase(static_cast<size_t>(what[0].first - cflags.c_str()),
385 static_cast<size_t>(what[0].second - what[0].first));
388 beh_cflags +=
" -D__M_IPC_FILENAME=\\\\\\\"${M_IPC_FILENAME}\\\\\\\"";
389 beh_cflags +=
" -D__M_OUT_LVL=${OUT_LVL}";
390 if(cflags.find(
"-m32") != std::string::npos)
392 beh_cflags +=
" -D__M32";
394 else if(cflags.find(
"-mx32") != std::string::npos)
396 beh_cflags +=
" -D__MX32";
398 else if(cflags.find(
"-m64") != std::string::npos)
400 beh_cflags +=
" -D__M64";
402 beh_cflags +=
" -O2";
411 const auto pp_srcs =
Param->isOption(OPT_pretty_print) ?
Param->getOption<std::string>(OPT_pretty_print) :
"";
412 const auto tb_srcs = [&]() {
414 if(
Param->isOption(OPT_testbench_input_file))
421 for(
const auto&
filename : tb_files)
425 files += cosim_src +
" ";
433 else if(
Param->isOption(OPT_testbench_input_string))
435 files += cosim_src +
" ";
437 if(
Param->isOption(OPT_no_parse_files))
446 const auto tb_extra_cflags =
447 Param->isOption(OPT_tb_extra_gcc_options) ?
Param->getOption<std::string>(OPT_tb_extra_gcc_options) :
"";
450 <<
" SIM_DIR=\"${SIM_DIR}\" BEH_DIR=\"" << beh_dir <<
"\" \\\n" 451 <<
" TOP_FNAME=\"" <<
top_fname <<
"\" \\\n" 452 <<
" MTOP_FNAME=\"" << m_top_fname <<
"\" \\\n" 453 <<
" MPPTOP_FNAME=\"" << m_pp_top_fname <<
"\" \\\n" 454 <<
" CC=\"${CC}\" \\\n" 455 <<
" BEH_CC=\"${BEH_CC}\" \\\n" 456 <<
" CFLAGS=\"" << cflags <<
"\" \\\n" 457 <<
" BEH_CFLAGS=\"" << beh_cflags <<
"\" \\\n" 458 <<
" TB_CFLAGS=\"" << tb_extra_cflags <<
"\" \\\n" 459 <<
" SRCS=\"" << srcs <<
"\" \\\n" 460 <<
" COSIM_SRC=\"" << cosim_src <<
"\" \\\n" 461 <<
" PP_SRC=\"" << pp_srcs <<
"\" \\\n" 462 <<
" TB_SRCS=\"" << tb_srcs <<
"\" \\\n" 463 <<
" -j " << std::thread::hardware_concurrency() <<
" -f Makefile.mk\n\n";
Main class for wrapping Verilator.
#define STR_CST_string_separator
The character used to separate concatenated string.
const std::vector< std::string > SplitString(const std::string &input, const std::string &separators)
Function which splits a string into tokens.
Main class for wrapping VIVADO XSIM Xilinx.
CompilerWrapper_OptimizationSet
Possible optimization sets.
Auxiliary methods for manipulating string.
bool starts_with(const std::string &str, const std::string &pattern)
Wrapper to Verilator simulator.
redefinition of set to manage ordered/unordered structures
utility function used to read files.
CompilerWrapper_CompilerTarget
target of the compiler
bool ends_with(const std::string &str, const std::string &pattern)
This file collects some utility functions and macros.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
constants used in testbench generation
void add(int accelnum, int startidx, int endidx)
#define OUTPUT_LEVEL_PEDANTIC
verbose debugging print is performed.
std::string GetPath(std::filesystem::path path)
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Parameters_FileFormat
File formats.
Wrapper to XSIM by XILINX VIVADO.
this class is used to manage the command-line or XML options.
std::string GetCurrentPath()
Main class for wrapping the frontend compiler.
#define PRINT_OUT_MEX(profLevel, curprofLevel, mex)
#define OUTPUT_LEVEL_VERBOSE
verbose debugging print is performed.
std::string relocate_compiler_path(const std::string &path, bool resolve_path=false)
std::string cxa_prefix_mangled(const std::string &signature, const std::string &prefix)
#define STR_CST_testbench_generation_basename
The basename of the testbench 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 ...
Implementation of the wrapper to Gcc for C sources.