Add an autochecked configuration free testbench

This commit is contained in:
AurelienUoU 2018-12-11 14:44:13 -07:00
parent 79f3db9880
commit f5ea3ff233
7 changed files with 589 additions and 27 deletions

View File

@ -116,16 +116,22 @@ void vpr_dump_syn_verilog(t_vpr_setup vpr_setup,
char* top_netlist_path = NULL; char* top_netlist_path = NULL;
char* bitstream_file_name = NULL; char* bitstream_file_name = NULL;
char* bitstream_file_path = NULL; char* bitstream_file_path = NULL;
char* hex_file_name = NULL;
char* hex_file_path = NULL;
char* top_testbench_file_name = NULL; char* top_testbench_file_name = NULL;
char* top_auto_testbench_file_name = NULL; char* top_auto_testbench_file_name = NULL;
char* top_auto_preconf_testbench_file_name = NULL;
char* top_testbench_file_path = NULL; char* top_testbench_file_path = NULL;
char* top_auto_testbench_file_path = NULL; char* top_auto_testbench_file_path = NULL;
char* top_auto_preconf_testbench_file_path = NULL;
char* blif_testbench_file_name = NULL; char* blif_testbench_file_name = NULL;
char* blif_testbench_file_path = NULL; char* blif_testbench_file_path = NULL;
char* chomped_parent_dir = NULL; char* chomped_parent_dir = NULL;
char* chomped_circuit_name = NULL; char* chomped_circuit_name = NULL;
boolean tb_preconf = TRUE;
/* Check if the routing architecture we support*/ /* Check if the routing architecture we support*/
if (UNI_DIRECTIONAL != vpr_setup.RoutingArch.directionality) { if (UNI_DIRECTIONAL != vpr_setup.RoutingArch.directionality) {
vpr_printf(TIO_MESSAGE_ERROR, "FPGA synthesizable Verilog dumping only support uni-directional routing architecture!\n"); vpr_printf(TIO_MESSAGE_ERROR, "FPGA synthesizable Verilog dumping only support uni-directional routing architecture!\n");
@ -167,10 +173,14 @@ void vpr_dump_syn_verilog(t_vpr_setup vpr_setup,
top_netlist_path = my_strcat(verilog_dir_formatted, top_netlist_file); top_netlist_path = my_strcat(verilog_dir_formatted, top_netlist_file);
bitstream_file_name = my_strcat(chomped_circuit_name, bitstream_verilog_file_postfix); bitstream_file_name = my_strcat(chomped_circuit_name, bitstream_verilog_file_postfix);
bitstream_file_path = my_strcat(verilog_dir_formatted, bitstream_file_name); bitstream_file_path = my_strcat(verilog_dir_formatted, bitstream_file_name);
hex_file_name = my_strcat(chomped_circuit_name, hex_verilog_file_postfix);
hex_file_path = my_strcat(verilog_dir_formatted, hex_file_name);
top_testbench_file_name = my_strcat(chomped_circuit_name, top_testbench_verilog_file_postfix); top_testbench_file_name = my_strcat(chomped_circuit_name, top_testbench_verilog_file_postfix);
top_testbench_file_path = my_strcat(verilog_dir_formatted, top_testbench_file_name); top_testbench_file_path = my_strcat(verilog_dir_formatted, top_testbench_file_name);
top_auto_testbench_file_name = my_strcat(chomped_circuit_name, top_auto_testbench_verilog_file_postfix); top_auto_testbench_file_name = my_strcat(chomped_circuit_name, top_auto_testbench_verilog_file_postfix);
top_auto_testbench_file_path = my_strcat(verilog_dir_formatted, top_auto_testbench_file_name); top_auto_testbench_file_path = my_strcat(verilog_dir_formatted, top_auto_testbench_file_name);
top_auto_preconf_testbench_file_name = my_strcat(chomped_circuit_name, top_auto_preconf_testbench_verilog_file_postfix);
top_auto_preconf_testbench_file_path = my_strcat(verilog_dir_formatted, top_auto_preconf_testbench_file_name);
blif_testbench_file_name = my_strcat(chomped_circuit_name, blif_testbench_verilog_file_postfix); blif_testbench_file_name = my_strcat(chomped_circuit_name, blif_testbench_verilog_file_postfix);
blif_testbench_file_path = my_strcat(verilog_dir_formatted, blif_testbench_file_name); blif_testbench_file_path = my_strcat(verilog_dir_formatted, blif_testbench_file_name);
@ -250,9 +260,22 @@ void vpr_dump_syn_verilog(t_vpr_setup vpr_setup,
dump_verilog_top_testbench(chomped_circuit_name, top_testbench_file_path, num_clocks, dump_verilog_top_testbench(chomped_circuit_name, top_testbench_file_path, num_clocks,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice)); vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice));
} }
if ( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb) { // AA: to generate autocheck testbench but only one bitstream // AA: to generate autocheck testbench but only one bitstream
if ( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb) {
dump_verilog_top_auto_testbench(chomped_circuit_name, top_auto_testbench_file_path, num_clocks, dump_verilog_top_auto_testbench(chomped_circuit_name, top_auto_testbench_file_path, num_clocks,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice)); vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice),
modelsim_auto_testbench_module_postfix);
}
// AA: to generate autocheck preconfigured testbench
if (( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb) && (tb_preconf)) {
dump_verilog_top_auto_preconf_testbench(chomped_circuit_name,
top_auto_preconf_testbench_file_path,
num_clocks,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts,
*(Arch.spice),
modelsim_auto_preconf_testbench_module_postfix,
hex_file_path);
dump_fpga_spice_hex(hex_file_path, chomped_circuit_name, sram_verilog_orgz_info);
} }
/* Dump bitstream file */ /* Dump bitstream file */
dump_fpga_spice_bitstream(bitstream_file_path, chomped_circuit_name, sram_verilog_orgz_info); dump_fpga_spice_bitstream(bitstream_file_path, chomped_circuit_name, sram_verilog_orgz_info);
@ -267,7 +290,8 @@ void vpr_dump_syn_verilog(t_vpr_setup vpr_setup,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.include_timing, vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.include_timing,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.init_sim, vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.init_sim,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_tb, vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_tb,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb); vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb,
tb_preconf);
} }
/* dump verilog testbench only for input blif */ /* dump verilog testbench only for input blif */

