2020-02-26 22:30:21 -06:00
/********************************************************************
* This file includes functions that are used to create
* an auto - check top - level testbench for a FPGA fabric
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <fstream>
# include <iomanip>
# include <algorithm>
/* Headers from vtrutil library */
# include "vtr_log.h"
# include "vtr_assert.h"
# include "vtr_time.h"
/* Headers from openfpgautil library */
# include "openfpga_port.h"
# include "openfpga_digest.h"
# include "bitstream_manager_utils.h"
2020-04-05 18:39:30 -05:00
# include "openfpga_reserved_words.h"
2020-02-26 22:30:21 -06:00
# include "openfpga_naming.h"
# include "simulation_utils.h"
# include "openfpga_atom_netlist_utils.h"
# include "verilog_constants.h"
# include "verilog_writer_utils.h"
# include "verilog_testbench_utils.h"
# include "verilog_top_testbench.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Local variables used only in this file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
constexpr char * TOP_TESTBENCH_REFERENCE_INSTANCE_NAME = " REF_DUT " ;
constexpr char * TOP_TESTBENCH_FPGA_INSTANCE_NAME = " FPGA_DUT " ;
constexpr char * TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX = " _benchmark " ;
constexpr char * TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX = " _fpga " ;
constexpr char * TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX = " _flag " ;
2020-05-27 19:40:45 -05:00
constexpr char * TOP_TESTBENCH_PROG_TASK_NAME = " prog_cycle_task " ;
2020-02-26 22:30:21 -06:00
constexpr char * TOP_TESTBENCH_SIM_START_PORT_NAME = " sim_start " ;
constexpr int TOP_TESTBENCH_MAGIC_NUMBER_FOR_SIMULATION_TIME = 200 ;
constexpr char * TOP_TESTBENCH_ERROR_COUNTER = " nb_error " ;
constexpr char * TOP_TB_RESET_PORT_NAME = " greset " ;
constexpr char * TOP_TB_SET_PORT_NAME = " gset " ;
constexpr char * TOP_TB_PROG_RESET_PORT_NAME = " prog_reset " ;
constexpr char * TOP_TB_PROG_SET_PORT_NAME = " prog_set " ;
constexpr char * TOP_TB_CONFIG_DONE_PORT_NAME = " config_done " ;
constexpr char * TOP_TB_OP_CLOCK_PORT_NAME = " op_clock " ;
constexpr char * TOP_TB_PROG_CLOCK_PORT_NAME = " prog_clock " ;
constexpr char * TOP_TB_INOUT_REG_POSTFIX = " _reg " ;
constexpr char * TOP_TB_CLOCK_REG_POSTFIX = " _reg " ;
constexpr char * AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = " _autocheck_top_tb " ;
2020-05-30 00:22:01 -05:00
/********************************************************************
* Print local wires for flatten memory ( standalone ) configuration protocols
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-30 00:22:01 -05:00
void print_verilog_top_testbench_flatten_memory_port ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Print the port for Bit-Line */
print_verilog_comment ( fp , std : : string ( " ---- Bit Line ports ----- " ) ) ;
ModulePortId bl_port_id = module_manager . find_module_port ( top_module , std : : string ( MEMORY_BL_PORT_NAME ) ) ;
BasicPort bl_port = module_manager . module_port ( top_module , bl_port_id ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , bl_port ) < < " ; " < < std : : endl ;
/* Print the port for Word-Line */
print_verilog_comment ( fp , std : : string ( " ---- Word Line ports ----- " ) ) ;
ModulePortId wl_port_id = module_manager . find_module_port ( top_module , std : : string ( MEMORY_WL_PORT_NAME ) ) ;
BasicPort wl_port = module_manager . module_port ( top_module , wl_port_id ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , wl_port ) < < " ; " < < std : : endl ;
}
2020-02-26 22:30:21 -06:00
/********************************************************************
* Print local wires for configuration chain protocols
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_config_chain_port ( std : : fstream & fp ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Print the head of configuraion-chains here */
print_verilog_comment ( fp , std : : string ( " ---- Configuration-chain head ----- " ) ) ;
BasicPort config_chain_head_port ( generate_configuration_chain_head_name ( ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , config_chain_head_port ) < < " ; " < < std : : endl ;
/* Print the tail of configuration-chains here */
print_verilog_comment ( fp , std : : string ( " ---- Configuration-chain tail ----- " ) ) ;
BasicPort config_chain_tail_port ( generate_configuration_chain_tail_name ( ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , config_chain_tail_port ) < < " ; " < < std : : endl ;
}
2020-05-30 21:04:44 -05:00
/********************************************************************
* Print local wires for memory bank configuration protocols
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-30 21:04:44 -05:00
void print_verilog_top_testbench_memory_bank_port ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Print the address port for the Bit-Line decoder here */
print_verilog_comment ( fp , std : : string ( " ---- Address port for Bit-Line decoder ----- " ) ) ;
ModulePortId bl_addr_port_id = module_manager . find_module_port ( top_module ,
2020-05-30 21:53:19 -05:00
std : : string ( DECODER_BL_ADDRESS_PORT_NAME ) ) ;
2020-05-30 21:04:44 -05:00
BasicPort bl_addr_port = module_manager . module_port ( top_module , bl_addr_port_id ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , bl_addr_port ) < < " ; " < < std : : endl ;
/* Print the address port for the Word-Line decoder here */
print_verilog_comment ( fp , std : : string ( " ---- Address port for Word-Line decoder ----- " ) ) ;
ModulePortId wl_addr_port_id = module_manager . find_module_port ( top_module ,
2020-05-30 21:53:19 -05:00
std : : string ( DECODER_WL_ADDRESS_PORT_NAME ) ) ;
2020-05-30 21:04:44 -05:00
BasicPort wl_addr_port = module_manager . module_port ( top_module , wl_addr_port_id ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , wl_addr_port ) < < " ; " < < std : : endl ;
/* Print the data-input port for the frame-based decoder here */
print_verilog_comment ( fp , std : : string ( " ---- Data input port for frame-based decoder ----- " ) ) ;
ModulePortId din_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_DATA_IN_PORT_NAME ) ) ;
BasicPort din_port = module_manager . module_port ( top_module , din_port_id ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , din_port ) < < " ; " < < std : : endl ;
/* Wire the INVERTED programming clock to the enable signal !!! */
print_verilog_comment ( fp , std : : string ( " ---- Wire enable port of frame-based decoder to inverted programming clock ----- " ) ) ;
ModulePortId en_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_ENABLE_PORT_NAME ) ) ;
BasicPort en_port = module_manager . module_port ( top_module , en_port_id ) ;
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , en_port ) < < " ; " < < std : : endl ;
print_verilog_wire_connection ( fp , en_port , prog_clock_port , true ) ;
}
2020-05-27 19:40:45 -05:00
/********************************************************************
* Print local wires for frame - based decoder protocols
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-27 19:40:45 -05:00
void print_verilog_top_testbench_frame_decoder_port ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Print the address port for the frame-based decoder here */
print_verilog_comment ( fp , std : : string ( " ---- Address port for frame-based decoder ----- " ) ) ;
ModulePortId addr_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_ADDRESS_PORT_NAME ) ) ;
BasicPort addr_port = module_manager . module_port ( top_module , addr_port_id ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , addr_port ) < < " ; " < < std : : endl ;
/* Print the data-input port for the frame-based decoder here */
print_verilog_comment ( fp , std : : string ( " ---- Data input port for frame-based decoder ----- " ) ) ;
ModulePortId din_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_DATA_IN_PORT_NAME ) ) ;
BasicPort din_port = module_manager . module_port ( top_module , din_port_id ) ;
2020-05-28 19:22:27 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_REG , din_port ) < < " ; " < < std : : endl ;
2020-05-27 19:40:45 -05:00
2020-05-29 00:05:24 -05:00
/* Wire the INVERTED programming clock to the enable signal !!! */
print_verilog_comment ( fp , std : : string ( " ---- Wire enable port of frame-based decoder to inverted programming clock ----- " ) ) ;
2020-05-27 19:40:45 -05:00
ModulePortId en_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_ENABLE_PORT_NAME ) ) ;
BasicPort en_port = module_manager . module_port ( top_module , en_port_id ) ;
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
2020-05-28 19:22:27 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , en_port ) < < " ; " < < std : : endl ;
2020-05-29 00:05:24 -05:00
print_verilog_wire_connection ( fp , en_port , prog_clock_port , true ) ;
2020-05-27 19:40:45 -05:00
}
2020-02-26 22:30:21 -06:00
/********************************************************************
* Print local wires for different types of configuration protocols
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_config_protocol_port ( std : : fstream & fp ,
2020-05-27 19:40:45 -05:00
const e_config_protocol_type & sram_orgz_type ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
2020-02-26 22:30:21 -06:00
switch ( sram_orgz_type ) {
case CONFIG_MEM_STANDALONE :
2020-05-30 00:22:01 -05:00
print_verilog_top_testbench_flatten_memory_port ( fp , module_manager , top_module ) ;
2020-02-26 22:30:21 -06:00
break ;
case CONFIG_MEM_SCAN_CHAIN :
print_verilog_top_testbench_config_chain_port ( fp ) ;
break ;
case CONFIG_MEM_MEMORY_BANK :
2020-05-30 21:04:44 -05:00
print_verilog_top_testbench_memory_bank_port ( fp , module_manager , top_module ) ;
2020-02-26 22:30:21 -06:00
break ;
2020-05-27 19:40:45 -05:00
case CONFIG_MEM_FRAME_BASED :
print_verilog_top_testbench_frame_decoder_port ( fp , module_manager , top_module ) ;
2020-02-26 22:30:21 -06:00
break ;
default :
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Invalid type of SRAM organization! \n " ) ;
exit ( 1 ) ;
}
}
/********************************************************************
* Wire the global ports of FPGA fabric to local wires
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_global_ports_stimuli ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ,
const CircuitLibrary & circuit_lib ,
const std : : vector < CircuitPortId > & global_ports ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
print_verilog_comment ( fp , std : : string ( " ----- Begin connecting global ports of FPGA fabric to stimuli ----- " ) ) ;
/* Connect global clock ports to operating or programming clock signal */
for ( const CircuitPortId & model_global_port : global_ports ) {
if ( CIRCUIT_MODEL_PORT_CLOCK ! = circuit_lib . port_type ( model_global_port ) ) {
continue ;
}
/* Reach here, it means we have a global clock to deal with:
2020-06-12 18:31:14 -05:00
* 1. if the port is identified as a programming clock ,
2020-02-26 22:30:21 -06:00
* connect it to the local wire of programming clock
2020-06-12 18:31:14 -05:00
* 2. if the port is identified as an operating clock
2020-02-26 22:30:21 -06:00
* connect it to the local wire of operating clock
*/
/* Find the module port */
ModulePortId module_global_port = module_manager . find_module_port ( top_module , circuit_lib . port_prefix ( model_global_port ) ) ;
VTR_ASSERT ( true = = module_manager . valid_module_port_id ( top_module , module_global_port ) ) ;
BasicPort stimuli_clock_port ;
if ( true = = circuit_lib . port_is_prog ( model_global_port ) ) {
stimuli_clock_port . set_name ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) ) ;
stimuli_clock_port . set_width ( 1 ) ;
} else {
VTR_ASSERT_SAFE ( false = = circuit_lib . port_is_prog ( model_global_port ) ) ;
stimuli_clock_port . set_name ( std : : string ( TOP_TB_OP_CLOCK_PORT_NAME ) ) ;
stimuli_clock_port . set_width ( 1 ) ;
}
/* Wire the port to the input stimuli:
* The wiring will be inverted if the default value of the global port is 1
* Otherwise , the wiring will not be inverted !
*/
2020-06-12 18:31:14 -05:00
print_verilog_wire_connection ( fp , module_manager . module_port ( top_module , module_global_port ) ,
stimuli_clock_port ,
1 = = circuit_lib . port_default_value ( model_global_port ) ) ;
2020-02-26 22:30:21 -06:00
}
/* Connect global configuration done ports to configuration done signal */
for ( const CircuitPortId & model_global_port : global_ports ) {
/* Bypass clock signals, they have been processed */
if ( CIRCUIT_MODEL_PORT_CLOCK = = circuit_lib . port_type ( model_global_port ) ) {
continue ;
}
if ( false = = circuit_lib . port_is_config_enable ( model_global_port ) ) {
continue ;
}
/* Reach here, it means we have a configuration done port to deal with */
/* Find the module port */
ModulePortId module_global_port = module_manager . find_module_port ( top_module , circuit_lib . port_prefix ( model_global_port ) ) ;
VTR_ASSERT ( true = = module_manager . valid_module_port_id ( top_module , module_global_port ) ) ;
BasicPort stimuli_config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
/* Wire the port to the input stimuli:
* The wiring will be inverted if the default value of the global port is 1
* Otherwise , the wiring will not be inverted !
*/
2020-06-12 18:31:14 -05:00
print_verilog_wire_connection ( fp , module_manager . module_port ( top_module , module_global_port ) ,
stimuli_config_done_port ,
1 = = circuit_lib . port_default_value ( model_global_port ) ) ;
2020-02-26 22:30:21 -06:00
}
/* Connect global reset ports to operating or programming reset signal */
for ( const CircuitPortId & model_global_port : global_ports ) {
/* Bypass clock signals, they have been processed */
if ( CIRCUIT_MODEL_PORT_CLOCK = = circuit_lib . port_type ( model_global_port ) ) {
continue ;
}
/* Bypass config_done signals, they have been processed */
if ( true = = circuit_lib . port_is_config_enable ( model_global_port ) ) {
continue ;
}
if ( false = = circuit_lib . port_is_reset ( model_global_port ) ) {
continue ;
}
/* Reach here, it means we have a reset port to deal with */
/* Find the module port */
ModulePortId module_global_port = module_manager . find_module_port ( top_module , circuit_lib . port_prefix ( model_global_port ) ) ;
VTR_ASSERT ( true = = module_manager . valid_module_port_id ( top_module , module_global_port ) ) ;
BasicPort stimuli_reset_port ;
if ( true = = circuit_lib . port_is_prog ( model_global_port ) ) {
stimuli_reset_port . set_name ( std : : string ( TOP_TB_PROG_RESET_PORT_NAME ) ) ;
stimuli_reset_port . set_width ( 1 ) ;
} else {
VTR_ASSERT_SAFE ( false = = circuit_lib . port_is_prog ( model_global_port ) ) ;
stimuli_reset_port . set_name ( std : : string ( TOP_TB_RESET_PORT_NAME ) ) ;
stimuli_reset_port . set_width ( 1 ) ;
}
/* Wire the port to the input stimuli:
* The wiring will be inverted if the default value of the global port is 1
* Otherwise , the wiring will not be inverted !
*/
2020-06-12 18:31:14 -05:00
print_verilog_wire_connection ( fp , module_manager . module_port ( top_module , module_global_port ) ,
stimuli_reset_port ,
1 = = circuit_lib . port_default_value ( model_global_port ) ) ;
2020-02-26 22:30:21 -06:00
}
/* Connect global set ports to operating or programming set signal */
for ( const CircuitPortId & model_global_port : global_ports ) {
/* Bypass clock signals, they have been processed */
if ( CIRCUIT_MODEL_PORT_CLOCK = = circuit_lib . port_type ( model_global_port ) ) {
continue ;
}
/* Bypass config_done signals, they have been processed */
if ( true = = circuit_lib . port_is_config_enable ( model_global_port ) ) {
continue ;
}
/* Bypass reset signals, they have been processed */
if ( true = = circuit_lib . port_is_reset ( model_global_port ) ) {
continue ;
}
if ( false = = circuit_lib . port_is_set ( model_global_port ) ) {
continue ;
}
/* Reach here, it means we have a set port to deal with */
/* Find the module port */
ModulePortId module_global_port = module_manager . find_module_port ( top_module , circuit_lib . port_prefix ( model_global_port ) ) ;
VTR_ASSERT ( true = = module_manager . valid_module_port_id ( top_module , module_global_port ) ) ;
BasicPort stimuli_set_port ;
if ( true = = circuit_lib . port_is_prog ( model_global_port ) ) {
stimuli_set_port . set_name ( std : : string ( TOP_TB_PROG_SET_PORT_NAME ) ) ;
stimuli_set_port . set_width ( 1 ) ;
} else {
VTR_ASSERT_SAFE ( false = = circuit_lib . port_is_prog ( model_global_port ) ) ;
stimuli_set_port . set_name ( std : : string ( TOP_TB_SET_PORT_NAME ) ) ;
stimuli_set_port . set_width ( 1 ) ;
}
/* Wire the port to the input stimuli:
* The wiring will be inverted if the default value of the global port is 1
* Otherwise , the wiring will not be inverted !
*/
2020-06-12 18:31:14 -05:00
print_verilog_wire_connection ( fp , module_manager . module_port ( top_module , module_global_port ) ,
stimuli_set_port ,
1 = = circuit_lib . port_default_value ( model_global_port ) ) ;
2020-02-26 22:30:21 -06:00
}
/* For the rest of global ports, wire them to constant signals */
for ( const CircuitPortId & model_global_port : global_ports ) {
/* Bypass clock signals, they have been processed */
if ( CIRCUIT_MODEL_PORT_CLOCK = = circuit_lib . port_type ( model_global_port ) ) {
continue ;
}
/* Bypass config_done signals, they have been processed */
if ( true = = circuit_lib . port_is_config_enable ( model_global_port ) ) {
continue ;
}
/* Bypass reset signals, they have been processed */
if ( true = = circuit_lib . port_is_reset ( model_global_port ) ) {
continue ;
}
/* Bypass set signals, they have been processed */
if ( true = = circuit_lib . port_is_set ( model_global_port ) ) {
continue ;
}
2020-04-15 16:48:33 -05:00
/* Bypass io signals, they do not need any drivers */
if ( true = = circuit_lib . port_is_io ( model_global_port ) ) {
2020-04-05 18:39:30 -05:00
continue ;
}
/* Find the port name, gpio port has special names */
std : : string port_name ;
if ( true = = circuit_lib . port_is_io ( model_global_port ) ) {
port_name = generate_fpga_global_io_port_name ( std : : string ( GIO_INOUT_PREFIX ) , circuit_lib , circuit_lib . port_parent_model ( model_global_port ) , model_global_port ) ;
} else {
VTR_ASSERT_SAFE ( false = = circuit_lib . port_is_io ( model_global_port ) ) ;
port_name = circuit_lib . port_prefix ( model_global_port ) ;
}
2020-02-26 22:30:21 -06:00
/* Reach here, it means we have a port to deal with */
/* Find the module port and wire it to constant values */
2020-04-05 18:39:30 -05:00
ModulePortId module_global_port = module_manager . find_module_port ( top_module , port_name ) ;
2020-02-26 22:30:21 -06:00
VTR_ASSERT ( true = = module_manager . valid_module_port_id ( top_module , module_global_port ) ) ;
BasicPort module_port = module_manager . module_port ( top_module , module_global_port ) ;
std : : vector < size_t > default_values ( module_port . get_width ( ) , circuit_lib . port_default_value ( model_global_port ) ) ;
print_verilog_wire_constant_values ( fp , module_port , default_values ) ;
}
print_verilog_comment ( fp , std : : string ( " ----- End connecting global ports of FPGA fabric to stimuli ----- " ) ) ;
}
/********************************************************************
2020-06-12 18:31:14 -05:00
* This function prints the top testbench module declaration
2020-02-26 22:30:21 -06:00
* and internal wires / port declaration
* Ports can be classified in two categories :
* 1. General - purpose ports , which are datapath I / Os , clock signals
* for the FPGA fabric and input benchmark
* 2. Fabric - featured ports , which are required by configuration
* protocols .
* Due the difference in configuration protocols , the internal
* wires and ports will be different :
* ( a ) configuration - chain : we will have two ports ,
* a head and a tail for the configuration chain ,
* in addition to the regular ports .
2020-06-12 18:31:14 -05:00
* ( b ) memory - decoders : we will have a few ports to drive
2020-02-26 22:30:21 -06:00
* address lines for decoders and a bit input port to feed
* configuration bits
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_ports ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ,
const AtomContext & atom_ctx ,
2020-02-27 17:37:20 -06:00
const VprNetlistAnnotation & netlist_annotation ,
2020-02-26 22:30:21 -06:00
const std : : vector < std : : string > & clock_port_names ,
const e_config_protocol_type & sram_orgz_type ,
const std : : string & circuit_name ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Print module definition */
fp < < " module " < < circuit_name < < std : : string ( AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX ) ;
fp < < " ; " < < std : : endl ;
/* Print regular local wires:
* 1. global ports , i . e . , reset , set and clock signals
* 2. datapath I / O signals
*/
/* Global ports of top-level module */
print_verilog_comment ( fp , std : : string ( " ----- Local wires for global ports of FPGA fabric ----- " ) ) ;
for ( const BasicPort & module_port : module_manager . module_ports_by_type ( top_module , ModuleManager : : MODULE_GLOBAL_PORT ) ) {
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , module_port ) < < " ; " < < std : : endl ;
}
/* Add an empty line as a splitter */
fp < < std : : endl ;
/* Datapath I/Os of top-level module */
print_verilog_comment ( fp , std : : string ( " ----- Local wires for I/Os of FPGA fabric ----- " ) ) ;
for ( const BasicPort & module_port : module_manager . module_ports_by_type ( top_module , ModuleManager : : MODULE_GPIO_PORT ) ) {
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , module_port ) < < " ; " < < std : : endl ;
}
/* Add an empty line as a splitter */
fp < < std : : endl ;
2020-04-05 18:50:11 -05:00
for ( const BasicPort & module_port : module_manager . module_ports_by_type ( top_module , ModuleManager : : MODULE_GPIN_PORT ) ) {
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , module_port ) < < " ; " < < std : : endl ;
}
/* Add an empty line as a splitter */
fp < < std : : endl ;
for ( const BasicPort & module_port : module_manager . module_ports_by_type ( top_module , ModuleManager : : MODULE_GPOUT_PORT ) ) {
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , module_port ) < < " ; " < < std : : endl ;
}
/* Add an empty line as a splitter */
fp < < std : : endl ;
2020-02-26 22:30:21 -06:00
/* Add local wires/registers that drive stimulus
* We create these general purpose ports here ,
2020-06-12 18:31:14 -05:00
* and then wire them to the ports of FPGA fabric depending on their usage
2020-02-26 22:30:21 -06:00
*/
/* Configuration done port */
BasicPort config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , config_done_port ) < < " ; " < < std : : endl ;
/* Programming clock */
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , prog_clock_port ) < < " ; " < < std : : endl ;
BasicPort prog_clock_register_port ( std : : string ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) + std : : string ( TOP_TB_CLOCK_REG_POSTFIX ) ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , prog_clock_register_port ) < < " ; " < < std : : endl ;
/* Operating clock */
BasicPort op_clock_port ( std : : string ( TOP_TB_OP_CLOCK_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , op_clock_port ) < < " ; " < < std : : endl ;
BasicPort op_clock_register_port ( std : : string ( std : : string ( TOP_TB_OP_CLOCK_PORT_NAME ) + std : : string ( TOP_TB_CLOCK_REG_POSTFIX ) ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , op_clock_register_port ) < < " ; " < < std : : endl ;
/* Programming set and reset */
BasicPort prog_reset_port ( std : : string ( TOP_TB_PROG_RESET_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , prog_reset_port ) < < " ; " < < std : : endl ;
BasicPort prog_set_port ( std : : string ( TOP_TB_PROG_SET_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , prog_set_port ) < < " ; " < < std : : endl ;
/* Global set and reset */
BasicPort reset_port ( std : : string ( TOP_TB_RESET_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , reset_port ) < < " ; " < < std : : endl ;
BasicPort set_port ( std : : string ( TOP_TB_SET_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , set_port ) < < " ; " < < std : : endl ;
/* Configuration ports depend on the organization of SRAMs */
2020-05-27 19:40:45 -05:00
print_verilog_top_testbench_config_protocol_port ( fp , sram_orgz_type ,
module_manager , top_module ) ;
2020-02-26 22:30:21 -06:00
2020-06-12 18:31:14 -05:00
/* Create a clock port if the benchmark have one but not in the default name!
2020-02-26 22:30:21 -06:00
* We will wire the clock directly to the operating clock directly
*/
for ( const std : : string clock_port_name : clock_port_names ) {
if ( 0 = = clock_port_name . compare ( op_clock_port . get_name ( ) ) ) {
continue ;
}
/* Ensure the clock port name is not a duplication of global ports of the FPGA module */
bool print_clock_port = true ;
for ( const BasicPort & module_port : module_manager . module_ports_by_type ( top_module , ModuleManager : : MODULE_GLOBAL_PORT ) ) {
if ( 0 = = clock_port_name . compare ( module_port . get_name ( ) ) ) {
print_clock_port = false ;
}
}
if ( false = = print_clock_port ) {
continue ;
}
/* Print the clock and wire it to op_clock */
print_verilog_comment ( fp , std : : string ( " ----- Create a clock for benchmark and wire it to op_clock ------- " ) ) ;
BasicPort clock_port ( clock_port_name , 1 ) ;
fp < < " \t " < < generate_verilog_port ( VERILOG_PORT_WIRE , clock_port ) < < " ; " < < std : : endl ;
print_verilog_wire_connection ( fp , clock_port , op_clock_port , false ) ;
}
2020-02-27 17:37:20 -06:00
print_verilog_testbench_shared_ports ( fp , atom_ctx , netlist_annotation ,
2020-02-27 17:51:55 -06:00
clock_port_names ,
2020-02-26 22:30:21 -06:00
std : : string ( TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX ) ,
std : : string ( TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX ) ,
std : : string ( TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX ) ,
std : : string ( AUTOCHECKED_SIMULATION_FLAG ) ) ;
2020-06-12 18:31:14 -05:00
/* Instantiate an integer to count the number of error and
2020-02-26 22:30:21 -06:00
* determine if the simulation succeed or failed
*/
print_verilog_comment ( fp , std : : string ( " ----- Error counter ----- " ) ) ;
fp < < " \t integer " < < TOP_TESTBENCH_ERROR_COUNTER < < " = 0; " < < std : : endl ;
}
2020-05-29 19:07:21 -05:00
/********************************************************************
2020-06-12 18:31:14 -05:00
* Estimate the number of configuration clock cycles
2020-05-29 19:07:21 -05:00
* by traversing the linked - list and count the number of SRAM = 1 or BL = 1 & WL = 1 in it .
* We plus 1 additional config clock cycle here because we need to reset everything during the first clock cycle
2020-06-12 18:31:14 -05:00
* If we consider fast configuration , the number of clock cycles will be
2020-05-29 19:07:21 -05:00
* the number of non - zero data points in the fabric bitstream
* Note that this will not applicable to configuration chain ! ! !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-29 19:07:21 -05:00
size_t calculate_num_config_clock_cycles ( const e_config_protocol_type & sram_orgz_type ,
const bool & fast_configuration ,
2020-07-15 12:44:23 -05:00
const BitstreamManager & bitstream_manager ,
2020-05-29 19:07:21 -05:00
const FabricBitstream & fabric_bitstream ) {
2020-07-03 11:55:25 -05:00
size_t num_config_clock_cycles = 1 + fabric_bitstream . num_bits ( ) ;
2020-05-29 19:07:21 -05:00
/* Branch on the type of configuration protocol */
switch ( sram_orgz_type ) {
case CONFIG_MEM_STANDALONE :
2020-06-12 18:31:14 -05:00
/* We just need 1 clock cycle to load all the configuration bits
2020-05-30 00:22:01 -05:00
* since all the ports are exposed at the top - level
*/
num_config_clock_cycles = 2 ;
break ;
2020-05-29 19:07:21 -05:00
case CONFIG_MEM_SCAN_CHAIN :
2020-07-15 12:44:23 -05:00
/* For fast configuraiton, the bitstream size counts from the first bit '1' */
if ( true = = fast_configuration ) {
2020-07-15 12:56:11 -05:00
size_t full_num_config_clock_cycles = num_config_clock_cycles ;
2020-07-15 12:44:23 -05:00
size_t num_bits_to_skip = 0 ;
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
if ( true = = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ) {
break ;
}
num_bits_to_skip + + ;
}
2020-07-15 12:56:11 -05:00
num_config_clock_cycles = full_num_config_clock_cycles - num_bits_to_skip ;
VTR_LOG ( " Fast configuration reduces number of configuration clock cycles from %lu to %lu (compression_rate = %f%) \n " ,
full_num_config_clock_cycles ,
num_config_clock_cycles ,
100. * ( ( float ) num_config_clock_cycles / ( float ) full_num_config_clock_cycles - 1. ) ) ;
2020-07-15 12:44:23 -05:00
}
2020-05-29 19:07:21 -05:00
break ;
2020-05-30 21:04:44 -05:00
case CONFIG_MEM_MEMORY_BANK :
2020-05-29 19:07:21 -05:00
case CONFIG_MEM_FRAME_BASED : {
/* For fast configuration, we will skip all the zero data points */
if ( true = = fast_configuration ) {
2020-05-29 19:22:36 -05:00
size_t full_num_config_clock_cycles = num_config_clock_cycles ;
2020-05-29 19:07:21 -05:00
num_config_clock_cycles = 1 ;
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
if ( true = = fabric_bitstream . bit_din ( bit_id ) ) {
num_config_clock_cycles + + ;
}
}
2020-05-29 19:22:36 -05:00
VTR_LOG ( " Fast configuration reduces number of configuration clock cycles from %lu to %lu (compression_rate = %f%) \n " ,
full_num_config_clock_cycles ,
num_config_clock_cycles ,
100. * ( ( float ) num_config_clock_cycles / ( float ) full_num_config_clock_cycles - 1. ) ) ;
2020-05-29 19:07:21 -05:00
}
break ;
}
2020-06-12 18:31:14 -05:00
default :
2020-05-29 19:07:21 -05:00
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Invalid SRAM organization type! \n " ) ;
exit ( 1 ) ;
}
2020-05-29 19:22:36 -05:00
VTR_LOG ( " Will use %ld configuration clock cycles to top testbench \n " ,
num_config_clock_cycles ) ;
2020-05-29 19:07:21 -05:00
return num_config_clock_cycles ;
}
2020-02-26 22:30:21 -06:00
/********************************************************************
* Instanciate the input benchmark module
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
2020-06-12 18:31:14 -05:00
void print_verilog_top_testbench_benchmark_instance ( std : : fstream & fp ,
2020-02-26 22:30:21 -06:00
const std : : string & reference_verilog_top_name ,
2020-02-27 17:37:20 -06:00
const AtomContext & atom_ctx ,
2020-05-22 15:40:05 -05:00
const VprNetlistAnnotation & netlist_annotation ,
const bool & explicit_port_mapping ) {
2020-02-26 22:30:21 -06:00
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Benchmark is instanciated conditionally: only when a preprocessing flag is enable */
2020-06-12 18:31:14 -05:00
print_verilog_preprocessing_flag ( fp , std : : string ( AUTOCHECKED_SIMULATION_FLAG ) ) ;
2020-02-26 22:30:21 -06:00
print_verilog_comment ( fp , std : : string ( " ----- Reference Benchmark Instanication ------- " ) ) ;
2020-06-12 18:31:14 -05:00
/* Do NOT use explicit port mapping here:
2020-02-26 22:30:21 -06:00
* VPR added a prefix of " out_ " to the output ports of input benchmark
*/
2020-05-01 22:18:14 -05:00
std : : vector < std : : string > prefix_to_remove ;
prefix_to_remove . push_back ( std : : string ( VPR_BENCHMARK_OUT_PORT_PREFIX ) ) ;
prefix_to_remove . push_back ( std : : string ( OPENFPGA_BENCHMARK_OUT_PORT_PREFIX ) ) ;
2020-02-26 22:30:21 -06:00
print_verilog_testbench_benchmark_instance ( fp , reference_verilog_top_name ,
std : : string ( TOP_TESTBENCH_REFERENCE_INSTANCE_NAME ) ,
std : : string ( ) ,
std : : string ( ) ,
2020-05-01 22:18:14 -05:00
prefix_to_remove ,
2020-02-26 22:30:21 -06:00
std : : string ( TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX ) ,
2020-02-27 17:37:20 -06:00
atom_ctx , netlist_annotation ,
2020-05-22 15:40:05 -05:00
explicit_port_mapping ) ;
2020-02-26 22:30:21 -06:00
print_verilog_comment ( fp , std : : string ( " ----- End reference Benchmark Instanication ------- " ) ) ;
/* Add an empty line as splitter */
fp < < std : : endl ;
/* Condition ends for the benchmark instanciation */
print_verilog_endif ( fp ) ;
/* Add an empty line as splitter */
fp < < std : : endl ;
}
/********************************************************************
2020-06-12 18:31:14 -05:00
* Print tasks ( processes ) in Verilog format ,
* which is very useful in generating stimuli for each clock cycle
* This function is tuned for configuration - chain manipulation :
2020-02-26 22:30:21 -06:00
* During each programming cycle , we feed the input of scan chain with a memory bit
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_load_bitstream_task_configuration_chain ( std : : fstream & fp ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
BasicPort cc_head_port ( generate_configuration_chain_head_name ( ) , 1 ) ;
BasicPort cc_head_value ( generate_configuration_chain_head_name ( ) + std : : string ( " _val " ) , 1 ) ;
/* Add an empty line as splitter */
fp < < std : : endl ;
2020-06-12 18:31:14 -05:00
/* Feed the scan-chain input at each falling edge of programming clock
* It aims at avoid racing the programming clock ( scan - chain data changes at the rising edge ) .
2020-02-26 22:30:21 -06:00
*/
print_verilog_comment ( fp , std : : string ( " ----- Task: input values during a programming clock cycle ----- " ) ) ;
2020-05-27 19:40:45 -05:00
fp < < " task " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) < < " ; " < < std : : endl ;
2020-02-26 22:30:21 -06:00
fp < < generate_verilog_port ( VERILOG_PORT_INPUT , cc_head_value ) < < " ; " < < std : : endl ;
fp < < " \t begin " < < std : : endl ;
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) < < " ); " < < std : : endl ;
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-02-26 22:30:21 -06:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , cc_head_port ) ;
fp < < " = " ;
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , cc_head_value ) ;
fp < < " ; " < < std : : endl ;
fp < < " \t end " < < std : : endl ;
fp < < " endtask " < < std : : endl ;
/* Add an empty line as splitter */
fp < < std : : endl ;
}
/********************************************************************
2020-06-12 18:31:14 -05:00
* Print tasks ( processes ) in Verilog format ,
* which is very useful in generating stimuli for each clock cycle
* This function is tuned for memory bank manipulation :
2020-05-30 21:04:44 -05:00
* During each programming cycle , we feed
* - an address to the BL address port of top module
* - an address to the WL address port of top module
* - a data input to the din port of top module
2020-02-26 22:30:21 -06:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-30 21:04:44 -05:00
void print_verilog_top_testbench_load_bitstream_task_memory_bank ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
ModulePortId en_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_ENABLE_PORT_NAME ) ) ;
BasicPort en_port = module_manager . module_port ( top_module , en_port_id ) ;
ModulePortId bl_addr_port_id = module_manager . find_module_port ( top_module ,
2020-05-30 21:53:19 -05:00
std : : string ( DECODER_BL_ADDRESS_PORT_NAME ) ) ;
2020-05-30 21:04:44 -05:00
BasicPort bl_addr_port = module_manager . module_port ( top_module , bl_addr_port_id ) ;
BasicPort bl_addr_value = bl_addr_port ;
bl_addr_value . set_name ( std : : string ( MEMORY_BL_PORT_NAME ) + std : : string ( " _val " ) ) ;
ModulePortId wl_addr_port_id = module_manager . find_module_port ( top_module ,
2020-05-30 21:53:19 -05:00
std : : string ( DECODER_WL_ADDRESS_PORT_NAME ) ) ;
2020-05-30 21:04:44 -05:00
BasicPort wl_addr_port = module_manager . module_port ( top_module , wl_addr_port_id ) ;
BasicPort wl_addr_value = wl_addr_port ;
wl_addr_value . set_name ( std : : string ( MEMORY_WL_PORT_NAME ) + std : : string ( " _val " ) ) ;
ModulePortId din_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_DATA_IN_PORT_NAME ) ) ;
BasicPort din_port = module_manager . module_port ( top_module , din_port_id ) ;
BasicPort din_value = din_port ;
din_value . set_name ( std : : string ( DECODER_DATA_IN_PORT_NAME ) + std : : string ( " _val " ) ) ;
/* Add an empty line as splitter */
fp < < std : : endl ;
2020-06-12 18:31:14 -05:00
/* Feed the address and data input at each falling edge of programming clock
2020-05-30 21:04:44 -05:00
* As the enable signal is wired to the programming clock , we should synchronize
* address and data with the enable signal
*/
print_verilog_comment ( fp , std : : string ( " ----- Task: assign BL and WL address, and data values at rising edge of enable signal ----- " ) ) ;
fp < < " task " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) < < " ; " < < std : : endl ;
fp < < generate_verilog_port ( VERILOG_PORT_INPUT , bl_addr_value ) < < " ; " < < std : : endl ;
fp < < generate_verilog_port ( VERILOG_PORT_INPUT , wl_addr_value ) < < " ; " < < std : : endl ;
fp < < generate_verilog_port ( VERILOG_PORT_INPUT , din_value ) < < " ; " < < std : : endl ;
fp < < " \t begin " < < std : : endl ;
fp < < " \t \t @(posedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , en_port ) < < " ); " < < std : : endl ;
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-05-30 21:04:44 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , bl_addr_port ) ;
2020-06-12 18:31:14 -05:00
fp < < " = " ;
2020-05-30 21:04:44 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , bl_addr_value ) ;
fp < < " ; " < < std : : endl ;
fp < < std : : endl ;
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-05-30 21:04:44 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , wl_addr_port ) ;
2020-06-12 18:31:14 -05:00
fp < < " = " ;
2020-05-30 21:04:44 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , wl_addr_value ) ;
fp < < " ; " < < std : : endl ;
fp < < std : : endl ;
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-05-30 21:04:44 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , din_port ) ;
2020-06-12 18:31:14 -05:00
fp < < " = " ;
2020-05-30 21:04:44 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , din_value ) ;
fp < < " ; " < < std : : endl ;
fp < < std : : endl ;
fp < < " \t end " < < std : : endl ;
fp < < " endtask " < < std : : endl ;
/* Add an empty line as splitter */
fp < < std : : endl ;
}
2020-05-27 19:40:45 -05:00
/********************************************************************
2020-06-12 18:31:14 -05:00
* Print tasks ( processes ) in Verilog format ,
* which is very useful in generating stimuli for each clock cycle
* This function is tuned for frame - based memory manipulation :
2020-05-27 19:40:45 -05:00
* During each programming cycle , we feed
* - an address to the address port of top module
* - a data input to the din port of top module
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-27 19:40:45 -05:00
void print_verilog_top_testbench_load_bitstream_task_frame_decoder ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
2020-05-29 00:05:24 -05:00
ModulePortId en_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_ENABLE_PORT_NAME ) ) ;
BasicPort en_port = module_manager . module_port ( top_module , en_port_id ) ;
2020-05-27 19:40:45 -05:00
ModulePortId addr_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_ADDRESS_PORT_NAME ) ) ;
BasicPort addr_port = module_manager . module_port ( top_module , addr_port_id ) ;
BasicPort addr_value = addr_port ;
addr_value . set_name ( std : : string ( DECODER_ADDRESS_PORT_NAME ) + std : : string ( " _val " ) ) ;
ModulePortId din_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_DATA_IN_PORT_NAME ) ) ;
BasicPort din_port = module_manager . module_port ( top_module , din_port_id ) ;
BasicPort din_value = din_port ;
din_value . set_name ( std : : string ( DECODER_DATA_IN_PORT_NAME ) + std : : string ( " _val " ) ) ;
/* Add an empty line as splitter */
fp < < std : : endl ;
2020-06-12 18:31:14 -05:00
/* Feed the address and data input at each falling edge of programming clock
2020-05-27 19:40:45 -05:00
* As the enable signal is wired to the programming clock , we should synchronize
* address and data with the enable signal
*/
2020-05-29 00:05:24 -05:00
print_verilog_comment ( fp , std : : string ( " ----- Task: assign address and data values at rising edge of enable signal ----- " ) ) ;
2020-05-27 19:40:45 -05:00
fp < < " task " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) < < " ; " < < std : : endl ;
fp < < generate_verilog_port ( VERILOG_PORT_INPUT , addr_value ) < < " ; " < < std : : endl ;
fp < < generate_verilog_port ( VERILOG_PORT_INPUT , din_value ) < < " ; " < < std : : endl ;
fp < < " \t begin " < < std : : endl ;
2020-05-29 00:05:24 -05:00
fp < < " \t \t @(posedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , en_port ) < < " ); " < < std : : endl ;
2020-05-27 19:40:45 -05:00
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-05-27 19:47:27 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , addr_port ) ;
2020-06-12 18:31:14 -05:00
fp < < " = " ;
2020-05-27 19:47:27 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , addr_value ) ;
fp < < " ; " < < std : : endl ;
2020-05-27 19:40:45 -05:00
fp < < std : : endl ;
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-05-27 19:47:27 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , din_port ) ;
2020-06-12 18:31:14 -05:00
fp < < " = " ;
2020-05-27 19:47:27 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , din_value ) ;
fp < < " ; " < < std : : endl ;
2020-05-27 19:40:45 -05:00
fp < < std : : endl ;
2020-02-26 22:30:21 -06:00
fp < < " \t end " < < std : : endl ;
fp < < " endtask " < < std : : endl ;
/* Add an empty line as splitter */
fp < < std : : endl ;
}
/********************************************************************
2020-06-12 18:31:14 -05:00
* Print tasks , which is very useful in generating stimuli for each clock cycle
2020-02-26 22:30:21 -06:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_load_bitstream_task ( std : : fstream & fp ,
2020-05-27 19:40:45 -05:00
const e_config_protocol_type & sram_orgz_type ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
2020-02-26 22:30:21 -06:00
switch ( sram_orgz_type ) {
case CONFIG_MEM_STANDALONE :
2020-05-30 00:22:01 -05:00
/* No need to have a specific task. Loading is done in 1 clock cycle */
2020-02-26 22:30:21 -06:00
break ;
case CONFIG_MEM_SCAN_CHAIN :
print_verilog_top_testbench_load_bitstream_task_configuration_chain ( fp ) ;
break ;
case CONFIG_MEM_MEMORY_BANK :
2020-05-30 21:04:44 -05:00
print_verilog_top_testbench_load_bitstream_task_memory_bank ( fp ,
module_manager ,
top_module ) ;
2020-02-26 22:30:21 -06:00
break ;
2020-05-27 19:40:45 -05:00
case CONFIG_MEM_FRAME_BASED :
print_verilog_top_testbench_load_bitstream_task_frame_decoder ( fp ,
module_manager ,
top_module ) ;
2020-02-26 22:30:21 -06:00
break ;
default :
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Invalid type of SRAM organization! \n " ) ;
exit ( 1 ) ;
}
}
/********************************************************************
* Print generatic input stimuli for the top testbench
* include :
* 1. configuration done signal
* 2. programming clock
* 3. operating clock
* 4. programming reset signal
* 5. programming set signal
* 6. reset signal
* 7. set signal
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_generic_stimulus ( std : : fstream & fp ,
const size_t & num_config_clock_cycles ,
const float & prog_clock_period ,
const float & op_clock_period ,
const float & timescale ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , std : : string ( " ----- Number of clock cycles in configuration phase: " + std : : to_string ( num_config_clock_cycles ) + " ----- " ) ) ;
2020-02-26 22:30:21 -06:00
BasicPort config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
BasicPort op_clock_port ( std : : string ( TOP_TB_OP_CLOCK_PORT_NAME ) , 1 ) ;
BasicPort op_clock_register_port ( std : : string ( std : : string ( TOP_TB_OP_CLOCK_PORT_NAME ) + std : : string ( TOP_TB_CLOCK_REG_POSTFIX ) ) , 1 ) ;
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
BasicPort prog_clock_register_port ( std : : string ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) + std : : string ( TOP_TB_CLOCK_REG_POSTFIX ) ) , 1 ) ;
BasicPort prog_reset_port ( std : : string ( TOP_TB_PROG_RESET_PORT_NAME ) , 1 ) ;
BasicPort prog_set_port ( std : : string ( TOP_TB_PROG_SET_PORT_NAME ) , 1 ) ;
BasicPort reset_port ( std : : string ( TOP_TB_RESET_PORT_NAME ) , 1 ) ;
BasicPort set_port ( std : : string ( TOP_TB_SET_PORT_NAME ) , 1 ) ;
/* Generate stimuli waveform for configuration done signals */
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , " ----- Begin configuration done signal generation ----- " ) ;
print_verilog_pulse_stimuli ( fp , config_done_port ,
2020-02-26 22:30:21 -06:00
0 , /* Initial value */
2020-06-12 18:31:14 -05:00
num_config_clock_cycles * prog_clock_period / timescale , 0 ) ;
print_verilog_comment ( fp , " ----- End configuration done signal generation ----- " ) ;
2020-02-26 22:30:21 -06:00
fp < < std : : endl ;
/* Generate stimuli waveform for programming clock signals */
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , " ----- Begin raw programming clock signal generation ----- " ) ;
print_verilog_clock_stimuli ( fp , prog_clock_register_port ,
2020-02-26 22:30:21 -06:00
0 , /* Initial value */
0.5 * prog_clock_period / timescale ,
2020-06-12 18:31:14 -05:00
std : : string ( ) ) ;
print_verilog_comment ( fp , " ----- End raw programming clock signal generation ----- " ) ;
2020-02-26 22:30:21 -06:00
fp < < std : : endl ;
/* Programming clock should be only enabled during programming phase.
* When configuration is done ( config_done is enabled ) , programming clock should be always zero .
*/
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , std : : string ( " ----- Actual programming clock is triggered only when " + config_done_port . get_name ( ) + " and " + prog_reset_port . get_name ( ) + " are disabled ----- " ) ) ;
2020-02-26 22:30:21 -06:00
fp < < " \t assign " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) ;
fp < < " = " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_register_port ) ;
fp < < " & (~ " < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) < < " ) " ;
fp < < " & (~ " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_reset_port ) < < " ) " ;
fp < < " ; " < < std : : endl ;
fp < < std : : endl ;
/* Generate stimuli waveform for operating clock signals */
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , " ----- Begin raw operating clock signal generation ----- " ) ;
print_verilog_clock_stimuli ( fp , op_clock_register_port ,
2020-02-26 22:30:21 -06:00
0 , /* Initial value */
0.5 * op_clock_period / timescale ,
2020-06-12 18:31:14 -05:00
std : : string ( " ~ " + reset_port . get_name ( ) ) ) ;
print_verilog_comment ( fp , " ----- End raw operating clock signal generation ----- " ) ;
2020-02-26 22:30:21 -06:00
/* Operation clock should be enabled after programming phase finishes.
* Before configuration is done ( config_done is enabled ) , operation clock should be always zero .
*/
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , std : : string ( " ----- Actual operating clock is triggered only when " + config_done_port . get_name ( ) + " is enabled ----- " ) ) ;
2020-02-26 22:30:21 -06:00
fp < < " \t assign " < < generate_verilog_port ( VERILOG_PORT_CONKT , op_clock_port ) ;
fp < < " = " < < generate_verilog_port ( VERILOG_PORT_CONKT , op_clock_register_port ) ;
fp < < " & " < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) ;
fp < < " ; " < < std : : endl ;
fp < < std : : endl ;
2020-06-12 18:31:14 -05:00
/* Reset signal for configuration circuit:
* only enable during the first clock cycle in programming phase
2020-02-26 22:30:21 -06:00
*/
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , " ----- Begin programming reset signal generation ----- " ) ;
print_verilog_pulse_stimuli ( fp , prog_reset_port ,
2020-02-26 22:30:21 -06:00
1 , /* Initial value */
2020-06-12 18:31:14 -05:00
prog_clock_period / timescale , 0 ) ;
print_verilog_comment ( fp , " ----- End programming reset signal generation ----- " ) ;
2020-02-26 22:30:21 -06:00
fp < < std : : endl ;
/* Programming set signal for configuration circuit : always disabled */
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , " ----- Begin programming set signal generation: always disabled ----- " ) ;
print_verilog_pulse_stimuli ( fp , prog_set_port ,
2020-02-26 22:30:21 -06:00
0 , /* Initial value */
2020-06-12 18:31:14 -05:00
prog_clock_period / timescale , 0 ) ;
print_verilog_comment ( fp , " ----- End programming set signal generation: always disabled ----- " ) ;
2020-02-26 22:30:21 -06:00
fp < < std : : endl ;
/* Operating reset signals: only enabled during the first clock cycle in operation phase */
std : : vector < float > reset_pulse_widths ;
reset_pulse_widths . push_back ( op_clock_period / timescale ) ;
reset_pulse_widths . push_back ( 2 * op_clock_period / timescale ) ;
std : : vector < size_t > reset_flip_values ;
reset_flip_values . push_back ( 1 ) ;
reset_flip_values . push_back ( 0 ) ;
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , " ----- Begin operating reset signal generation ----- " ) ;
2020-02-26 22:30:21 -06:00
print_verilog_comment ( fp , " ----- Reset signal is enabled until the first clock cycle in operation phase ----- " ) ;
print_verilog_pulse_stimuli ( fp , reset_port ,
1 ,
reset_pulse_widths ,
reset_flip_values ,
config_done_port . get_name ( ) ) ;
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , " ----- End operating reset signal generation ----- " ) ;
2020-02-26 22:30:21 -06:00
/* Operating set signal for configuration circuit : always disabled */
2020-06-12 18:31:14 -05:00
print_verilog_comment ( fp , " ----- Begin operating set signal generation: always disabled ----- " ) ;
print_verilog_pulse_stimuli ( fp , set_port ,
2020-02-26 22:30:21 -06:00
0 , /* Initial value */
2020-06-12 18:31:14 -05:00
op_clock_period / timescale , 0 ) ;
print_verilog_comment ( fp , " ----- End operating set signal generation: always disabled ----- " ) ;
2020-02-26 22:30:21 -06:00
fp < < std : : endl ;
}
/********************************************************************
2020-06-12 18:31:14 -05:00
* Print stimulus for a FPGA fabric with a flatten memory ( standalone ) configuration protocol
2020-05-30 00:22:01 -05:00
* We will load the bitstream in the second clock cycle , right after the first reset cycle
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-30 00:22:01 -05:00
void print_verilog_top_testbench_vanilla_bitstream ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ,
const BitstreamManager & bitstream_manager ,
const FabricBitstream & fabric_bitstream ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Find Bit-Line and Word-Line port */
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
/* Find Bit-Line and Word-Line port */
ModulePortId bl_port_id = module_manager . find_module_port ( top_module , std : : string ( MEMORY_BL_PORT_NAME ) ) ;
BasicPort bl_port = module_manager . module_port ( top_module , bl_port_id ) ;
ModulePortId wl_port_id = module_manager . find_module_port ( top_module , std : : string ( MEMORY_WL_PORT_NAME ) ) ;
BasicPort wl_port = module_manager . module_port ( top_module , wl_port_id ) ;
/* Initial value should be the first configuration bits
2020-06-12 18:31:14 -05:00
* In the rest of programming cycles ,
2020-05-30 00:22:01 -05:00
* configuration bits are fed at the falling edge of programming clock .
2020-06-12 18:31:14 -05:00
* We do not care the value of scan_chain head during the first programming cycle
2020-05-30 00:22:01 -05:00
* It is reset anyway
*/
std : : vector < size_t > initial_bl_values ( bl_port . get_width ( ) , 0 ) ;
std : : vector < size_t > initial_wl_values ( wl_port . get_width ( ) , 0 ) ;
print_verilog_comment ( fp , " ----- Begin bitstream loading during configuration phase ----- " ) ;
fp < < " initial " < < std : : endl ;
fp < < " \t begin " < < std : : endl ;
print_verilog_comment ( fp , " ----- Configuration chain default input ----- " ) ;
fp < < " \t \t " ;
fp < < generate_verilog_port_constant_values ( bl_port , initial_bl_values ) ;
2020-05-30 13:16:41 -05:00
fp < < " ; " < < std : : endl ;
2020-05-30 00:22:01 -05:00
fp < < " \t \t " ;
fp < < generate_verilog_port_constant_values ( wl_port , initial_wl_values ) ;
2020-05-30 13:16:41 -05:00
fp < < " ; " < < std : : endl ;
2020-05-30 00:22:01 -05:00
fp < < std : : endl ;
2020-05-30 13:16:41 -05:00
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) < < " ) begin " < < std : : endl ;
2020-05-30 00:22:01 -05:00
/* Enable all the WLs */
std : : vector < size_t > enabled_wl_values ( wl_port . get_width ( ) , 1 ) ;
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-05-30 00:22:01 -05:00
fp < < generate_verilog_port_constant_values ( wl_port , enabled_wl_values ) ;
2020-05-30 13:16:41 -05:00
fp < < " ; " < < std : : endl ;
2020-05-30 00:22:01 -05:00
size_t ibit = 0 ;
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
BasicPort cur_bl_port ( bl_port ) ;
cur_bl_port . set_width ( ibit , ibit ) ;
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-05-30 00:22:01 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , cur_bl_port ) ;
2020-06-12 18:31:14 -05:00
fp < < " = " ;
2020-05-30 00:22:01 -05:00
fp < < " 1'b " < < ( size_t ) bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ;
fp < < " ; " < < std : : endl ;
ibit + + ;
}
2020-05-30 13:16:41 -05:00
fp < < " \t \t end " < < std : : endl ;
2020-05-30 00:22:01 -05:00
/* Disable all the WLs */
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) < < " ); " < < std : : endl ;
2020-05-30 13:16:41 -05:00
2020-06-12 18:31:14 -05:00
fp < < " \t \t \t " ;
2020-05-30 13:16:41 -05:00
fp < < generate_verilog_port_constant_values ( wl_port , initial_wl_values ) ;
fp < < " ; " < < std : : endl ;
2020-05-30 00:22:01 -05:00
/* Raise the flag of configuration done when bitstream loading is complete */
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) < < " ); " < < std : : endl ;
2020-06-12 18:31:14 -05:00
2020-05-30 00:22:01 -05:00
BasicPort config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
fp < < " \t \t \t " ;
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) ;
fp < < " <= " ;
std : : vector < size_t > config_done_enable_values ( config_done_port . get_width ( ) , 1 ) ;
fp < < generate_verilog_constant_values ( config_done_enable_values ) ;
fp < < " ; " < < std : : endl ;
fp < < " \t end " < < std : : endl ;
print_verilog_comment ( fp , " ----- End bitstream loading during configuration phase ----- " ) ;
}
2020-02-26 22:30:21 -06:00
/********************************************************************
2020-06-12 18:31:14 -05:00
* Print stimulus for a FPGA fabric with a configuration chain protocol
2020-02-26 22:30:21 -06:00
* where configuration bits are programming in serial ( one by one )
* Task list :
* 1. For clock signal , we should create voltage waveforms for two types of clock signals :
* a . operation clock
2020-06-12 18:31:14 -05:00
* b . programming clock
* 2. For Set / Reset , we reset the chip after programming phase ends
2020-02-26 22:30:21 -06:00
* and before operation phase starts
2020-06-12 18:31:14 -05:00
* 3. For input / output clb nets ( mapped to I / O grids ) ,
* we should create voltage waveforms only after programming phase
2020-02-26 22:30:21 -06:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_configuration_chain_bitstream ( std : : fstream & fp ,
2020-07-15 12:44:23 -05:00
const bool & fast_configuration ,
2020-02-26 22:30:21 -06:00
const BitstreamManager & bitstream_manager ,
2020-05-27 16:53:40 -05:00
const FabricBitstream & fabric_bitstream ) {
2020-02-26 22:30:21 -06:00
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Initial value should be the first configuration bits
2020-06-12 18:31:14 -05:00
* In the rest of programming cycles ,
2020-02-26 22:30:21 -06:00
* configuration bits are fed at the falling edge of programming clock .
2020-06-12 18:31:14 -05:00
* We do not care the value of scan_chain head during the first programming cycle
2020-02-26 22:30:21 -06:00
* It is reset anyway
*/
BasicPort config_chain_head_port ( generate_configuration_chain_head_name ( ) , 1 ) ;
std : : vector < size_t > initial_values ( config_chain_head_port . get_width ( ) , 0 ) ;
print_verilog_comment ( fp , " ----- Begin bitstream loading during configuration phase ----- " ) ;
fp < < " initial " < < std : : endl ;
fp < < " \t begin " < < std : : endl ;
print_verilog_comment ( fp , " ----- Configuration chain default input ----- " ) ;
fp < < " \t \t " ;
fp < < generate_verilog_port_constant_values ( config_chain_head_port , initial_values ) ;
fp < < " ; " ;
fp < < std : : endl ;
2020-07-15 12:44:23 -05:00
/* Attention: when the fast configuration is enabled, we will start from the first bit '1'
* This requires a reset signal ( as we forced in the first clock cycle )
2020-02-26 22:30:21 -06:00
*/
2020-07-15 18:52:41 -05:00
bool start_config = false ;
2020-05-27 16:53:40 -05:00
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
2020-07-15 18:52:41 -05:00
if ( ( false = = start_config )
& & ( true = = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ) ) {
start_config = true ;
2020-07-15 12:44:23 -05:00
}
/* In fast configuration mode, we do not output anything
* until we have to ( the first bit ' 1 ' detected )
*/
if ( ( true = = fast_configuration )
2020-07-15 18:52:41 -05:00
& & ( false = = start_config ) ) {
2020-07-15 12:44:23 -05:00
continue ;
}
2020-05-27 19:40:45 -05:00
fp < < " \t \t " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) ;
2020-05-27 16:53:40 -05:00
fp < < " (1'b " < < ( size_t ) bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) < < " ); " < < std : : endl ;
2020-02-26 22:30:21 -06:00
}
/* Raise the flag of configuration done when bitstream loading is complete */
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) < < " ); " < < std : : endl ;
2020-06-12 18:31:14 -05:00
2020-02-26 22:30:21 -06:00
BasicPort config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
fp < < " \t \t \t " ;
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) ;
fp < < " <= " ;
std : : vector < size_t > config_done_enable_values ( config_done_port . get_width ( ) , 1 ) ;
fp < < generate_verilog_constant_values ( config_done_enable_values ) ;
fp < < " ; " < < std : : endl ;
fp < < " \t end " < < std : : endl ;
print_verilog_comment ( fp , " ----- End bitstream loading during configuration phase ----- " ) ;
}
2020-05-30 21:04:44 -05:00
/********************************************************************
2020-06-12 18:31:14 -05:00
* Print stimulus for a FPGA fabric with a memory bank configuration protocol
2020-05-30 21:04:44 -05:00
* where configuration bits are programming in serial ( one by one )
*
* We will use the programming task function created before
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-30 21:04:44 -05:00
void print_verilog_top_testbench_memory_bank_bitstream ( std : : fstream & fp ,
const bool & fast_configuration ,
const ModuleManager & module_manager ,
const ModuleId & top_module ,
const FabricBitstream & fabric_bitstream ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
2020-06-12 18:31:14 -05:00
/* Feed addresss and data input pair one by one
2020-05-30 21:04:44 -05:00
* Note : the first cycle is reserved for programming reset
2020-06-12 18:31:14 -05:00
* We should give dummy values
2020-05-30 21:04:44 -05:00
*/
ModulePortId bl_addr_port_id = module_manager . find_module_port ( top_module ,
2020-05-30 21:53:19 -05:00
std : : string ( DECODER_BL_ADDRESS_PORT_NAME ) ) ;
2020-05-30 21:04:44 -05:00
BasicPort bl_addr_port = module_manager . module_port ( top_module , bl_addr_port_id ) ;
std : : vector < size_t > initial_bl_addr_values ( bl_addr_port . get_width ( ) , 0 ) ;
ModulePortId wl_addr_port_id = module_manager . find_module_port ( top_module ,
2020-05-30 21:53:19 -05:00
std : : string ( DECODER_WL_ADDRESS_PORT_NAME ) ) ;
2020-05-30 21:04:44 -05:00
BasicPort wl_addr_port = module_manager . module_port ( top_module , wl_addr_port_id ) ;
std : : vector < size_t > initial_wl_addr_values ( wl_addr_port . get_width ( ) , 0 ) ;
ModulePortId din_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_DATA_IN_PORT_NAME ) ) ;
BasicPort din_port = module_manager . module_port ( top_module , din_port_id ) ;
std : : vector < size_t > initial_din_values ( din_port . get_width ( ) , 0 ) ;
print_verilog_comment ( fp , " ----- Begin bitstream loading during configuration phase ----- " ) ;
fp < < " initial " < < std : : endl ;
fp < < " \t begin " < < std : : endl ;
print_verilog_comment ( fp , " ----- Address port default input ----- " ) ;
fp < < " \t \t " ;
fp < < generate_verilog_port_constant_values ( bl_addr_port , initial_bl_addr_values ) ;
2020-05-30 21:53:19 -05:00
fp < < " ; " ;
fp < < std : : endl ;
2020-05-30 21:04:44 -05:00
fp < < generate_verilog_port_constant_values ( wl_addr_port , initial_wl_addr_values ) ;
fp < < " ; " ;
2020-05-30 21:53:19 -05:00
fp < < std : : endl ;
2020-05-30 21:04:44 -05:00
print_verilog_comment ( fp , " ----- Data-input port default input ----- " ) ;
fp < < " \t \t " ;
fp < < generate_verilog_port_constant_values ( din_port , initial_din_values ) ;
fp < < " ; " ;
fp < < std : : endl ;
/* Attention: the configuration chain protcol requires the last configuration bit is fed first
2020-06-12 18:31:14 -05:00
* We will visit the fabric bitstream in a reverse way
2020-02-26 22:30:21 -06:00
*/
2020-05-30 21:04:44 -05:00
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
/* When fast configuration is enabled, we skip zero data_in values */
if ( ( true = = fast_configuration )
& & ( false = = fabric_bitstream . bit_din ( bit_id ) ) ) {
continue ;
}
fp < < " \t \t " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) ;
fp < < " ( " < < bl_addr_port . get_width ( ) < < " 'b " ;
VTR_ASSERT ( bl_addr_port . get_width ( ) = = fabric_bitstream . bit_bl_address ( bit_id ) . size ( ) ) ;
2020-07-02 16:56:50 -05:00
for ( const char & addr_bit : fabric_bitstream . bit_bl_address ( bit_id ) ) {
2020-06-12 18:31:14 -05:00
fp < < addr_bit ;
2020-05-30 21:04:44 -05:00
}
fp < < " , " ;
fp < < wl_addr_port . get_width ( ) < < " 'b " ;
VTR_ASSERT ( wl_addr_port . get_width ( ) = = fabric_bitstream . bit_wl_address ( bit_id ) . size ( ) ) ;
2020-07-02 16:56:50 -05:00
for ( const char & addr_bit : fabric_bitstream . bit_wl_address ( bit_id ) ) {
2020-06-12 18:31:14 -05:00
fp < < addr_bit ;
2020-05-30 21:04:44 -05:00
}
fp < < " , " ;
fp < < " 1'b " ;
if ( true = = fabric_bitstream . bit_din ( bit_id ) ) {
fp < < " 1 " ;
} else {
VTR_ASSERT ( false = = fabric_bitstream . bit_din ( bit_id ) ) ;
fp < < " 0 " ;
}
fp < < " ); " < < std : : endl ;
2020-02-26 22:30:21 -06:00
}
/* Raise the flag of configuration done when bitstream loading is complete */
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) < < " ); " < < std : : endl ;
2020-06-12 18:31:14 -05:00
2020-02-26 22:30:21 -06:00
BasicPort config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
fp < < " \t \t \t " ;
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) ;
fp < < " <= " ;
std : : vector < size_t > config_done_enable_values ( config_done_port . get_width ( ) , 1 ) ;
fp < < generate_verilog_constant_values ( config_done_enable_values ) ;
fp < < " ; " < < std : : endl ;
fp < < " \t end " < < std : : endl ;
print_verilog_comment ( fp , " ----- End bitstream loading during configuration phase ----- " ) ;
}
/********************************************************************
2020-06-12 18:31:14 -05:00
* Print stimulus for a FPGA fabric with a frame - based configuration protocol
2020-05-27 19:40:45 -05:00
* where configuration bits are programming in serial ( one by one )
*
* We will use the programming task function created before
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-05-27 19:40:45 -05:00
void print_verilog_top_testbench_frame_decoder_bitstream ( std : : fstream & fp ,
2020-05-29 19:07:21 -05:00
const bool & fast_configuration ,
2020-05-27 19:40:45 -05:00
const ModuleManager & module_manager ,
const ModuleId & top_module ,
const FabricBitstream & fabric_bitstream ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
2020-06-12 18:31:14 -05:00
/* Feed addresss and data input pair one by one
2020-05-27 19:40:45 -05:00
* Note : the first cycle is reserved for programming reset
2020-06-12 18:31:14 -05:00
* We should give dummy values
2020-05-27 19:40:45 -05:00
*/
ModulePortId addr_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_ADDRESS_PORT_NAME ) ) ;
BasicPort addr_port = module_manager . module_port ( top_module , addr_port_id ) ;
std : : vector < size_t > initial_addr_values ( addr_port . get_width ( ) , 0 ) ;
ModulePortId din_port_id = module_manager . find_module_port ( top_module ,
std : : string ( DECODER_DATA_IN_PORT_NAME ) ) ;
BasicPort din_port = module_manager . module_port ( top_module , din_port_id ) ;
std : : vector < size_t > initial_din_values ( din_port . get_width ( ) , 0 ) ;
print_verilog_comment ( fp , " ----- Begin bitstream loading during configuration phase ----- " ) ;
fp < < " initial " < < std : : endl ;
fp < < " \t begin " < < std : : endl ;
print_verilog_comment ( fp , " ----- Address port default input ----- " ) ;
fp < < " \t \t " ;
fp < < generate_verilog_port_constant_values ( addr_port , initial_addr_values ) ;
fp < < " ; " ;
2020-05-30 21:53:19 -05:00
fp < < std : : endl ;
2020-05-27 19:40:45 -05:00
print_verilog_comment ( fp , " ----- Data-input port default input ----- " ) ;
fp < < " \t \t " ;
fp < < generate_verilog_port_constant_values ( din_port , initial_din_values ) ;
fp < < " ; " ;
fp < < std : : endl ;
/* Attention: the configuration chain protcol requires the last configuration bit is fed first
2020-06-12 18:31:14 -05:00
* We will visit the fabric bitstream in a reverse way
2020-05-27 19:40:45 -05:00
*/
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
2020-05-29 19:07:21 -05:00
/* When fast configuration is enabled, we skip zero data_in values */
if ( ( true = = fast_configuration )
& & ( false = = fabric_bitstream . bit_din ( bit_id ) ) ) {
continue ;
}
2020-05-27 19:40:45 -05:00
fp < < " \t \t " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) ;
fp < < " ( " < < addr_port . get_width ( ) < < " 'b " ;
VTR_ASSERT ( addr_port . get_width ( ) = = fabric_bitstream . bit_address ( bit_id ) . size ( ) ) ;
2020-07-02 16:56:50 -05:00
for ( const char & addr_bit : fabric_bitstream . bit_address ( bit_id ) ) {
2020-06-12 18:31:14 -05:00
fp < < addr_bit ;
2020-05-27 19:40:45 -05:00
}
fp < < " , " ;
fp < < " 1'b " ;
if ( true = = fabric_bitstream . bit_din ( bit_id ) ) {
fp < < " 1 " ;
} else {
VTR_ASSERT ( false = = fabric_bitstream . bit_din ( bit_id ) ) ;
fp < < " 0 " ;
}
fp < < " ); " < < std : : endl ;
}
2020-05-29 00:05:24 -05:00
/* Disable the address and din */
fp < < " \t \t " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) ;
fp < < " ( " < < addr_port . get_width ( ) < < " 'b " ;
std : : vector < size_t > all_zero_addr ( addr_port . get_width ( ) , 0 ) ;
for ( const size_t & addr_bit : all_zero_addr ) {
2020-06-12 18:31:14 -05:00
fp < < addr_bit ;
2020-05-29 00:05:24 -05:00
}
fp < < " , " ;
fp < < " 1'b0 " ;
fp < < " ); " < < std : : endl ;
2020-05-27 19:40:45 -05:00
/* Raise the flag of configuration done when bitstream loading is complete */
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) < < " ); " < < std : : endl ;
2020-06-12 18:31:14 -05:00
2020-05-27 19:40:45 -05:00
BasicPort config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
fp < < " \t \t \t " ;
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) ;
fp < < " <= " ;
std : : vector < size_t > config_done_enable_values ( config_done_port . get_width ( ) , 1 ) ;
fp < < generate_verilog_constant_values ( config_done_enable_values ) ;
fp < < " ; " < < std : : endl ;
fp < < " \t end " < < std : : endl ;
print_verilog_comment ( fp , " ----- End bitstream loading during configuration phase ----- " ) ;
}
2020-02-26 22:30:21 -06:00
/********************************************************************
2020-06-12 18:31:14 -05:00
* Generate the stimuli for the top - level testbench
2020-02-26 22:30:21 -06:00
* The simulation consists of two phases : configuration phase and operation phase
2020-06-12 18:31:14 -05:00
* Configuration bits are loaded serially .
2020-02-26 22:30:21 -06:00
* This is actually what we do for a physical FPGA
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-12 18:31:14 -05:00
static
2020-02-26 22:30:21 -06:00
void print_verilog_top_testbench_bitstream ( std : : fstream & fp ,
const e_config_protocol_type & sram_orgz_type ,
2020-05-29 19:07:21 -05:00
const bool & fast_configuration ,
2020-05-27 19:40:45 -05:00
const ModuleManager & module_manager ,
const ModuleId & top_module ,
2020-02-26 22:30:21 -06:00
const BitstreamManager & bitstream_manager ,
2020-05-27 16:53:40 -05:00
const FabricBitstream & fabric_bitstream ) {
2020-02-26 22:30:21 -06:00
/* Branch on the type of configuration protocol */
switch ( sram_orgz_type ) {
case CONFIG_MEM_STANDALONE :
2020-06-12 18:31:14 -05:00
print_verilog_top_testbench_vanilla_bitstream ( fp ,
2020-05-30 00:22:01 -05:00
module_manager , top_module ,
bitstream_manager , fabric_bitstream ) ;
2020-02-26 22:30:21 -06:00
break ;
case CONFIG_MEM_SCAN_CHAIN :
2020-07-15 12:44:23 -05:00
print_verilog_top_testbench_configuration_chain_bitstream ( fp , fast_configuration ,
bitstream_manager , fabric_bitstream ) ;
2020-02-26 22:30:21 -06:00
break ;
case CONFIG_MEM_MEMORY_BANK :
2020-05-30 21:04:44 -05:00
print_verilog_top_testbench_memory_bank_bitstream ( fp , fast_configuration ,
module_manager , top_module ,
fabric_bitstream ) ;
2020-02-26 22:30:21 -06:00
break ;
2020-05-27 19:40:45 -05:00
case CONFIG_MEM_FRAME_BASED :
2020-05-29 19:07:21 -05:00
print_verilog_top_testbench_frame_decoder_bitstream ( fp , fast_configuration ,
2020-05-27 19:40:45 -05:00
module_manager , top_module ,
fabric_bitstream ) ;
break ;
2020-06-12 18:31:14 -05:00
default :
2020-02-26 22:30:21 -06:00
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Invalid SRAM organization type! \n " ) ;
exit ( 1 ) ;
}
}
/********************************************************************
2020-06-12 18:31:14 -05:00
* The top - level function to generate a testbench , in order to verify :
* 1. Configuration phase of the FPGA fabric , where the bitstream is
2020-02-26 22:30:21 -06:00
* loaded to the configuration protocol of the FPGA fabric
* 2. Operating phase of the FPGA fabric , where input stimuli are
* fed to the I / Os of the FPGA fabric
* + - - - - - - - - - - +
* | FPGA | + - - - - - - - - - - - - +
* + - - - - - > | Fabric | - - - - - - > | |
* | | | | |
* | + - - - - - - - - - - + | |
2020-06-12 18:31:14 -05:00
* | | Output |
2020-02-26 22:30:21 -06:00
* random_input_vectors - - - - - + | Vector | - - - - > Functional correct ?
2020-06-12 18:31:14 -05:00
* | | Comparator |
2020-02-26 22:30:21 -06:00
* | + - - - - - - - - - - - + | |
* | | Input | | |
* + - - - - - > | Benchmark | - - - - - > | |
* + - - - - - - - - - - - + + - - - - - - - - - - - - +
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void print_verilog_top_testbench ( const ModuleManager & module_manager ,
const BitstreamManager & bitstream_manager ,
2020-05-27 16:53:40 -05:00
const FabricBitstream & fabric_bitstream ,
2020-02-26 22:30:21 -06:00
const e_config_protocol_type & sram_orgz_type ,
const CircuitLibrary & circuit_lib ,
const std : : vector < CircuitPortId > & global_ports ,
const AtomContext & atom_ctx ,
2020-06-12 18:31:14 -05:00
const PlacementContext & place_ctx ,
2020-02-26 22:30:21 -06:00
const IoLocationMap & io_location_map ,
2020-02-27 17:37:20 -06:00
const VprNetlistAnnotation & netlist_annotation ,
2020-02-26 22:30:21 -06:00
const std : : string & circuit_name ,
const std : : string & verilog_fname ,
2020-05-22 15:40:05 -05:00
const SimulationSetting & simulation_parameters ,
2020-05-29 19:07:21 -05:00
const bool & fast_configuration ,
2020-05-22 15:40:05 -05:00
const bool & explicit_port_mapping ) {
2020-02-26 22:30:21 -06:00
std : : string timer_message = std : : string ( " Write autocheck testbench for FPGA top-level Verilog netlist for ' " ) + circuit_name + std : : string ( " ' " ) ;
/* Start time count */
vtr : : ScopedStartFinishTimer timer ( timer_message ) ;
/* Create the file stream */
std : : fstream fp ;
fp . open ( verilog_fname , std : : fstream : : out | std : : fstream : : trunc ) ;
/* Validate the file stream */
check_file_stream ( verilog_fname . c_str ( ) , fp ) ;
/* Generate a brief description on the Verilog file*/
std : : string title = std : : string ( " FPGA Verilog Testbench for Top-level netlist of Design: " ) + circuit_name ;
2020-06-12 18:31:14 -05:00
print_verilog_file_header ( fp , title ) ;
2020-02-26 22:30:21 -06:00
/* Find the top_module */
ModuleId top_module = module_manager . find_module ( generate_fpga_top_module_name ( ) ) ;
VTR_ASSERT ( true = = module_manager . valid_module_id ( top_module ) ) ;
/* Preparation: find all the clock ports */
2020-02-27 17:51:55 -06:00
std : : vector < std : : string > clock_port_names = find_atom_netlist_clock_port_names ( atom_ctx . nlist , netlist_annotation ) ;
2020-02-26 22:30:21 -06:00
/* Start of testbench */
2020-06-12 18:31:14 -05:00
print_verilog_top_testbench_ports ( fp , module_manager , top_module ,
2020-02-27 17:37:20 -06:00
atom_ctx , netlist_annotation , clock_port_names ,
2020-02-26 22:30:21 -06:00
sram_orgz_type , circuit_name ) ;
/* Find the clock period */
float prog_clock_period = ( 1. / simulation_parameters . programming_clock_frequency ( ) ) ;
float op_clock_period = ( 1. / simulation_parameters . operating_clock_frequency ( ) ) ;
2020-06-12 18:31:14 -05:00
/* Estimate the number of configuration clock cycles */
2020-05-29 19:07:21 -05:00
size_t num_config_clock_cycles = calculate_num_config_clock_cycles ( sram_orgz_type ,
fast_configuration ,
2020-07-15 12:44:23 -05:00
bitstream_manager ,
2020-05-29 19:07:21 -05:00
fabric_bitstream ) ;
2020-02-26 22:30:21 -06:00
/* Generate stimuli for general control signals */
print_verilog_top_testbench_generic_stimulus ( fp ,
num_config_clock_cycles ,
prog_clock_period ,
op_clock_period ,
VERILOG_SIM_TIMESCALE ) ;
/* Generate stimuli for global ports or connect them to existed signals */
print_verilog_top_testbench_global_ports_stimuli ( fp ,
module_manager , top_module ,
circuit_lib , global_ports ) ;
/* Instanciate FPGA top-level module */
2020-06-12 18:31:14 -05:00
print_verilog_testbench_fpga_instance ( fp , module_manager , top_module ,
2020-05-22 15:40:05 -05:00
std : : string ( TOP_TESTBENCH_FPGA_INSTANCE_NAME ) ,
2020-06-12 18:31:14 -05:00
explicit_port_mapping ) ;
2020-02-26 22:30:21 -06:00
/* Connect I/Os to benchmark I/Os or constant driver */
print_verilog_testbench_connect_fpga_ios ( fp , module_manager , top_module ,
2020-02-27 17:37:20 -06:00
atom_ctx , place_ctx , io_location_map ,
2020-06-12 18:31:14 -05:00
netlist_annotation ,
std : : string ( ) ,
std : : string ( TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX ) ,
2020-02-26 22:30:21 -06:00
( size_t ) VERILOG_DEFAULT_SIGNAL_INIT_VALUE ) ;
/* Instanciate input benchmark */
2020-06-12 18:31:14 -05:00
print_verilog_top_testbench_benchmark_instance ( fp ,
2020-02-26 22:30:21 -06:00
circuit_name ,
2020-02-27 17:37:20 -06:00
atom_ctx ,
2020-05-22 15:40:05 -05:00
netlist_annotation ,
2020-06-12 18:31:14 -05:00
explicit_port_mapping ) ;
2020-02-26 22:30:21 -06:00
/* Print tasks used for loading bitstreams */
2020-05-27 19:40:45 -05:00
print_verilog_top_testbench_load_bitstream_task ( fp ,
sram_orgz_type ,
module_manager , top_module ) ;
2020-02-26 22:30:21 -06:00
/* load bitstream to FPGA fabric in a configuration phase */
print_verilog_top_testbench_bitstream ( fp , sram_orgz_type ,
2020-05-29 19:07:21 -05:00
fast_configuration ,
2020-05-27 19:40:45 -05:00
module_manager , top_module ,
2020-02-26 22:30:21 -06:00
bitstream_manager , fabric_bitstream ) ;
/* Add stimuli for reset, set, clock and iopad signals */
2020-06-12 18:31:14 -05:00
print_verilog_testbench_random_stimuli ( fp , atom_ctx ,
netlist_annotation ,
clock_port_names ,
2020-02-26 22:30:21 -06:00
std : : string ( TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX ) ,
BasicPort ( std : : string ( TOP_TB_OP_CLOCK_PORT_NAME ) , 1 ) ) ;
/* Add output autocheck */
2020-06-12 18:31:14 -05:00
print_verilog_testbench_check ( fp ,
2020-02-26 22:30:21 -06:00
std : : string ( AUTOCHECKED_SIMULATION_FLAG ) ,
std : : string ( TOP_TESTBENCH_SIM_START_PORT_NAME ) ,
std : : string ( TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX ) ,
std : : string ( TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX ) ,
std : : string ( TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX ) ,
std : : string ( TOP_TESTBENCH_ERROR_COUNTER ) ,
2020-02-27 17:37:20 -06:00
atom_ctx ,
2020-06-12 18:31:14 -05:00
netlist_annotation ,
2020-02-27 17:37:20 -06:00
clock_port_names ,
std : : string ( TOP_TB_OP_CLOCK_PORT_NAME ) ) ;
2020-02-26 22:30:21 -06:00
/* Find simulation time */
float simulation_time = find_simulation_time_period ( VERILOG_SIM_TIMESCALE ,
num_config_clock_cycles ,
1. / simulation_parameters . programming_clock_frequency ( ) ,
simulation_parameters . num_clock_cycles ( ) ,
1. / simulation_parameters . operating_clock_frequency ( ) ) ;
/* Add Icarus requirement */
2020-06-12 18:31:14 -05:00
print_verilog_timeout_and_vcd ( fp ,
2020-02-26 22:30:21 -06:00
std : : string ( ICARUS_SIMULATOR_FLAG ) ,
std : : string ( circuit_name + std : : string ( AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX ) ) ,
2020-06-12 18:31:14 -05:00
std : : string ( circuit_name + std : : string ( " _formal.vcd " ) ) ,
2020-02-26 22:30:21 -06:00
std : : string ( TOP_TESTBENCH_SIM_START_PORT_NAME ) ,
std : : string ( TOP_TESTBENCH_ERROR_COUNTER ) ,
( int ) simulation_time ) ;
/* Testbench ends*/
print_verilog_module_end ( fp , std : : string ( circuit_name ) + std : : string ( AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX ) ) ;
/* Close the file stream */
fp . close ( ) ;
}
} /* end namespace openfpga */