[Tool] Apply a dirty fix to Verilog testbench generator so that multi-clock testbench can be generated

This commit is contained in:
tangxifan 2021-01-13 15:13:19 -07:00
parent 91f12071d5
commit 9cc9e45b4b
4 changed files with 65 additions and 54 deletions

View File

@ -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!
* 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 -------"));
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 */
fp << std::endl;
@ -227,16 +229,16 @@ void print_verilog_random_top_testbench(const std::string& circuit_name,
explicit_port_mapping);
/* 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 */
print_verilog_testbench_clock_stimuli(fp, simulation_parameters,
clock_port);
clock_ports);
print_verilog_testbench_random_stimuli(fp, atom_ctx,
netlist_annotation,
clock_port_names,
std::string(CHECKFLAG_PORT_POSTFIX),
clock_port);
clock_ports);
print_verilog_testbench_check(fp,
std::string(AUTOCHECKED_SIMULATION_FLAG),

View File

@ -347,14 +347,18 @@ void print_verilog_timeout_and_vcd(std::fstream& fp,
* Restrictions:
* 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) {
std::vector<BasicPort> clock_ports;
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 BasicPort(clock_port_names[0], 1);
return clock_ports;
}
/********************************************************************
@ -382,7 +386,7 @@ void print_verilog_testbench_check(std::fstream& fp,
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 -------"));
@ -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 << 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\t";
print_verilog_register_connection(fp, sim_start_port, sim_start_port, true);
@ -466,11 +477,12 @@ void print_verilog_testbench_check(std::fstream& fp,
*******************************************************************/
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
const SimulationSetting& simulation_parameters,
const BasicPort& clock_port) {
const std::vector<BasicPort>& clock_ports) {
/* Validate the file stream */
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;
/* Create clock stimuli */
@ -488,6 +500,7 @@ void print_verilog_testbench_clock_stimuli(std::fstream& fp,
/* Add an empty line as splitter */
fp << std::endl;
}
}
/********************************************************************
* Generate random stimulus for the input ports (non-clock signals)
@ -498,7 +511,7 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
const std::string& check_flag_port_postfix,
const BasicPort& clock_port) {
const std::vector<BasicPort>& clock_ports) {
/* Validate the file stream */
valid_file_stream(fp);
@ -557,25 +570,14 @@ void print_verilog_testbench_random_stimuli(std::fstream& fp,
/* Add an empty line as splitter */
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 -------"));
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()) {
/* Bypass non-I/O atom blocks ! */

View File

@ -60,7 +60,7 @@ void print_verilog_timeout_and_vcd(std::fstream& fp,
const std::string& error_counter_name,
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);
void print_verilog_testbench_check(std::fstream& fp,
@ -77,14 +77,14 @@ void print_verilog_testbench_check(std::fstream& fp,
void print_verilog_testbench_clock_stimuli(std::fstream& fp,
const SimulationSetting& simulation_parameters,
const BasicPort& clock_port);
const std::vector<BasicPort>& clock_ports);
void print_verilog_testbench_random_stimuli(std::fstream& fp,
const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
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,
const AtomContext& atom_ctx,

View File

@ -288,10 +288,17 @@ 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
* 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()) {
BasicPort global_port_to_connect(module_manager.module_port(top_module, module_global_port).get_name(), pin, pin);
/* 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 */
for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) {
@ -1935,7 +1942,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
netlist_annotation,
clock_port_names,
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 */
print_verilog_testbench_check(fp,