View File

@ -402,7 +402,8 @@ int dump_verilog_top_testbench_find_num_config_clock_cycles(t_llist* head) {
static static
void dump_verilog_top_auto_testbench_ports(FILE* fp, void dump_verilog_top_auto_testbench_ports(FILE* fp,
char* circuit_name, char* circuit_name,
t_syn_verilog_opts syn_verilog_opts){ t_syn_verilog_opts syn_verilog_opts,
char* postfix){
int num_array_bl, num_array_wl; int num_array_bl, num_array_wl;
int bl_decoder_size, wl_decoder_size; int bl_decoder_size, wl_decoder_size;
int iblock, iopad_idx; int iblock, iopad_idx;
@ -411,7 +412,7 @@ void dump_verilog_top_auto_testbench_ports(FILE* fp,
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &mem_model); get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &mem_model);
fprintf(fp, "`include \"%s\"\n", syn_verilog_opts.verilog_benchmark_file); fprintf(fp, "`include \"%s\"\n", syn_verilog_opts.verilog_benchmark_file);
fprintf(fp, "module %s_top_auto_tb;\n", circuit_name); fprintf(fp, "module %s;\n", my_strcat(circuit_name, postfix));
/* Local wires */ /* Local wires */
/* 1. reset, set, clock signals */ /* 1. reset, set, clock signals */
/* 2. iopad signals */ /* 2. iopad signals */
@ -567,16 +568,11 @@ void dump_verilog_top_auto_testbench_call_benchmark(FILE* fp, char* blif_circuit
if(iblock>0){ if(iblock>0){
fprintf(fp, ",\n"); fprintf(fp, ",\n");
} }
if(VPACK_INPAD == logical_block[iblock].type){ if(TRUE == logical_block[iblock].is_clock){
/* See if this is a clock net */
if (TRUE == vpack_net[logical_block[iblock].output_nets[0][0]].is_global) {
fprintf(fp, " %s", top_tb_op_clock_port_name); fprintf(fp, " %s", top_tb_op_clock_port_name);
} } else if(VPACK_INPAD == logical_block[iblock].type){
else{
fprintf(fp, " %s_%s_%d_", logical_block[iblock].name, gio_inout_prefix, iopad_idx); fprintf(fp, " %s_%s_%d_", logical_block[iblock].name, gio_inout_prefix, iopad_idx);
} } else if(VPACK_OUTPAD == logical_block[iblock].type){
}
else if(VPACK_OUTPAD == logical_block[iblock].type){
fprintf(fp, " %s_benchmark", logical_block[iblock].name); fprintf(fp, " %s_benchmark", logical_block[iblock].name);
} }
} }
@ -624,7 +620,8 @@ void dump_verilog_top_auto_testbench(char* circuit_name,
char* top_netlist_name, char* top_netlist_name,
int num_clock, int num_clock,
t_syn_verilog_opts syn_verilog_opts, t_syn_verilog_opts syn_verilog_opts,
t_spice verilog) { t_spice verilog,
char* postfix) {
FILE* fp = NULL; FILE* fp = NULL;
char* title = my_strcat("FPGA Verilog Testbench for Top-level netlist of Design: ", circuit_name); char* title = my_strcat("FPGA Verilog Testbench for Top-level netlist of Design: ", circuit_name);
@ -635,14 +632,13 @@ void dump_verilog_top_auto_testbench(char* circuit_name,
exit(1); exit(1);
} }
vpr_printf(TIO_MESSAGE_INFO, "Writing Testbench for FPGA Top-level Verilog netlist for %s...\n", circuit_name); vpr_printf(TIO_MESSAGE_INFO, "Writing Autochecked Testbench for FPGA Top-level Verilog netlist for %s...\n", circuit_name);
/* Print the title */ /* Print the title */
dump_verilog_file_header(fp, title); dump_verilog_file_header(fp, title);
my_free(title); my_free(title);
/* Start of testbench */ /* Start of testbench */
dump_verilog_top_auto_testbench_ports(fp, circuit_name, syn_verilog_opts); dump_verilog_top_auto_testbench_ports(fp, circuit_name, syn_verilog_opts, postfix);
/* Call defined top-level module */ /* Call defined top-level module */
dump_verilog_top_testbench_call_top_module(fp, circuit_name); dump_verilog_top_testbench_call_top_module(fp, circuit_name);
@ -665,3 +661,302 @@ void dump_verilog_top_auto_testbench(char* circuit_name,
return; return;
} }
static
void dump_verilog_top_preconf_testbench_stimuli(FILE* fp,
int num_clock,
t_syn_verilog_opts syn_verilog_opts,
t_spice verilog,
char* hex_file_path,
t_spice spice) {
int inet, iblock, iopad_idx;
int found_mapped_inpad = 0;
t_spice_model* scff_mem_model = NULL;
/* Find Input Pad Spice model */
t_spice_net_info* cur_spice_net_info = NULL;
int iscff, num_scffs;
float prog_clock_period = (1./spice.spice_params.stimulate_params.prog_clock_freq);
float op_clock_period = (1./spice.spice_params.stimulate_params.op_clock_freq);
num_scffs = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &scff_mem_model);
fprintf(fp, " // Loading configuration as initial state\n");
fprintf(fp, "integer count;\n");
fprintf(fp, "integer file;\n");
fprintf(fp, "reg[0:%d] tmp;\n\n", (num_scffs - 1));
fprintf(fp, "initial begin\n");
fprintf(fp, " file = $fopen(\"%s\", \"r\");\n", hex_file_path);
fprintf(fp, " for(count = %d; count > -1 ; count = count - 1) begin\n", (num_scffs - 1));
fprintf(fp, " tmp[count] = $fgetc(file);\n");
fprintf(fp, " end\n");
fprintf(fp, " $signal_force(\"U0/%s_scff_in\", tmp, 0, 1, , 1);\n", scff_mem_model->prefix );
fprintf(fp, " $fclose(file);\n");
fprintf(fp, "end\n");
fprintf(fp, " // End loading configuration as initial state\n\n");
/* config_done signal: indicate when configuration is finished */
fprintf(fp, "//----- %s ----\n", top_tb_config_done_port_name);
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- CONFIG_DONE GENERATOR\n");
fprintf(fp, " %s = 1'b0;\n", top_tb_config_done_port_name);
fprintf(fp, " //----- %s signal is enabled after 50ns delay ----\n",
top_tb_config_done_port_name);
fprintf(fp, " #50 %s = 1'b1;\n", top_tb_config_done_port_name);
fprintf(fp, " end\n");
fprintf(fp, "//----- END of %s ----\n",
top_tb_config_done_port_name);
fprintf(fp, "\n");
/* Generate stimilus of programming clock */
fprintf(fp, "//----- Raw Programming clock ----\n");
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- PROG_CLOCK INITIALIZATION\n");
fprintf(fp, " %s%s = 1'b0;\n", top_tb_prog_clock_port_name, top_tb_clock_reg_postfix);
fprintf(fp, " end\n");
fprintf(fp, "//----- END of Programming clock ----\n");
fprintf(fp, "\n");
/* Programming is already done
*/
fprintf(fp, "//---- Actual programming clock is triggered only when %s and %s are disabled\n",
top_tb_config_done_port_name,
top_tb_prog_reset_port_name);
fprintf(fp, " assign %s = %s%s & (~%s) & (~%s);\n",
top_tb_prog_clock_port_name,
top_tb_prog_clock_port_name, top_tb_clock_reg_postfix,
top_tb_config_done_port_name,
top_tb_prog_reset_port_name);
/*
fprintf(fp, " assign %s = %s%s & (~%s);\n",
top_tb_prog_clock_port_name,
top_tb_prog_clock_port_name, top_tb_clock_reg_postfix,
top_tb_config_done_port_name);
*/
fprintf(fp, "//----- END of Actual Programming clock ----\n");
fprintf(fp, "\n");
/* Generate stimilus of programming clock */
fprintf(fp, "//----- Raw Operation clock ----\n");
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- OP_CLOCK INITIALIZATION\n");
fprintf(fp, " %s%s = 1'b0;\n", top_tb_op_clock_port_name, top_tb_clock_reg_postfix);
fprintf(fp, " end\n");
fprintf(fp, "always wait(~%s)\n", top_tb_reset_port_name);
fprintf(fp, " begin //--- OP_CLOCK GENERATOR\n");
fprintf(fp, " #%.2f %s%s = ~%s%s;\n",
0.5*op_clock_period / verilog_sim_timescale,
top_tb_op_clock_port_name, top_tb_clock_reg_postfix,
top_tb_op_clock_port_name, top_tb_clock_reg_postfix);
fprintf(fp, " end\n");
fprintf(fp, "//----- END of Operation clock ----\n");
/* Operation clock should be enabled after programming phase finishes.
* Before configuration is done (config_done is enabled), operation clock should be always zero.
*/
fprintf(fp, "//---- Actual operation clock is triggered only when %s is enabled \n",
top_tb_config_done_port_name);
fprintf(fp, " assign %s = %s%s & (%s);\n",
top_tb_op_clock_port_name,
top_tb_op_clock_port_name, top_tb_clock_reg_postfix,
top_tb_config_done_port_name);
fprintf(fp, "//----- END of Actual Operation clock ----\n");
fprintf(fp, "\n");
/* Reset signal for configuration circuit : only enable during the first clock cycle in programming phase */
fprintf(fp, "//----- Programming Reset Stimuli ----\n");
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- PROGRAMMING RESET GENERATOR\n");
fprintf(fp, " %s = 1'b0;\n", top_tb_prog_reset_port_name);
/* Reset is disenabled to avoid configuration reset */
fprintf(fp, "end\n");
fprintf(fp, "\n");
/* Set signal for configuration circuit : only enable during the first clock cycle in programming phase */
fprintf(fp, "//----- Programming set Stimuli ----\n");
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- PROGRAMMING SET GENERATOR\n");
fprintf(fp, "%s = 1'b0;\n", top_tb_prog_set_port_name);
fprintf(fp, "//----- Programming set signal is always disabled -----\n");
fprintf(fp, "end\n");
fprintf(fp, "\n");
/* reset signals: only enabled during the first clock cycle in operation phase */
fprintf(fp, "//----- Reset Stimuli ----\n");
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- RESET GENERATOR\n");
fprintf(fp, " %s = 1'b1;\n", top_tb_reset_port_name);
/* Reset is enabled until the first clock cycle in operation phase */
fprintf(fp, "//----- Reset signal is enabled until the first clock cycle in operation phase ----\n");
fprintf(fp, "wait(%s);\n",
top_tb_config_done_port_name);
fprintf(fp, "#%.2f %s = 1'b1;\n",
(1 * op_clock_period)/ verilog_sim_timescale,
top_tb_reset_port_name);
fprintf(fp, "#%.2f %s = 1'b0;\n",
(2 * op_clock_period) / verilog_sim_timescale,
top_tb_reset_port_name);
fprintf(fp, "end\n");
fprintf(fp, "\n");
/* set signals */
fprintf(fp, "//----- Set Stimuli ----\n");
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- SET GENERATOR\n");
fprintf(fp, "%s = 1'b0;\n", top_tb_set_port_name);
fprintf(fp, "//----- Set signal is always disabled -----\n");
fprintf(fp, "end\n");
fprintf(fp, "\n");
/* Inputs stimuli: BL/WL address lines */
//dump_verilog_top_testbench_conf_bits_serial(fp, sram_verilog_orgz_info->conf_bit_head);
/* For each input_signal
* TODO: this part is low-efficent for run-time concern... Need improve
*/
assert(NULL != iopad_verilog_model);
for (iopad_idx = 0; iopad_idx < iopad_verilog_model->cnt; iopad_idx++) {
/* Find if this inpad is mapped to a logical block */
found_mapped_inpad = 0;
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
/* Bypass OUTPAD: donot put any voltage stimuli */
/* Make sure We find the correct logical block !*/
if ((iopad_verilog_model == logical_block[iblock].mapped_spice_model)
&&(iopad_idx == logical_block[iblock].mapped_spice_model_index)) {
/* Output PAD only need a short connection */
if (VPACK_OUTPAD == logical_block[iblock].type) {
fprintf(fp, "//----- Output %s does not need a Stimuli ----\n", logical_block[iblock].name);
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- Input %s[%d] GENERATOR\n", gio_inout_prefix, iopad_idx);
fprintf(fp, " %s%s%s[%d] = 1'b%d;\n",
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
verilog_default_signal_init_value);
fprintf(fp, "end\n");
found_mapped_inpad = 1;
break;
}
/* Input PAD only need a short connection */
assert(VPACK_INPAD == logical_block[iblock].type);
cur_spice_net_info = NULL;
for (inet = 0; inet < num_nets; inet++) {
if (0 == strcmp(clb_net[inet].name, logical_block[iblock].name)) {
cur_spice_net_info = clb_net[inet].spice_net_info;
break;
}
}
assert(NULL != cur_spice_net_info);
assert(!(0 > cur_spice_net_info->density));
assert(!(1 < cur_spice_net_info->density));
assert(!(0 > cur_spice_net_info->probability));
assert(!(1 < cur_spice_net_info->probability));
/* Connect the reg to inouts */
fprintf(fp, "//----- Input %s Stimuli ----\n", logical_block[iblock].name);
fprintf(fp, "assign %s%s[%d] = %s%s%s[%d];\n",
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx,
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx);
/* Get the net information */
/* TODO: Give the net name in the blif file !*/
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- Input %s GENERATOR\n", logical_block[iblock].name);
fprintf(fp, " %s%s%s[%d] = 1'b%d;\n",
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
cur_spice_net_info->init_val);
fprintf(fp, "end\n");
fprintf(fp, "always wait (~%s)\n", top_tb_reset_port_name);
fprintf(fp, " begin \n");
fprintf(fp, " %s%s%s[%d] = ~%s%s%s[%d];\n #%.2f\n",
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
(op_clock_period * 2 * ((int)(cur_spice_net_info->probability / cur_spice_net_info->density)+ iblock) / verilog_sim_timescale));
fprintf(fp, " %s%s%s[%d] = ~%s%s%s[%d];\n #%.2f;\n",
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
(op_clock_period * 2 * ((int)((cur_spice_net_info->density / cur_spice_net_info->probability) * 2.5 + iblock)) / verilog_sim_timescale));
fprintf(fp, " end \n");
fprintf(fp, "\n");
found_mapped_inpad++;
}
}
assert((0 == found_mapped_inpad)||(1 == found_mapped_inpad));
/* If we find one iopad already, we finished in this round here */
if (1 == found_mapped_inpad) {
continue;
}
/* if we cannot find any mapped inpad from tech.-mapped netlist, give a default */
/* Connect the reg to inouts */
fprintf(fp, "//----- Input %s[%d] Stimuli ----\n", gio_inout_prefix, iopad_idx);
fprintf(fp, "assign %s%s[%d] = %s%s%s[%d];\n",
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx,
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx);
/* TODO: Give the net name in the blif file !*/
fprintf(fp, "initial\n");
fprintf(fp, " begin //--- Input %s[%d] GENERATOR\n", gio_inout_prefix, iopad_idx);
fprintf(fp, " %s%s%s[%d] = 1'b%d;\n",
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
verilog_default_signal_init_value);
fprintf(fp, "end\n");
}
return;
}
void dump_verilog_top_auto_preconf_testbench(char* circuit_name,
char* top_netlist_name,
int num_clock,
t_syn_verilog_opts syn_verilog_opts,
t_spice verilog,
char* postfix,
char* hex_file_path) {
FILE* fp = NULL;
char* title = my_strcat("FPGA Verilog Testbench for Top-level netlist of Design: ", circuit_name);
/* Check if the path exists*/
fp = fopen(top_netlist_name,"w");
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create top Verilog testbench %s!",__FILE__, __LINE__, top_netlist_name);
exit(1);
}
vpr_printf(TIO_MESSAGE_INFO, "Writing Autocheked and Preconfigured Testbench for FPGA Top-level Verilog netlist for %s...\n", circuit_name);
/* Print the title */
dump_verilog_file_header(fp, title);
my_free(title);
/* Start of testbench */
dump_verilog_top_auto_testbench_ports(fp, circuit_name, syn_verilog_opts, postfix);
/* Call defined top-level module */
dump_verilog_top_testbench_call_top_module(fp, circuit_name);
/* Call defined benchmark */
dump_verilog_top_auto_testbench_call_benchmark(fp, blif_circuit_name);
/* Add stimuli for reset, set, clock and iopad signals */
dump_verilog_top_preconf_testbench_stimuli(fp, num_clock, syn_verilog_opts, verilog, hex_file_path, verilog);
/* Add output autocheck */
dump_verilog_top_auto_testbench_check(fp);
/* Testbench ends*/
fprintf(fp, "endmodule\n");
/* Close the file*/
fclose(fp);
return;
}
void dump_fpga_spice_hex(char* hex_file_path,
char* chomped_circuit_name,
t_sram_orgz_info* sram_verilog_orgz_info) {
FILE* fp = NULL;
t_llist* temp = sram_verilog_orgz_info->conf_bit_head;
t_conf_bit_info* cur_conf_bit_info = NULL;
fp = fopen(hex_file_path, "w");
while (NULL != temp) {
cur_conf_bit_info = (t_conf_bit_info*)(temp->dptr);
fprintf(fp, "%d", cur_conf_bit_info->sram_bit->val);
temp = temp->next;
}
fclose(fp);
return;
}

