Add an autochecked configuration free testbench
This commit is contained in:
parent
79f3db9880
commit
f5ea3ff233
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue