[Tool] Apply a dirty fix to Verilog testbench generator so that multi-clock testbench can be generated
This commit is contained in:
parent
91f12071d5
commit
9cc9e45b4b
|
@ -65,9 +65,11 @@ void print_verilog_top_random_testbench_ports(std::fstream& fp,
|
||||||
/* Create a clock port if the benchmark does not have one!
|
/* Create a clock port if the benchmark does not have one!
|
||||||
* The clock is used for counting and synchronizing input stimulus
|
* The clock is used for counting and synchronizing input stimulus
|
||||||
*/
|
*/
|
||||||
BasicPort clock_port = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
|
std::vector<BasicPort> clock_ports = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
|
||||||
print_verilog_comment(fp, std::string("----- Default clock port is added here since benchmark does not contain one -------"));
|
print_verilog_comment(fp, std::string("----- Default clock port is added here since benchmark does not contain one -------"));
|
||||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, clock_port) << ";" << std::endl;
|
for (const BasicPort& clock_port : clock_ports) {
|
||||||
|
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, clock_port) << ";" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add an empty line as splitter */
|
/* Add an empty line as splitter */
|
||||||
fp << std::endl;
|
fp << std::endl;
|
||||||
|
@ -227,16 +229,16 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
|
||||||
explicit_port_mapping);
|
explicit_port_mapping);
|
||||||
|
|
||||||
/* Find clock port to be used */
|
/* Find clock port to be used */
|
||||||
BasicPort clock_port = generate_verilog_testbench_clock_port(clock_port_names, std::string(DEFAULT_CLOCK_NAME));
|
std::vector<BasicPort> clock_ports = 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_clock_stimuli(fp, simulation_parameters,
|
print_verilog_testbench_clock_stimuli(fp, simulation_parameters,
|
||||||
clock_port);
|
clock_ports);
|
||||||
print_verilog_testbench_random_stimuli(fp, atom_ctx,
|
print_verilog_testbench_random_stimuli(fp, atom_ctx,
|
||||||
netlist_annotation,
|
netlist_annotation,
|
||||||
clock_port_names,
|
clock_port_names,
|
||||||
std::string(CHECKFLAG_PORT_POSTFIX),
|
std::string(CHECKFLAG_PORT_POSTFIX),
|
||||||
clock_port);
|
clock_ports);
|
||||||
|
|
||||||
print_verilog_testbench_check(fp,
|
print_verilog_testbench_check(fp,
|
||||||
std::string(AUTOCHECKED_SIMULATION_FLAG),
|
std::string(AUTOCHECKED_SIMULATION_FLAG),
|
||||||
|
|
|
@ -347,14 +347,18 @@ void print_verilog_timeout_and_vcd(std::fstream& fp,
|
||||||
* Restrictions:
|
* Restrictions:
|
||||||
* Assume this is a single clock benchmark
|
* Assume this is a single clock benchmark
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
BasicPort generate_verilog_testbench_clock_port(const std::vector<std::string>& clock_port_names,
|
std::vector<BasicPort> generate_verilog_testbench_clock_port(const std::vector<std::string>& clock_port_names,
|
||||||
const std::string& default_clock_name) {
|
const std::string& default_clock_name) {
|
||||||
|
std::vector<BasicPort> clock_ports;
|
||||||
if (0 == clock_port_names.size()) {
|
if (0 == clock_port_names.size()) {
|
||||||
return BasicPort(default_clock_name, 1);
|
clock_ports.push_back(BasicPort(default_clock_name, 1));
|
||||||
|
} else {
|
||||||
|
for (const std::string& clock_port_name : clock_port_names) {
|
||||||
|
clock_ports.push_back(BasicPort(clock_port_name, 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VTR_ASSERT(1 == clock_port_names.size());
|
return clock_ports;
|
||||||
return BasicPort(clock_port_names[0], 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
|
@ -382,7 +386,7 @@ void print_verilog_testbench_check(std::fstream& fp,
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Begin checking output vectors -------"));
|
print_verilog_comment(fp, std::string("----- Begin checking output vectors -------"));
|
||||||
|
|
||||||
BasicPort clock_port = generate_verilog_testbench_clock_port(clock_port_names, default_clock_name);
|
std::vector<BasicPort> clock_ports = generate_verilog_testbench_clock_port(clock_port_names, default_clock_name);
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Skip the first falling edge of clock, it is for initialization -------"));
|
print_verilog_comment(fp, std::string("----- Skip the first falling edge of clock, it is for initialization -------"));
|
||||||
|
|
||||||
|
@ -391,7 +395,14 @@ void print_verilog_testbench_check(std::fstream& fp,
|
||||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, sim_start_port) << ";" << std::endl;
|
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, sim_start_port) << ";" << std::endl;
|
||||||
fp << std::endl;
|
fp << std::endl;
|
||||||
|
|
||||||
fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ") begin" << std::endl;
|
/* TODO: This is limitation when multiple clock signals exist
|
||||||
|
* Ideally, all the input signals are generated by different clock edges,
|
||||||
|
* depending which clock domain the signals belong to
|
||||||
|
* Currently, as we lack the information, we only use the first clock signal
|
||||||
|
*/
|
||||||
|
VTR_ASSERT(1 <= clock_ports.size());
|
||||||
|
|
||||||
|
fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_ports[0]) << ") begin" << std::endl;
|
||||||
fp << "\t\tif (1'b1 == " << generate_verilog_port(VERILOG_PORT_CONKT, sim_start_port) << ") begin" << std::endl;
|
fp << "\t\tif (1'b1 == " << generate_verilog_port(VERILOG_PORT_CONKT, sim_start_port) << ") begin" << std::endl;
|
||||||
fp << "\t\t";
|
fp << "\t\t";
|
||||||
print_verilog_register_connection(fp, sim_start_port, sim_start_port, true);
|
print_verilog_register_connection(fp, sim_start_port, sim_start_port, true);
|
||||||
|
@ -466,27 +477,29 @@ void print_verilog_testbench_check(std::fstream& fp,
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
|
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
|
||||||
const SimulationSetting& simulation_parameters,
|
const SimulationSetting& simulation_parameters,
|
||||||
const BasicPort& clock_port) {
|
const std::vector<BasicPort>& clock_ports) {
|
||||||
/* Validate the file stream */
|
/* Validate the file stream */
|
||||||
valid_file_stream(fp);
|
valid_file_stream(fp);
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Clock Initialization -------"));
|
for (const BasicPort& clock_port : clock_ports) {
|
||||||
|
print_verilog_comment(fp, std::string("----- Clock '") + clock_port.get_name() + std::string("' Initialization -------"));
|
||||||
|
|
||||||
fp << "\tinitial begin" << std::endl;
|
fp << "\tinitial begin" << std::endl;
|
||||||
/* Create clock stimuli */
|
/* Create clock stimuli */
|
||||||
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(10) << ((0.5/simulation_parameters.operating_clock_frequency())/VERILOG_SIM_TIMESCALE) << std::endl;
|
fp << "\t\t\t#" << std::setprecision(10) << ((0.5/simulation_parameters.operating_clock_frequency())/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;
|
fp << "\tend" << std::endl;
|
||||||
|
|
||||||
/* Add an empty line as splitter */
|
/* Add an empty line as splitter */
|
||||||
fp << std::endl;
|
fp << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
|
@ -498,7 +511,7 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
|
||||||
const VprNetlistAnnotation& netlist_annotation,
|
const VprNetlistAnnotation& netlist_annotation,
|
||||||
const std::vector<std::string>& clock_port_names,
|
const std::vector<std::string>& clock_port_names,
|
||||||
const std::string& check_flag_port_postfix,
|
const std::string& check_flag_port_postfix,
|
||||||
const BasicPort& clock_port) {
|
const std::vector<BasicPort>& clock_ports) {
|
||||||
/* Validate the file stream */
|
/* Validate the file stream */
|
||||||
valid_file_stream(fp);
|
valid_file_stream(fp);
|
||||||
|
|
||||||
|
@ -557,25 +570,14 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
|
||||||
/* Add an empty line as splitter */
|
/* Add an empty line as splitter */
|
||||||
fp << std::endl;
|
fp << std::endl;
|
||||||
|
|
||||||
// Not ready yet to determine if input is reset
|
|
||||||
/*
|
|
||||||
fprintf(fp, "//----- Reset Stimulis\n");
|
|
||||||
fprintf(fp, " initial begin\n");
|
|
||||||
fprintf(fp, " #%.3f\n",(rand() % 10) + 0.001);
|
|
||||||
fprintf(fp, " %s <= !%s;\n", reset_input_name, reset_input_name);
|
|
||||||
fprintf(fp, " #%.3f\n",(rand() % 10) + 0.001);
|
|
||||||
fprintf(fp, " %s <= !%s;\n", reset_input_name, reset_input_name);
|
|
||||||
fprintf(fp, " while(1) begin\n");
|
|
||||||
fprintf(fp, " #%.3f\n", (rand() % 15) + 0.5);
|
|
||||||
fprintf(fp, " %s <= !%s;\n", reset_input_name, reset_input_name);
|
|
||||||
fprintf(fp, " #%.3f\n", (rand() % 10000) + 200);
|
|
||||||
fprintf(fp, " %s <= !%s;\n", reset_input_name, reset_input_name);
|
|
||||||
fprintf(fp, " end\n");
|
|
||||||
fprintf(fp, " end\n\n");
|
|
||||||
*/
|
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Input Stimulus -------"));
|
print_verilog_comment(fp, std::string("----- Input Stimulus -------"));
|
||||||
fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_port) << ") begin" << std::endl;
|
/* TODO: This is limitation when multiple clock signals exist
|
||||||
|
* Ideally, all the input signals are generated by different clock edges,
|
||||||
|
* depending which clock domain the signals belong to
|
||||||
|
* Currently, as we lack the information, we only use the first clock signal
|
||||||
|
*/
|
||||||
|
VTR_ASSERT(1 <= clock_ports.size());
|
||||||
|
fp << "\talways@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, clock_ports[0]) << ") begin" << std::endl;
|
||||||
|
|
||||||
for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) {
|
for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) {
|
||||||
/* Bypass non-I/O atom blocks ! */
|
/* Bypass non-I/O atom blocks ! */
|
||||||
|
|
|
@ -60,8 +60,8 @@ void print_verilog_timeout_and_vcd(std::fstream& fp,
|
||||||
const std::string& error_counter_name,
|
const std::string& error_counter_name,
|
||||||
const float& simulation_time);
|
const float& simulation_time);
|
||||||
|
|
||||||
BasicPort generate_verilog_testbench_clock_port(const std::vector<std::string>& clock_port_names,
|
std::vector<BasicPort> generate_verilog_testbench_clock_port(const std::vector<std::string>& clock_port_names,
|
||||||
const std::string& default_clock_name);
|
const std::string& default_clock_name);
|
||||||
|
|
||||||
void print_verilog_testbench_check(std::fstream& fp,
|
void print_verilog_testbench_check(std::fstream& fp,
|
||||||
const std::string& autochecked_preprocessing_flag,
|
const std::string& autochecked_preprocessing_flag,
|
||||||
|
@ -77,14 +77,14 @@ void print_verilog_testbench_check(std::fstream& fp,
|
||||||
|
|
||||||
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
|
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
|
||||||
const SimulationSetting& simulation_parameters,
|
const SimulationSetting& simulation_parameters,
|
||||||
const BasicPort& clock_port);
|
const std::vector<BasicPort>& clock_ports);
|
||||||
|
|
||||||
void print_verilog_testbench_random_stimuli(std::fstream& fp,
|
void print_verilog_testbench_random_stimuli(std::fstream& fp,
|
||||||
const AtomContext& atom_ctx,
|
const AtomContext& atom_ctx,
|
||||||
const VprNetlistAnnotation& netlist_annotation,
|
const VprNetlistAnnotation& netlist_annotation,
|
||||||
const std::vector<std::string>& clock_port_names,
|
const std::vector<std::string>& clock_port_names,
|
||||||
const std::string& check_flag_port_postfix,
|
const std::string& check_flag_port_postfix,
|
||||||
const BasicPort& clock_port);
|
const std::vector<BasicPort>& clock_ports);
|
||||||
|
|
||||||
void print_verilog_testbench_shared_ports(std::fstream& fp,
|
void print_verilog_testbench_shared_ports(std::fstream& fp,
|
||||||
const AtomContext& atom_ctx,
|
const AtomContext& atom_ctx,
|
||||||
|
|
|
@ -288,9 +288,16 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp,
|
||||||
* The wiring will be inverted if the default value of the global port is 1
|
* The wiring will be inverted if the default value of the global port is 1
|
||||||
* Otherwise, the wiring will not be inverted!
|
* Otherwise, the wiring will not be inverted!
|
||||||
*/
|
*/
|
||||||
print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port),
|
for (const size_t& pin : module_manager.module_port(top_module, module_global_port).pins()) {
|
||||||
stimuli_clock_port,
|
BasicPort global_port_to_connect(module_manager.module_port(top_module, module_global_port).get_name(), pin, pin);
|
||||||
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
|
/* TODO: This is a temporary fix to make the testbench generator run in multi-clock scenario
|
||||||
|
* Need to consider multiple clock sources to connect
|
||||||
|
* each of which may operate in different ferquency!!!
|
||||||
|
*/
|
||||||
|
print_verilog_wire_connection(fp, global_port_to_connect,
|
||||||
|
stimuli_clock_port,
|
||||||
|
1 == fabric_global_port_info.global_port_default_value(fabric_global_port));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect global configuration done ports to configuration done signal */
|
/* Connect global configuration done ports to configuration done signal */
|
||||||
|
@ -1935,7 +1942,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
|
||||||
netlist_annotation,
|
netlist_annotation,
|
||||||
clock_port_names,
|
clock_port_names,
|
||||||
std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX),
|
std::string(TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX),
|
||||||
BasicPort(std::string(TOP_TB_OP_CLOCK_PORT_NAME), 1));
|
std::vector<BasicPort>(1, 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,
|
||||||
|
|
Loading…
Reference in New Issue