View File

@ -2,4 +2,18 @@ void dump_verilog_top_auto_testbench(char* circuit_name,
char* top_netlist_name, char* top_netlist_name,
int num_clock, int num_clock,
t_syn_verilog_opts syn_verilog_opts, t_syn_verilog_opts syn_verilog_opts,
t_spice verilog); t_spice verilog,
char* postfix);
void dump_verilog_top_auto_preconf_testbench(char* circuit_name,
char* top_netlist_name,
int num_clock,
t_syn_verilog_opts syn_verilog_opts,
t_spice verilog,
char* postfix,
char* hex_file_path);
void dump_fpga_spice_hex(char* hex_file_path,
char* chomped_circuit_name,
t_sram_orgz_info* sram_verilog_orgz_info);

View File

@ -24,12 +24,15 @@ char* modelsim_proc_script_name_postfix = "_proc.tcl";
char* modelsim_top_script_name_postfix = "_runsim.tcl"; char* modelsim_top_script_name_postfix = "_runsim.tcl";
char* modelsim_testbench_module_postfix = "_top_tb"; char* modelsim_testbench_module_postfix = "_top_tb";
char* modelsim_auto_testbench_module_postfix = "_top_auto_tb"; char* modelsim_auto_testbench_module_postfix = "_top_auto_tb";
char* modelsim_auto_preconf_testbench_module_postfix = "_top_auto_preconf_tb";
char* modelsim_simulation_time_unit = "ms"; char* modelsim_simulation_time_unit = "ms";
char* verilog_top_postfix = "_top.v"; char* verilog_top_postfix = "_top.v";
char* bitstream_verilog_file_postfix = ".bitstream"; char* bitstream_verilog_file_postfix = ".bitstream";
char* hex_verilog_file_postfix = ".hex";
char* top_testbench_verilog_file_postfix = "_top_tb.v"; char* top_testbench_verilog_file_postfix = "_top_tb.v";
char* top_auto_testbench_verilog_file_postfix = "_top_auto_tb.v"; char* top_auto_testbench_verilog_file_postfix = "_top_auto_tb.v";
char* top_auto_preconf_testbench_verilog_file_postfix = "_top_auto_preconf_tb.v";
char* blif_testbench_verilog_file_postfix = "_blif_tb.v"; char* blif_testbench_verilog_file_postfix = "_blif_tb.v";
char* submodule_verilog_file_name = "sub_module.v"; char* submodule_verilog_file_name = "sub_module.v";
char* logic_block_verilog_file_name = "logic_blocks.v"; char* logic_block_verilog_file_name = "logic_blocks.v";

