diff --git a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_api.c b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_api.c index 2af8f7c53..06c0af9b8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_api.c +++ b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_api.c @@ -116,16 +116,22 @@ void vpr_dump_syn_verilog(t_vpr_setup vpr_setup, char* top_netlist_path = NULL; char* bitstream_file_name = NULL; char* bitstream_file_path = NULL; + char* hex_file_name = NULL; + char* hex_file_path = NULL; char* top_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_auto_testbench_file_path = NULL; + char* top_auto_preconf_testbench_file_path = NULL; char* blif_testbench_file_name = NULL; char* blif_testbench_file_path = NULL; char* chomped_parent_dir = NULL; char* chomped_circuit_name = NULL; + boolean tb_preconf = TRUE; + /* Check if the routing architecture we support*/ if (UNI_DIRECTIONAL != vpr_setup.RoutingArch.directionality) { 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); bitstream_file_name = my_strcat(chomped_circuit_name, bitstream_verilog_file_postfix); 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_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_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_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, 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, - 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_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.init_sim, 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 */ diff --git a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_autocheck_tb.c b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_autocheck_tb.c index 91c4cd40c..6d7505882 100644 --- a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_autocheck_tb.c +++ b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_autocheck_tb.c @@ -401,8 +401,9 @@ int dump_verilog_top_testbench_find_num_config_clock_cycles(t_llist* head) { static void dump_verilog_top_auto_testbench_ports(FILE* fp, - char* circuit_name, - t_syn_verilog_opts syn_verilog_opts){ + char* circuit_name, + t_syn_verilog_opts syn_verilog_opts, + char* postfix){ int num_array_bl, num_array_wl; int bl_decoder_size, wl_decoder_size; 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); 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 */ /* 1. reset, set, clock signals */ /* 2. iopad signals */ @@ -567,16 +568,11 @@ void dump_verilog_top_auto_testbench_call_benchmark(FILE* fp, char* blif_circuit if(iblock>0){ fprintf(fp, ",\n"); } - if(VPACK_INPAD == logical_block[iblock].type){ - /* 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); - } - else{ + if(TRUE == logical_block[iblock].is_clock){ + fprintf(fp, " %s", top_tb_op_clock_port_name); + } else if(VPACK_INPAD == logical_block[iblock].type){ 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); } } @@ -624,7 +620,8 @@ void dump_verilog_top_auto_testbench(char* circuit_name, char* top_netlist_name, int num_clock, t_syn_verilog_opts syn_verilog_opts, - t_spice verilog) { + t_spice verilog, + char* postfix) { FILE* fp = NULL; 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); } - 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 */ dump_verilog_file_header(fp, title); my_free(title); - /* 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 */ dump_verilog_top_testbench_call_top_module(fp, circuit_name); @@ -665,3 +661,302 @@ void dump_verilog_top_auto_testbench(char* circuit_name, 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; +} diff --git a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_autocheck_tb.h b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_autocheck_tb.h index d97ca8e48..bd085e7a2 100644 --- a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_autocheck_tb.h +++ b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_autocheck_tb.h @@ -2,4 +2,18 @@ void dump_verilog_top_auto_testbench(char* circuit_name, char* top_netlist_name, int num_clock, 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); diff --git a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_global.c b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_global.c index dfef44193..0eb6be08d 100644 --- a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_global.c +++ b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_global.c @@ -24,12 +24,15 @@ char* modelsim_proc_script_name_postfix = "_proc.tcl"; char* modelsim_top_script_name_postfix = "_runsim.tcl"; char* modelsim_testbench_module_postfix = "_top_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* verilog_top_postfix = "_top.v"; char* bitstream_verilog_file_postfix = ".bitstream"; +char* hex_verilog_file_postfix = ".hex"; char* top_testbench_verilog_file_postfix = "_top_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* submodule_verilog_file_name = "sub_module.v"; char* logic_block_verilog_file_name = "logic_blocks.v"; diff --git a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_global.h b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_global.h index eb8c2b7a5..e2ced7899 100644 --- a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_global.h +++ b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_global.h @@ -16,12 +16,15 @@ extern char* modelsim_proc_script_name_postfix; extern char* modelsim_top_script_name_postfix; extern char* modelsim_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* verilog_top_postfix; extern char* bitstream_verilog_file_postfix; +extern char* hex_verilog_file_postfix; extern char* top_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* submodule_verilog_file_name; extern char* logic_block_verilog_file_name; diff --git a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_modelsim_autodeck.c b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_modelsim_autodeck.c index 5a8581fd6..f79105b1a 100644 --- a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_modelsim_autodeck.c +++ b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_modelsim_autodeck.c @@ -362,6 +362,138 @@ void dump_verilog_modelsim_proc_auto_script(char* modelsim_proc_filename, 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, char* modelsim_proc_script_filename, char* modelsim_project_path, @@ -500,6 +632,75 @@ void dump_verilog_modelsim_top_auto_script(char* modelsim_top_auto_script_filena 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 *****/ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info, t_spice spice, @@ -510,13 +711,17 @@ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info, boolean include_timing, boolean init_sim, boolean print_top_tb, - boolean print_top_auto_tb) { + boolean print_top_auto_tb, + boolean tb_preconf) { char* modelsim_project_name = NULL; char* modelsim_proc_script_filename = NULL; char* modelsim_top_script_filename = NULL; char* modelsim_proc_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_preconf_tb_postfix = "_preconf_autocheck"; float simulation_time_period = 0.; /* 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_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_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 */ 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, 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 */ 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), @@ -568,11 +781,19 @@ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info, } if(print_top_auto_tb){ 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)), - verilog_dir_formatted, - chomped_circuit_name, modelsim_project_name, - simulation_time_period, modelsim_simulation_time_unit, - spice); + 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, + chomped_circuit_name, modelsim_project_name, + simulation_time_period, modelsim_simulation_time_unit, + spice); } /* Free */ my_free(modelsim_project_name); diff --git a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_modelsim_autodeck.h b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_modelsim_autodeck.h index dcba6abf6..dcadc018f 100644 --- a/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_modelsim_autodeck.h +++ b/vpr7_x2p/vpr/SRC/fpga_spice/verilog/verilog_modelsim_autodeck.h @@ -8,4 +8,6 @@ void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info, boolean include_timing, boolean init_sim, boolean print_top_tb, - boolean print_top_auto_tb); + boolean print_top_auto_tb, + boolean tb_preconf); +