fine tuning top testbench and getting ready for testing

This commit is contained in:
tangxifan 2019-11-04 12:08:36 -07:00
parent d7bbae76a4
commit 3274a49779
6 changed files with 114 additions and 46 deletions

View File

@ -291,10 +291,14 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
/* Call defined benchmark */ /* Call defined benchmark */
print_verilog_top_random_testbench_benchmark_instance(fp, circuit_name, L_logical_blocks); print_verilog_top_random_testbench_benchmark_instance(fp, circuit_name, L_logical_blocks);
/* Find clock port to be used */
BasicPort clock_port = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
/* Add stimuli for reset, set, clock and iopad signals */ /* Add stimuli for reset, set, clock and iopad signals */
print_verilog_testbench_random_stimuli(fp, simulation_parameters, L_logical_blocks, print_verilog_testbench_clock_stimuli(fp, simulation_parameters,
std::string(CHECKFLAG_PORT_POSTFIX), clock_port);
clock_port_names, std::string(DEFAULT_CLOCK_NAME)); print_verilog_testbench_random_stimuli(fp, L_logical_blocks,
std::string(CHECKFLAG_PORT_POSTFIX), clock_port);
print_verilog_testbench_check(fp, print_verilog_testbench_check(fp,
std::string(autochecked_simulation_flag), std::string(autochecked_simulation_flag),

View File

@ -422,6 +422,7 @@ void print_verilog_preconfig_top_module(const ModuleManager& module_manager,
L_logical_blocks, device_size, L_grids, L_logical_blocks, device_size, L_grids,
L_blocks, L_blocks,
std::string(formal_verification_top_module_port_postfix), std::string(formal_verification_top_module_port_postfix),
std::string(formal_verification_top_module_port_postfix),
(size_t)verilog_default_signal_init_value); (size_t)verilog_default_signal_init_value);
/* Assign FPGA internal SRAM/Memory ports to bitstream values */ /* Assign FPGA internal SRAM/Memory ports to bitstream values */

View File

@ -108,7 +108,8 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
const vtr::Point<size_t>& device_size, const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& L_grids, const std::vector<std::vector<t_grid_tile>>& L_grids,
const std::vector<t_block>& L_blocks, const std::vector<t_block>& L_blocks,
const std::string& io_port_name_postfix, const std::string& io_input_port_name_postfix,
const std::string& io_output_port_name_postfix,
const size_t& unused_io_value) { const size_t& unused_io_value) {
/* Validate the file stream */ /* Validate the file stream */
check_file_handler(fp); check_file_handler(fp);
@ -140,14 +141,21 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
VTR_ASSERT(io_index < module_mapped_io_port.get_width()); VTR_ASSERT(io_index < module_mapped_io_port.get_width());
module_mapped_io_port.set_width(io_index, io_index); module_mapped_io_port.set_width(io_index, io_index);
/* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1 */ /* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always has a size of 1
BasicPort benchmark_io_port(std::string(std::string(io_lb.name)+ io_port_name_postfix), 1); * In addition, the input and output ports may have different postfix in naming
* due to verification context! Here, we give full customization on naming
print_verilog_comment(fp, std::string("----- Blif Benchmark inout " + std::string(io_lb.name) + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----")); */
BasicPort benchmark_io_port;
if (VPACK_INPAD == io_lb.type) { if (VPACK_INPAD == io_lb.type) {
benchmark_io_port.set_name(std::string(std::string(io_lb.name) + io_input_port_name_postfix));
benchmark_io_port.set_width(1);
print_verilog_comment(fp, std::string("----- Blif Benchmark input " + std::string(io_lb.name) + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----"));
print_verilog_wire_connection(fp, module_mapped_io_port, benchmark_io_port, false); print_verilog_wire_connection(fp, module_mapped_io_port, benchmark_io_port, false);
} else { } else {
VTR_ASSERT(VPACK_OUTPAD == io_lb.type); VTR_ASSERT(VPACK_OUTPAD == io_lb.type);
benchmark_io_port.set_name(std::string(std::string(io_lb.name) + io_output_port_name_postfix));
benchmark_io_port.set_width(1);
print_verilog_comment(fp, std::string("----- Blif Benchmark output " + std::string(io_lb.name) + " is mapped to FPGA IOPAD " + module_mapped_io_port.get_name() + "[" + std::to_string(io_index) + "] -----"));
print_verilog_wire_connection(fp, benchmark_io_port, module_mapped_io_port, false); print_verilog_wire_connection(fp, benchmark_io_port, module_mapped_io_port, false);
} }
@ -336,33 +344,51 @@ void print_verilog_testbench_check(std::fstream& fp,
} }
/******************************************************************** /********************************************************************
* Generate random stimulus for the input ports * Generate random stimulus for the clock port
* This function is designed to drive the clock port of a benchmark module
* If there is no clock port found, we will give a default clock name
* In such case, this clock will not be wired to the benchmark module
* but be only used as a synchronizer in verification
*******************************************************************/ *******************************************************************/
void print_verilog_testbench_random_stimuli(std::fstream& fp, void print_verilog_testbench_clock_stimuli(std::fstream& fp,
const t_spice_params& simulation_parameters, const t_spice_params& simulation_parameters,
const std::vector<t_logical_block>& L_logical_blocks, const BasicPort& clock_port) {
const std::string& check_flag_port_postfix,
const std::vector<std::string>& clock_port_names,
const std::string& default_clock_name) {
/* Validate the file stream */ /* Validate the file stream */
check_file_handler(fp); check_file_handler(fp);
print_verilog_comment(fp, std::string("----- Initialization -------")); print_verilog_comment(fp, std::string("----- Clock Initialization -------"));
fp << "\tinitial begin" << std::endl; fp << "\tinitial begin" << std::endl;
/* Create clock stimuli */ /* Create clock stimuli */
BasicPort clock_port = generate_verilog_testbench_clock_port(clock_port_names, default_clock_name);
fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << " <= 1'b0;" << std::endl; fp << "\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << " <= 1'b0;" << std::endl;
fp << "\t\twhile(1) begin" << std::endl; fp << "\t\twhile(1) begin" << std::endl;
fp << "\t\t\t#" << std::setprecision(2) << ((0.5/simulation_parameters.stimulate_params.op_clock_freq)/verilog_sim_timescale) << std::endl; fp << "\t\t\t#" << std::setprecision(10) << ((0.5/simulation_parameters.stimulate_params.op_clock_freq)/verilog_sim_timescale) << std::endl;
fp << "\t\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port); fp << "\t\t\t" << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
fp << " <= !"; fp << " <= !";
fp << generate_verilog_port(VERILOG_PORT_CONKT, clock_port); fp << generate_verilog_port(VERILOG_PORT_CONKT, clock_port);
fp << ";" << std::endl; fp << ";" << std::endl;
fp << "\t\tend" << std::endl; fp << "\t\tend" << std::endl;
fp << "\tend" << std::endl;
/* Add an empty line as splitter */ /* Add an empty line as splitter */
fp << std::endl; fp << std::endl;
}
/********************************************************************
* Generate random stimulus for the input ports (non-clock signals)
* For clock signals, please use print_verilog_testbench_clock_stimuli
*******************************************************************/
void print_verilog_testbench_random_stimuli(std::fstream& fp,
const std::vector<t_logical_block>& L_logical_blocks,
const std::string& check_flag_port_postfix,
const BasicPort& clock_port) {
/* Validate the file stream */
check_file_handler(fp);
print_verilog_comment(fp, std::string("----- Input Initialization -------"));
fp << "\tinitial begin" << std::endl;
for (const t_logical_block& lb : L_logical_blocks) { for (const t_logical_block& lb : L_logical_blocks) {
/* Bypass non-I/O logical blocks ! */ /* Bypass non-I/O logical blocks ! */

View File

@ -29,7 +29,8 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
const vtr::Point<size_t>& device_size, const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& L_grids, const std::vector<std::vector<t_grid_tile>>& L_grids,
const std::vector<t_block>& L_blocks, const std::vector<t_block>& L_blocks,
const std::string& io_port_name_postfix, const std::string& io_input_port_name_postfix,
const std::string& io_output_port_name_postfix,
const size_t& unused_io_value); const size_t& unused_io_value);
void print_verilog_timeout_and_vcd(std::fstream& fp, void print_verilog_timeout_and_vcd(std::fstream& fp,
@ -54,11 +55,13 @@ void print_verilog_testbench_check(std::fstream& fp,
const std::vector<std::string>& clock_port_names, const std::vector<std::string>& clock_port_names,
const std::string& default_clock_name); const std::string& default_clock_name);
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
const t_spice_params& simulation_parameters,
const BasicPort& clock_port);
void print_verilog_testbench_random_stimuli(std::fstream& fp, void print_verilog_testbench_random_stimuli(std::fstream& fp,
const t_spice_params& simulation_parameters,
const std::vector<t_logical_block>& L_logical_blocks, const std::vector<t_logical_block>& L_logical_blocks,
const std::string& check_flag_port_postfix, const std::string& check_flag_port_postfix,
const std::vector<std::string>& clock_port_names, const BasicPort& clock_port);
const std::string& default_clock_name);
#endif #endif

View File

@ -29,12 +29,10 @@
constexpr char* TOP_TESTBENCH_REFERENCE_INSTANCE_NAME = "REF_DUT"; constexpr char* TOP_TESTBENCH_REFERENCE_INSTANCE_NAME = "REF_DUT";
constexpr char* TOP_TESTBENCH_FPGA_INSTANCE_NAME = "FPGA_DUT"; constexpr char* TOP_TESTBENCH_FPGA_INSTANCE_NAME = "FPGA_DUT";
constexpr char* TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX = "_benchmark"; constexpr char* TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX = "_benchmark";
constexpr char* TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX = "_verification"; constexpr char* TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX = "_fpga";
constexpr char* TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX = "_flag"; constexpr char* TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX = "_flag";
constexpr char* TOP_TESTBENCH_CONFIG_CHAIN_HEAD_PORT_NAME = "cc_in";
constexpr char* TOP_TESTBENCH_CONFIG_CHAIN_TAIL_PORT_NAME = "cc_out";
constexpr char* TOP_TESTBENCH_CC_PROG_TASK_NAME = "prog_cycle_task"; constexpr char* TOP_TESTBENCH_CC_PROG_TASK_NAME = "prog_cycle_task";
constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start"; constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start";
@ -52,13 +50,13 @@ void print_verilog_top_testbench_config_chain_port(std::fstream& fp) {
/* Print the head of configuraion-chains here */ /* Print the head of configuraion-chains here */
print_verilog_comment(fp, std::string("---- Configuration-chain head -----")); print_verilog_comment(fp, std::string("---- Configuration-chain head -----"));
BasicPort config_chain_head_port(std::string(TOP_TESTBENCH_CONFIG_CHAIN_HEAD_PORT_NAME), 1); BasicPort config_chain_head_port(generate_configuration_chain_head_name(), 1);
fp << generate_verilog_port(VERILOG_PORT_REG, config_chain_head_port) << ";" << std::endl; fp << generate_verilog_port(VERILOG_PORT_REG, config_chain_head_port) << ";" << std::endl;
/* Print the tail of configuration-chains here */ /* Print the tail of configuration-chains here */
print_verilog_comment(fp, std::string("---- Configuration-chain tail -----")); print_verilog_comment(fp, std::string("---- Configuration-chain tail -----"));
BasicPort config_chain_tail_port(std::string(TOP_TESTBENCH_CONFIG_CHAIN_TAIL_PORT_NAME), 1); BasicPort config_chain_tail_port(generate_configuration_chain_tail_name(), 1);
fp << generate_verilog_port(VERILOG_PORT_REG, config_chain_tail_port) << ";" << std::endl; fp << generate_verilog_port(VERILOG_PORT_WIRE, config_chain_tail_port) << ";" << std::endl;
} }
/******************************************************************** /********************************************************************
@ -411,8 +409,8 @@ void print_verilog_top_testbench_load_bitstream_task_configuration_chain(std::fs
check_file_handler(fp); check_file_handler(fp);
BasicPort prog_clock_port(std::string(top_tb_prog_clock_port_name), 1); BasicPort prog_clock_port(std::string(top_tb_prog_clock_port_name), 1);
BasicPort cc_head_port(std::string(TOP_TESTBENCH_CONFIG_CHAIN_HEAD_PORT_NAME), 1); BasicPort cc_head_port(generate_configuration_chain_head_name(), 1);
BasicPort cc_head_value(std::string(TOP_TESTBENCH_CONFIG_CHAIN_HEAD_PORT_NAME) + std::string("_val"), 1); BasicPort cc_head_value(generate_configuration_chain_head_name() + std::string("_val"), 1);
/* Add an empty line as splitter */ /* Add an empty line as splitter */
fp << std::endl; fp << std::endl;
@ -425,8 +423,12 @@ void print_verilog_top_testbench_load_bitstream_task_configuration_chain(std::fs
fp << generate_verilog_port(VERILOG_PORT_INPUT, cc_head_value) << ";" << std::endl; fp << generate_verilog_port(VERILOG_PORT_INPUT, cc_head_value) << ";" << std::endl;
fp << "\tbegin" << std::endl; fp << "\tbegin" << std::endl;
fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl; fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl;
fp << "\t\t"; fp << "\t\t\t";
print_verilog_wire_connection(fp, cc_head_port, cc_head_value, false); fp << generate_verilog_port(VERILOG_PORT_CONKT, cc_head_port);
fp << " = ";
fp << generate_verilog_port(VERILOG_PORT_CONKT, cc_head_value);
fp << ";" << std::endl;
fp << "\tend" << std::endl; fp << "\tend" << std::endl;
fp << "endtask" << std::endl; fp << "endtask" << std::endl;
@ -499,7 +501,7 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp,
print_verilog_comment(fp, "----- Begin configuration done signal generation -----"); print_verilog_comment(fp, "----- Begin configuration done signal generation -----");
print_verilog_pulse_stimuli(fp, config_done_port, print_verilog_pulse_stimuli(fp, config_done_port,
0, /* Initial value */ 0, /* Initial value */
num_config_clock_cycles * prog_clock_period / timescale, 1); num_config_clock_cycles * prog_clock_period / timescale, 0);
print_verilog_comment(fp, "----- End configuration done signal generation -----"); print_verilog_comment(fp, "----- End configuration done signal generation -----");
fp << std::endl; fp << std::endl;
@ -616,7 +618,7 @@ void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp,
* We do not care the value of scan_chain head during the first programming cycle * We do not care the value of scan_chain head during the first programming cycle
* It is reset anyway * It is reset anyway
*/ */
BasicPort config_chain_head_port(std::string(TOP_TESTBENCH_CONFIG_CHAIN_HEAD_PORT_NAME), 1); BasicPort config_chain_head_port(generate_configuration_chain_head_name(), 1);
std::vector<size_t> initial_values(config_chain_head_port.get_width(), 0); std::vector<size_t> initial_values(config_chain_head_port.get_width(), 0);
print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----");
@ -636,6 +638,19 @@ void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp,
fp << "\t\t" << std::string(TOP_TESTBENCH_CC_PROG_TASK_NAME); fp << "\t\t" << std::string(TOP_TESTBENCH_CC_PROG_TASK_NAME);
fp << "(1'b" << (size_t)bitstream_manager.bit_value(bit_id) << ");" << std::endl; fp << "(1'b" << (size_t)bitstream_manager.bit_value(bit_id) << ");" << std::endl;
} }
/* Raise the flag of configuration done when bitstream loading is complete */
BasicPort prog_clock_port(std::string(top_tb_prog_clock_port_name), 1);
fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl;
BasicPort config_done_port(std::string(top_tb_config_done_port_name), 1);
fp << "\t\t\t";
fp << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port);
fp << " <= ";
std::vector<size_t> config_done_enable_values(config_done_port.get_width(), 1);
fp << generate_verilog_constant_values(config_done_enable_values);
fp << ";" << std::endl;
fp << "\tend" << std::endl; fp << "\tend" << std::endl;
print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----");
} }
@ -767,6 +782,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module, print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module,
L_logical_blocks, device_size, L_grids, L_logical_blocks, device_size, L_grids,
L_blocks, L_blocks,
std::string(),
std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX),
(size_t)verilog_default_signal_init_value); (size_t)verilog_default_signal_init_value);
@ -786,9 +802,9 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
std::vector<std::string> clock_port_names = find_benchmark_clock_port_name(L_logical_blocks); std::vector<std::string> clock_port_names = find_benchmark_clock_port_name(L_logical_blocks);
/* Add stimuli for reset, set, clock and iopad signals */ /* Add stimuli for reset, set, clock and iopad signals */
print_verilog_testbench_random_stimuli(fp, simulation_parameters, L_logical_blocks, print_verilog_testbench_random_stimuli(fp, L_logical_blocks,
std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX), std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX),
clock_port_names, std::string(top_tb_op_clock_port_name)); BasicPort(std::string(top_tb_op_clock_port_name), 1));
/* Add output autocheck */ /* Add output autocheck */
print_verilog_testbench_check(fp, print_verilog_testbench_check(fp,

View File

@ -1234,13 +1234,17 @@ void print_verilog_pulse_stimuli(std::fstream& fp,
fp << "\tbegin" << std::endl; fp << "\tbegin" << std::endl;
fp << "\t"; fp << "\t";
std::vector<size_t> initial_values(port.get_width(), initial_value); std::vector<size_t> initial_values(port.get_width(), initial_value);
print_verilog_wire_constant_values(fp, port, initial_values); fp << "\t";
fp << generate_verilog_port_constant_values(port, initial_values);
fp << ";" << std::endl;
/* if flip_value is the same as initial value, we do not need to flip the signal ! */ /* if flip_value is the same as initial value, we do not need to flip the signal ! */
if (flip_value != initial_value) { if (flip_value != initial_value) {
fp << "\t" << "#" << std::setprecision(2) << pulse_width; fp << "\t" << "#" << std::setprecision(10) << pulse_width;
std::vector<size_t> port_flip_values(port.get_width(), flip_value); std::vector<size_t> port_flip_values(port.get_width(), flip_value);
print_verilog_wire_constant_values(fp, port, port_flip_values); fp << "\t";
fp << generate_verilog_port_constant_values(port, port_flip_values);
fp << ";" << std::endl;
} }
fp << "\tend" << std::endl; fp << "\tend" << std::endl;
@ -1274,7 +1278,9 @@ void print_verilog_pulse_stimuli(std::fstream& fp,
fp << "\tbegin" << std::endl; fp << "\tbegin" << std::endl;
fp << "\t"; fp << "\t";
std::vector<size_t> initial_values(port.get_width(), initial_value); std::vector<size_t> initial_values(port.get_width(), initial_value);
print_verilog_wire_constant_values(fp, port, initial_values); fp << "\t";
fp << generate_verilog_port_constant_values(port, initial_values);
fp << ";" << std::endl;
/* Set a wait condition if specified */ /* Set a wait condition if specified */
if (false == wait_condition.empty()) { if (false == wait_condition.empty()) {
@ -1284,9 +1290,11 @@ void print_verilog_pulse_stimuli(std::fstream& fp,
/* Number of flip conditions and values should match */ /* Number of flip conditions and values should match */
VTR_ASSERT(flip_values.size() == pulse_widths.size()); VTR_ASSERT(flip_values.size() == pulse_widths.size());
for (size_t ipulse = 0; ipulse < pulse_widths.size(); ++ipulse) { for (size_t ipulse = 0; ipulse < pulse_widths.size(); ++ipulse) {
fp << "\t" << "#" << std::setprecision(2) << pulse_widths[ipulse]; fp << "\t" << "#" << std::setprecision(10) << pulse_widths[ipulse];
std::vector<size_t> port_flip_value(port.get_width(), flip_values[ipulse]); std::vector<size_t> port_flip_value(port.get_width(), flip_values[ipulse]);
print_verilog_wire_constant_values(fp, port, port_flip_value); fp << "\t";
fp << generate_verilog_port_constant_values(port, port_flip_value);
fp << ";" << std::endl;
} }
fp << "\tend" << std::endl; fp << "\tend" << std::endl;
@ -1318,9 +1326,12 @@ void print_verilog_clock_stimuli(std::fstream& fp,
/* Config_done signal: indicate when configuration is finished */ /* Config_done signal: indicate when configuration is finished */
fp << "initial" << std::endl; fp << "initial" << std::endl;
fp << "\tbegin" << std::endl; fp << "\tbegin" << std::endl;
fp << "\t";
std::vector<size_t> initial_values(port.get_width(), initial_value); std::vector<size_t> initial_values(port.get_width(), initial_value);
print_verilog_wire_constant_values(fp, port, initial_values); fp << "\t\t";
fp << generate_verilog_port_constant_values(port, initial_values);
fp << ";" << std::endl;
fp << "\tend" << std::endl; fp << "\tend" << std::endl;
fp << "always"; fp << "always";
@ -1332,8 +1343,15 @@ void print_verilog_clock_stimuli(std::fstream& fp,
} }
fp << "\tbegin" << std::endl; fp << "\tbegin" << std::endl;
fp << "\t\t" << "#" << std::setprecision(2) << pulse_width; fp << "\t\t" << "#" << std::setprecision(10) << pulse_width;
print_verilog_wire_connection(fp, port, port, true);
fp << "\t";
fp << generate_verilog_port(VERILOG_PORT_CONKT, port);
fp << " = ";
fp << "~";
fp << generate_verilog_port(VERILOG_PORT_CONKT, port);
fp << ";" << std::endl;
fp << "\tend" << std::endl; fp << "\tend" << std::endl;
/* Print an empty line as splitter */ /* Print an empty line as splitter */