View File

@ -16,12 +16,15 @@ extern char* modelsim_proc_script_name_postfix;
extern char* modelsim_top_script_name_postfix; extern char* modelsim_top_script_name_postfix;
extern char* modelsim_testbench_module_postfix; extern char* modelsim_testbench_module_postfix;
extern char* modelsim_auto_testbench_module_postfix; extern char* modelsim_auto_testbench_module_postfix;
extern char* modelsim_auto_preconf_testbench_module_postfix;
extern char* modelsim_simulation_time_unit; extern char* modelsim_simulation_time_unit;
extern char* verilog_top_postfix; extern char* verilog_top_postfix;
extern char* bitstream_verilog_file_postfix; extern char* bitstream_verilog_file_postfix;
extern char* hex_verilog_file_postfix;
extern char* top_testbench_verilog_file_postfix; extern char* top_testbench_verilog_file_postfix;
extern char* top_auto_testbench_verilog_file_postfix; extern char* top_auto_testbench_verilog_file_postfix;
extern char* top_auto_preconf_testbench_verilog_file_postfix;
extern char* blif_testbench_verilog_file_postfix; extern char* blif_testbench_verilog_file_postfix;
extern char* submodule_verilog_file_name; extern char* submodule_verilog_file_name;
extern char* logic_block_verilog_file_name; extern char* logic_block_verilog_file_name;

View File

@ -362,6 +362,138 @@ void dump_verilog_modelsim_proc_auto_script(char* modelsim_proc_filename,
return; return;
} }
void dump_verilog_modelsim_proc_auto_preconf_script(char* modelsim_proc_filename,
char* modelsim_ini_path,
char* circuit_name,
boolean include_timing,
boolean init_sim,
char* modelsim_project_name) {
FILE* fp = NULL;
char* circuit_top_tb_name = NULL;
circuit_top_tb_name = my_strcat(circuit_name, modelsim_auto_preconf_testbench_module_postfix);
/* Create Modelsim proc file */
/* Open file and file handler */
fp = fopen(modelsim_proc_filename, "w");
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create Modelsim simulation deck auto-generation scripts: %s",
__FILE__, __LINE__, modelsim_proc_filename);
exit(1);
}
fprintf(fp, "proc create_project {projectname project_path} {\n");
fprintf(fp, " #Switch to the modelsim folder to create the project\n");
fprintf(fp, " set libname $projectname\n");
fprintf(fp, " set initfile %s\n", modelsim_ini_path);
fprintf(fp, " project new $project_path/$projectname $projectname $libname $initfile 0\n");
fprintf(fp, "}\n");
fprintf(fp, " \n");
fprintf(fp, "proc create_project_with_close {projectname modelsim_path} {\n");
fprintf(fp, " #Get the current project name\n");
fprintf(fp, " set project_env [project env]\n");
fprintf(fp, " if {$project_env eq \"\"} {\n");
fprintf(fp, " #If string empty (no project)\n");
fprintf(fp, " create_project $projectname $modelsim_path\n");
fprintf(fp, " } else {\n");
fprintf(fp, " #If string not empty (a project is loaded so clsoe it first)\n");
fprintf(fp, " project close\n");
fprintf(fp, " create_project $projectname $modelsim_path\n");
fprintf(fp, " }\n");
fprintf(fp, " }\n");
fprintf(fp, " \n");
fprintf(fp, "proc add_files_project {verilog_files} {\n");
fprintf(fp, " #Get the length of the list\n");
fprintf(fp, " set listlength [llength $verilog_files]\n");
fprintf(fp, " #Add the verilog files one by one\n");
fprintf(fp, " for {set x 0} {$x<$listlength} {incr x} {\n");
fprintf(fp, " project addfile [lindex $verilog_files $x]\n");
fprintf(fp, " }\n");
fprintf(fp, "}\n");
fprintf(fp, " \n");
fprintf(fp, "proc add_waves {} {\n");
fprintf(fp, " add wave -position insertpoint sim:/%s/*\n", circuit_top_tb_name);
fprintf(fp, "}\n");
fprintf(fp, "proc runsim {simtime unit} {\n");
fprintf(fp, " run $simtime $unit\n");
fprintf(fp, "}\n");
fprintf(fp, "#Top procedure to create enw project\n");
fprintf(fp, "proc top_create_new_project {projectname verilog_files modelsim_path simtime unit} {\n");
fprintf(fp, " #Create the project\n");
fprintf(fp, " create_project_with_close $projectname $modelsim_path\n");
fprintf(fp, " #Add the verilog files\n");
fprintf(fp, " add_files_project $verilog_files\n");
fprintf(fp, " #Compile all the files\n");
// fprintf(fp, " project compileall\n"); // removed to allow compilation with define
// Begin of compilation with Define
fprintf(fp, " set myFiles [project filenames]\n");
fprintf(fp, " foreach x $myFiles {\n");
fprintf(fp, " vlog ");
if(TRUE == include_timing){
fprintf(fp, "+define+%s ", verilog_timing_preproc_flag);
}
if(TRUE == init_sim){
fprintf(fp, "+define+%s ", verilog_init_sim_preproc_flag);
}
fprintf(fp, "$x\n }\n");
// End of compilation with Define
fprintf(fp, " #Start the simulation\n");
fprintf(fp, " vsim $projectname.%s -voptargs=+acc\n", circuit_top_tb_name);
fprintf(fp, " #Add the waves \n");
fprintf(fp, " add_waves\n");
fprintf(fp, " #run the simulation\n");
fprintf(fp, " runsim $simtime $unit\n");
fprintf(fp, " #Fit the window view\n");
fprintf(fp, " wave zoom full\n");
fprintf(fp, "}\n");
fprintf(fp, "#Top proc to recompile files and re run the simulation\n");
fprintf(fp, "proc top_rerun_sim {simtime unit} {\n");
// Save format
fprintf(fp, " #Save actual format\n");
fprintf(fp, " set myLoc [pwd]\n");
fprintf(fp, " write format wave -window .main_pane.wave.interior.cs.body.pw.wf $myLoc/relaunch.do\n");
// Quit simulation
fprintf(fp, " quit -sim\n");
// Recompile file
fprintf(fp, " #Compile updated verilog files\n");
fprintf(fp, " set myFiles [project filenames]\n");
fprintf(fp, " foreach x $myFiles {\n");
fprintf(fp, " vlog ");
if(TRUE == include_timing){
fprintf(fp, "+define+%s ", verilog_timing_preproc_flag);
}
if(TRUE == init_sim){
fprintf(fp, "+define+%s ", verilog_init_sim_preproc_flag);
}
fprintf(fp, "$x\n }\n");
// Restart the Simulation
fprintf(fp, " set projectname %s\n", modelsim_project_name);
fprintf(fp, " vsim $projectname.%s -voptargs=+acc -do relaunch.do\n", circuit_top_tb_name);
// Relaunch the Simulation
fprintf(fp, " #run the simulation\n");
fprintf(fp, " run $simtime $unit\n");
fprintf(fp, "}\n");
/* Close File handler */
fclose(fp);
/* Free */
my_free(circuit_top_tb_name);
return;
}
void dump_verilog_modelsim_top_script(char* modelsim_top_script_filename, void dump_verilog_modelsim_top_script(char* modelsim_top_script_filename,
char* modelsim_proc_script_filename, char* modelsim_proc_script_filename,
char* modelsim_project_path, char* modelsim_project_path,
@ -500,6 +632,75 @@ void dump_verilog_modelsim_top_auto_script(char* modelsim_top_auto_script_filena
return; return;
} }
void dump_verilog_modelsim_top_auto_preconf_script(char* modelsim_top_auto_script_filename,
char* modelsim_proc_auto_script_filename,
char* modelsim_project_path,
char* circuit_name,
char* modelsim_project_name,
float sim_time,
char* sim_time_unit,
t_spice spice) {
FILE* fp = NULL;
/* Create Modelsim proc file */
/* Open file and file handler */
fp = fopen(modelsim_top_auto_script_filename, "w");
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create Modelsim simulation deck auto-generation scripts: %s",
__FILE__, __LINE__, modelsim_top_auto_script_filename);
exit(1);
}
fprintf(fp, "set projectname %s\n", modelsim_project_name);
fprintf(fp, "set benchmark %s\n", circuit_name);
fprintf(fp, "\n");
fprintf(fp, "#in ms\n");
fprintf(fp, "set simtime %.4g\n", sim_time);
fprintf(fp, "set unit %s\n",
sim_time_unit);
fprintf(fp, "\n");
fprintf(fp, "#Path were both tcl script are located\n");
fprintf(fp, "set project_path \"%s%s\"\n", modelsim_project_path, default_modelsim_dir_name);
fprintf(fp, "\n");
fprintf(fp, "#Path were the verilog files are located\n");
fprintf(fp, "set verilog_path \"%s\"\n", modelsim_project_path);
fprintf(fp, "set verilog_files [list \\\n");
/* TODO: include verilog files */
fprintf(fp, " ${verilog_path}${benchmark}%s \\\n",
verilog_top_postfix);
fprintf(fp, " ${verilog_path}${benchmark}%s \\\n",
top_auto_preconf_testbench_verilog_file_postfix);
/* User-defined verilog netlists */
init_include_user_defined_verilog_netlists(spice);
modelsim_include_user_defined_verilog_netlists(fp, spice);
fprintf(fp, " ${verilog_path}%s%s \\\n",
default_lb_dir_name, logic_block_verilog_file_name);
fprintf(fp, " ${verilog_path}%s%s \\\n",
default_rr_dir_name, routing_verilog_file_name);
fprintf(fp, " ${verilog_path}%s%s ] \n",
default_submodule_dir_name, submodule_verilog_file_name);
fprintf(fp, "\n");
fprintf(fp, "#Source the tcl script\n");
fprintf(fp, "source ${verilog_path}%s\n", modelsim_proc_auto_script_filename);
fprintf(fp, "\n");
fprintf(fp, "#Execute the top level procedure\n");
fprintf(fp, "top_create_new_project $projectname $verilog_files $project_path $simtime $unit\n");
fprintf(fp, "\n");
fprintf(fp, "#Relaunch simulation\n");
/* Close File handler */
fclose(fp);
return;
}
/***** Top-level function *****/ /***** Top-level function *****/
void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info, void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
t_spice spice, t_spice spice,
@ -510,13 +711,17 @@ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
boolean include_timing, boolean include_timing,
boolean init_sim, boolean init_sim,
boolean print_top_tb, boolean print_top_tb,
boolean print_top_auto_tb) { boolean print_top_auto_tb,
boolean tb_preconf) {
char* modelsim_project_name = NULL; char* modelsim_project_name = NULL;
char* modelsim_proc_script_filename = NULL; char* modelsim_proc_script_filename = NULL;
char* modelsim_top_script_filename = NULL; char* modelsim_top_script_filename = NULL;
char* modelsim_proc_auto_script_filename = NULL; char* modelsim_proc_auto_script_filename = NULL;
char* modelsim_top_auto_script_filename = NULL; char* modelsim_top_auto_script_filename = NULL;
char* modelsim_proc_auto_preconf_script_filename = NULL;
char* modelsim_top_auto_preconf_script_filename = NULL;
char* auto_tb_postfix = "_autocheck"; char* auto_tb_postfix = "_autocheck";
char* auto_preconf_tb_postfix = "_preconf_autocheck";
float simulation_time_period = 0.; float simulation_time_period = 0.;
/* Determine the project name for Modelsim */ /* Determine the project name for Modelsim */
@ -525,6 +730,8 @@ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
modelsim_proc_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, modelsim_proc_script_name_postfix)); modelsim_proc_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, modelsim_proc_script_name_postfix));
modelsim_top_auto_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, my_strcat(auto_tb_postfix, modelsim_top_script_name_postfix))); modelsim_top_auto_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, my_strcat(auto_tb_postfix, modelsim_top_script_name_postfix)));
modelsim_proc_auto_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, my_strcat(auto_tb_postfix, modelsim_proc_script_name_postfix))); modelsim_proc_auto_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, my_strcat(auto_tb_postfix, modelsim_proc_script_name_postfix)));
modelsim_top_auto_preconf_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, my_strcat(auto_preconf_tb_postfix, modelsim_top_script_name_postfix)));
modelsim_proc_auto_preconf_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, my_strcat(auto_preconf_tb_postfix, modelsim_proc_script_name_postfix)));
/* Generate files */ /* Generate files */
vpr_printf(TIO_MESSAGE_INFO, "Writing Modelsim simulation deck auto-generation scripts...\n"); vpr_printf(TIO_MESSAGE_INFO, "Writing Modelsim simulation deck auto-generation scripts...\n");
@ -550,6 +757,12 @@ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
include_timing, init_sim, include_timing, init_sim,
modelsim_project_name); modelsim_project_name);
} }
if(tb_preconf){
dump_verilog_modelsim_proc_auto_preconf_script( modelsim_proc_auto_preconf_script_filename,
simulator_ini_path, chomped_circuit_name,
include_timing, init_sim,
modelsim_project_name);
}
/* Compute simulation time period */ /* Compute simulation time period */
simulation_time_period = get_verilog_modelsim_simulation_time_period(convert_modelsim_time_unit_to_float(modelsim_simulation_time_unit), simulation_time_period = get_verilog_modelsim_simulation_time_period(convert_modelsim_time_unit_to_float(modelsim_simulation_time_unit),
get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info), get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info),
@ -568,7 +781,15 @@ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
} }
if(print_top_auto_tb){ if(print_top_auto_tb){
dump_verilog_modelsim_top_auto_script(modelsim_top_auto_script_filename, dump_verilog_modelsim_top_auto_script(modelsim_top_auto_script_filename,
my_strcat(chomped_circuit_name, my_strcat( auto_tb_postfix, modelsim_proc_script_name_postfix)), my_strcat(chomped_circuit_name, my_strcat(auto_tb_postfix, modelsim_proc_script_name_postfix)),
verilog_dir_formatted,
chomped_circuit_name, modelsim_project_name,
simulation_time_period, modelsim_simulation_time_unit,
spice);
}
if(tb_preconf){
dump_verilog_modelsim_top_auto_preconf_script(modelsim_top_auto_preconf_script_filename,
my_strcat(chomped_circuit_name, my_strcat( auto_preconf_tb_postfix, modelsim_proc_script_name_postfix)),
verilog_dir_formatted, verilog_dir_formatted,
chomped_circuit_name, modelsim_project_name, chomped_circuit_name, modelsim_project_name,
simulation_time_period, modelsim_simulation_time_unit, simulation_time_period, modelsim_simulation_time_unit,

View File

@ -8,4 +8,6 @@ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
boolean include_timing, boolean include_timing,
boolean init_sim, boolean init_sim,
boolean print_top_tb, boolean print_top_tb,
boolean print_top_auto_tb); boolean print_top_auto_tb,
boolean tb_preconf);