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"
2020-09-29 13:22:10 -05:00
# include "fabric_bitstream_utils.h"
2020-02-26 22:30:21 -06:00
# 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-09-24 17:31:55 -05:00
/********************************************************************
* Identify global reset ports for programming
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
std : : vector < CircuitPortId > find_global_programming_reset_ports ( const CircuitLibrary & circuit_lib ,
const std : : vector < CircuitPortId > & global_ports ) {
/* Try to find global reset ports for programming */
std : : vector < CircuitPortId > global_prog_reset_ports ;
for ( const CircuitPortId & global_port : global_ports ) {
VTR_ASSERT ( true = = circuit_lib . port_is_global ( global_port ) ) ;
if ( false = = circuit_lib . port_is_prog ( global_port ) ) {
continue ;
}
VTR_ASSERT ( true = = circuit_lib . port_is_prog ( global_port ) ) ;
VTR_ASSERT ( ( false = = circuit_lib . port_is_reset ( global_port ) )
| | ( false = = circuit_lib . port_is_set ( global_port ) ) ) ;
if ( true = = circuit_lib . port_is_reset ( global_port ) ) {
global_prog_reset_ports . push_back ( global_port ) ;
}
}
return global_prog_reset_ports ;
}
/********************************************************************
* Identify global set ports for programming
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
std : : vector < CircuitPortId > find_global_programming_set_ports ( const CircuitLibrary & circuit_lib ,
const std : : vector < CircuitPortId > & global_ports ) {
/* Try to find global set ports for programming */
std : : vector < CircuitPortId > global_prog_set_ports ;
for ( const CircuitPortId & global_port : global_ports ) {
VTR_ASSERT ( true = = circuit_lib . port_is_global ( global_port ) ) ;
if ( false = = circuit_lib . port_is_prog ( global_port ) ) {
continue ;
}
VTR_ASSERT ( true = = circuit_lib . port_is_prog ( global_port ) ) ;
VTR_ASSERT ( ( false = = circuit_lib . port_is_reset ( global_port ) )
| | ( false = = circuit_lib . port_is_set ( global_port ) ) ) ;
if ( true = = circuit_lib . port_is_set ( global_port ) ) {
global_prog_set_ports . push_back ( global_port ) ;
}
}
return global_prog_set_ports ;
}
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-09-29 13:22:10 -05:00
void print_verilog_top_testbench_config_chain_port ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
2020-02-26 22:30:21 -06:00
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Print the head of configuraion-chains here */
print_verilog_comment ( fp , std : : string ( " ---- Configuration-chain head ----- " ) ) ;
2020-09-29 13:22:10 -05:00
ModulePortId cc_head_port_id = module_manager . find_module_port ( top_module , generate_configuration_chain_head_name ( ) ) ;
BasicPort config_chain_head_port = module_manager . module_port ( top_module , cc_head_port_id ) ;
2020-02-26 22:30:21 -06:00
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 ----- " ) ) ;
2020-09-29 13:22:10 -05:00
ModulePortId cc_tail_port_id = module_manager . find_module_port ( top_module , generate_configuration_chain_tail_name ( ) ) ;
BasicPort config_chain_tail_port = module_manager . module_port ( top_module , cc_tail_port_id ) ;
2020-02-26 22:30:21 -06:00
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 */
2020-09-25 22:05:20 -05:00
print_verilog_comment ( fp , std : : string ( " ---- Data input port for memory decoders ----- " ) ) ;
2020-05-30 21:04:44 -05:00
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 ;
2020-09-25 22:05:20 -05:00
/* Generate enable signal waveform here:
* which is a 90 degree phase shift than the programming clock
*/
print_verilog_comment ( fp , std : : string ( " ---- Wire enable port of memory decoders ----- " ) ) ;
2020-05-30 21:04:44 -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-09-25 22:05:20 -05:00
BasicPort en_register_port ( std : : string ( en_port . get_name ( ) + std : : string ( TOP_TB_CLOCK_REG_POSTFIX ) ) , 1 ) ;
2020-09-23 19:59:25 -05:00
BasicPort config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
2020-05-30 21:04:44 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , en_port ) < < " ; " < < std : : endl ;
2020-09-25 22:05:20 -05:00
fp < < generate_verilog_port ( VERILOG_PORT_REG , en_register_port ) < < " ; " < < std : : endl ;
write_tab_to_file ( fp , 1 ) ;
fp < < " assign " ;
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , en_port ) ;
fp < < " = " ;
fp < < " ~ " < < generate_verilog_port ( VERILOG_PORT_CONKT , en_register_port ) ;
fp < < " & " ;
fp < < " ~ " < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) ;
fp < < " ; " < < std : : endl ;
2020-05-30 21:04:44 -05:00
}
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-09-25 22:05:20 -05:00
/* Generate enable signal waveform here:
* which is a 90 degree phase shift than the programming clock
*/
print_verilog_comment ( fp , std : : string ( " ---- Wire enable port of frame-based decoders ----- " ) ) ;
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 ) ;
2020-09-25 22:05:20 -05:00
BasicPort en_register_port ( std : : string ( en_port . get_name ( ) + std : : string ( TOP_TB_CLOCK_REG_POSTFIX ) ) , 1 ) ;
2020-09-23 19:59:25 -05:00
2020-09-25 22:05:20 -05:00
BasicPort config_done_port ( std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) , 1 ) ;
fp < < generate_verilog_port ( VERILOG_PORT_WIRE , en_port ) < < " ; " < < std : : endl ;
fp < < generate_verilog_port ( VERILOG_PORT_REG , en_register_port ) < < " ; " < < std : : endl ;
write_tab_to_file ( fp , 1 ) ;
fp < < " assign " ;
fp < < generate_verilog_port ( VERILOG_PORT_CONKT , en_port ) ;
fp < < " = " ;
fp < < " ~ " < < generate_verilog_port ( VERILOG_PORT_CONKT , en_register_port ) ;
fp < < " & " ;
fp < < " ~ " < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) ;
fp < < " ; " < < std : : endl ;
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-09-23 21:27:52 -05:00
const ConfigProtocol & config_protocol ,
2020-05-27 19:40:45 -05:00
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
2020-09-23 21:27:52 -05:00
switch ( config_protocol . type ( ) ) {
2020-02-26 22:30:21 -06:00
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 :
2020-09-29 13:22:10 -05:00
print_verilog_top_testbench_config_chain_port ( fp , module_manager , top_module ) ;
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_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 :
2020-09-25 22:05:20 -05:00
print_verilog_top_testbench_frame_decoder_port ( fp ,
2020-09-23 21:27:52 -05:00
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 ,
2020-09-24 17:31:55 -05:00
const std : : vector < CircuitPortId > & global_ports ,
const bool & active_global_prog_reset ,
const bool & active_global_prog_set ) {
2020-02-26 22:30:21 -06:00
/* 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 ) ) ;
2020-09-24 17:31:55 -05:00
/* For global programming reset port, we will active only when specified */
2020-02-26 22:30:21 -06:00
BasicPort stimuli_reset_port ;
2020-09-24 17:31:55 -05:00
bool activate = true ;
2020-02-26 22:30:21 -06:00
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 ) ;
2020-09-24 17:31:55 -05:00
activate = active_global_prog_reset ;
2020-02-26 22:30:21 -06:00
} 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-09-24 17:31:55 -05:00
if ( true = = activate ) {
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 ) ) ;
} else {
VTR_ASSERT_SAFE ( false = = activate ) ;
print_verilog_wire_constant_values ( fp , module_manager . module_port ( top_module , module_global_port ) ,
std : : vector < size_t > ( 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 ) ) ;
2020-09-24 17:31:55 -05:00
/* For global programming set port, we will active only when specified */
2020-02-26 22:30:21 -06:00
BasicPort stimuli_set_port ;
2020-09-24 17:31:55 -05:00
bool activate = true ;
2020-02-26 22:30:21 -06:00
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 ) ;
2020-09-24 17:31:55 -05:00
activate = active_global_prog_set ;
2020-02-26 22:30:21 -06:00
} 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-09-24 17:31:55 -05:00
if ( true = = activate ) {
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 ) ) ;
} else {
VTR_ASSERT_SAFE ( false = = activate ) ;
print_verilog_wire_constant_values ( fp , module_manager . module_port ( top_module , module_global_port ) ,
std : : vector < size_t > ( 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 ,
2020-09-23 21:27:52 -05:00
const ConfigProtocol & config_protocol ,
2020-02-26 22:30:21 -06:00
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-09-25 22:05:20 -05:00
print_verilog_top_testbench_config_protocol_port ( fp , config_protocol ,
2020-05-27 19:40:45 -05:00
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
*/
2020-09-26 12:54:06 -05:00
print_verilog_comment ( fp , std : : string ( " ----- Error counter: Deposit an error for config_done signal is not raised at the beginning ----- " ) ) ;
fp < < " \t integer " < < TOP_TESTBENCH_ERROR_COUNTER < < " = 1; " < < std : : endl ;
2020-02-26 22:30:21 -06:00
}
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-09-24 17:31:55 -05:00
const bool & bit_value_to_skip ,
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-09-29 13:22:10 -05:00
/* Find the longest regional bitstream */
size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size ( fabric_bitstream ) ;
size_t num_config_clock_cycles = 1 + regional_bitstream_max_size ;
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-09-29 13:22:10 -05:00
/* For fast configuration, the bitstream size counts from the first bit '1' */
2020-07-15 12:44:23 -05:00
if ( true = = fast_configuration ) {
2020-09-29 13:22:10 -05:00
/* For fast configuration, the number of bits to be skipped
* depends on each regional bitstream
* For example :
* Region 0 : 000000001111101010
* Region 1 : 00000011010101
* Region 2 : 0010101111000110
* The number of bits that can be skipped is limited by Region 2
*/
size_t num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped ( fabric_bitstream , bitstream_manager , bit_value_to_skip ) ;
num_config_clock_cycles = 1 + regional_bitstream_max_size - num_bits_to_skip ;
2020-07-15 12:56:11 -05:00
VTR_LOG ( " Fast configuration reduces number of configuration clock cycles from %lu to %lu (compression_rate = %f%) \n " ,
2020-09-29 13:22:10 -05:00
1 + regional_bitstream_max_size ,
2020-07-15 12:56:11 -05:00
num_config_clock_cycles ,
2020-09-29 13:22:10 -05:00
100. * ( ( float ) num_config_clock_cycles / ( float ) ( 1 + regional_bitstream_max_size ) - 1. ) ) ;
2020-07-15 12:44:23 -05:00
}
2020-05-29 19:07:21 -05:00
break ;
2020-10-30 18:29:04 -05:00
case CONFIG_MEM_MEMORY_BANK : {
2020-05-29 19:07:21 -05:00
/* For fast configuration, we will skip all the zero data points */
2020-10-30 18:29:04 -05:00
num_config_clock_cycles = 1 + build_memory_bank_fabric_bitstream_by_address ( fabric_bitstream ) . size ( ) ;
2020-05-29 19:07:21 -05:00
if ( true = = fast_configuration ) {
2020-05-29 19:22:36 -05:00
size_t full_num_config_clock_cycles = num_config_clock_cycles ;
2020-10-30 18:29:04 -05:00
num_config_clock_cycles = 1 + find_memory_bank_fast_configuration_fabric_bitstream_size ( fabric_bitstream , bit_value_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. ) ) ;
}
break ;
}
case CONFIG_MEM_FRAME_BASED : {
num_config_clock_cycles = 1 + build_frame_based_fabric_bitstream_by_address ( fabric_bitstream ) . size ( ) ;
if ( true = = fast_configuration ) {
size_t full_num_config_clock_cycles = num_config_clock_cycles ;
num_config_clock_cycles = 1 + find_frame_based_fast_configuration_fabric_bitstream_size ( fabric_bitstream , bit_value_to_skip ) ;
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-09-29 13:22:10 -05:00
void print_verilog_top_testbench_load_bitstream_task_configuration_chain ( std : : fstream & fp ,
const ModuleManager & module_manager ,
const ModuleId & top_module ) {
2020-02-26 22:30:21 -06:00
/* Validate the file stream */
valid_file_stream ( fp ) ;
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
2020-09-29 13:22:10 -05:00
ModulePortId cc_head_port_id = module_manager . find_module_port ( top_module , generate_configuration_chain_head_name ( ) ) ;
BasicPort cc_head_port = module_manager . module_port ( top_module , cc_head_port_id ) ;
BasicPort cc_head_value ( generate_configuration_chain_head_name ( ) + std : : string ( " _val " ) , cc_head_port . get_width ( ) ) ;
2020-02-26 22:30:21 -06:00
/* 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 ) ;
2020-09-25 22:05:20 -05:00
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
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 ) ;
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 ;
2020-09-25 22:05:20 -05:00
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_port ) < < " ); " < < std : : endl ;
2020-05-30 21:04:44 -05:00
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-09-25 22:05:20 -05:00
BasicPort prog_clock_port ( std : : string ( TOP_TB_PROG_CLOCK_PORT_NAME ) , 1 ) ;
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-09-25 22:05:20 -05:00
fp < < " \t \t @(negedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , prog_clock_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 :
2020-09-29 13:22:10 -05:00
print_verilog_top_testbench_load_bitstream_task_configuration_chain ( fp ,
module_manager ,
top_module ) ;
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_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-09-24 17:31:55 -05:00
print_verilog_comment ( fp , " ----- Begin programming set signal generation ----- " ) ;
2020-06-12 18:31:14 -05:00
print_verilog_pulse_stimuli ( fp , prog_set_port ,
2020-09-24 17:31:55 -05:00
1 , /* Initial value */
2020-06-12 18:31:14 -05:00
prog_clock_period / timescale , 0 ) ;
2020-09-24 17:31:55 -05:00
print_verilog_comment ( fp , " ----- End programming set signal generation ----- " ) ;
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-09-25 22:05:20 -05:00
/********************************************************************
* Print input stimuli for configuration protocol
* include :
* - memory bank
* 1. the enable signal
* - frame - based
* 1. the enable signal
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
void print_verilog_top_testbench_configuration_protocol_stimulus ( std : : fstream & fp ,
const e_config_protocol_type & config_protocol_type ,
const ModuleManager & module_manager ,
const ModuleId & top_module ,
const float & prog_clock_period ,
const float & timescale ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Branch on the type of configuration protocol */
switch ( config_protocol_type ) {
case CONFIG_MEM_STANDALONE :
break ;
case CONFIG_MEM_SCAN_CHAIN :
break ;
case CONFIG_MEM_MEMORY_BANK :
case CONFIG_MEM_FRAME_BASED : {
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 en_register_port ( std : : string ( en_port . get_name ( ) + std : : string ( TOP_TB_CLOCK_REG_POSTFIX ) ) , 1 ) ;
print_verilog_comment ( fp , std : : string ( " ---- Generate enable signal waveform ----- " ) ) ;
print_verilog_shifted_clock_stimuli ( fp , en_register_port ,
0.25 * prog_clock_period / timescale ,
0.5 * prog_clock_period / timescale , 0 ) ;
break ;
}
default :
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Invalid SRAM organization type! \n " ) ;
exit ( 1 ) ;
}
}
2020-02-26 22:30:21 -06:00
/********************************************************************
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-09-23 22:25:06 -05:00
/********************************************************************
* Decide if we should use reset or set signal to acheive fast configuration
* - If only one type signal is specified , we use that type
* For example , only reset signal is defined , we will use reset
* - If both are defined , pick the one that will bring bigger reduction
* i . e . , larger number of configuration bits can be skipped
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
bool find_bit_value_to_skip_for_fast_configuration ( const e_config_protocol_type & config_protocol_type ,
const bool & fast_configuration ,
const std : : vector < CircuitPortId > & global_prog_reset_ports ,
const std : : vector < CircuitPortId > & global_prog_set_ports ,
const BitstreamManager & bitstream_manager ,
const FabricBitstream & fabric_bitstream ) {
/* Early exit conditions */
if ( ! global_prog_reset_ports . empty ( ) & & global_prog_set_ports . empty ( ) ) {
return false ;
} else if ( ! global_prog_set_ports . empty ( ) & & global_prog_reset_ports . empty ( ) ) {
return true ;
} else if ( global_prog_set_ports . empty ( ) & & global_prog_reset_ports . empty ( ) ) {
/* If both types of ports are not defined, the fast configuration should be turned off */
VTR_ASSERT ( false = = fast_configuration ) ;
return false ;
}
VTR_ASSERT ( ! global_prog_set_ports . empty ( ) & & ! global_prog_reset_ports . empty ( ) ) ;
bool bit_value_to_skip = false ;
2020-09-23 22:34:23 -05:00
VTR_LOG ( " Both reset and set ports are defined for programming controls, selecting the best-fit one... \n " ) ;
2020-09-23 22:25:06 -05:00
size_t num_ones_to_skip = 0 ;
size_t num_zeros_to_skip = 0 ;
/* Branch on the type of configuration protocol */
switch ( config_protocol_type ) {
case CONFIG_MEM_STANDALONE :
break ;
case CONFIG_MEM_SCAN_CHAIN : {
/* We can only skip the ones/zeros at the beginning of the bitstream */
/* Count how many logic '1' bits we can skip */
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
if ( false = = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ) {
break ;
}
VTR_ASSERT ( true = = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ) ;
num_ones_to_skip + + ;
}
/* Count how many logic '0' bits we can skip */
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
if ( true = = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ) {
break ;
}
VTR_ASSERT ( false = = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ) ;
num_zeros_to_skip + + ;
}
break ;
}
case CONFIG_MEM_MEMORY_BANK :
case CONFIG_MEM_FRAME_BASED : {
/* Count how many logic '1' and logic '0' bits we can skip */
for ( const FabricBitId & bit_id : fabric_bitstream . bits ( ) ) {
if ( false = = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ) {
num_zeros_to_skip + + ;
} else {
VTR_ASSERT ( true = = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ) ;
num_ones_to_skip + + ;
}
}
break ;
}
default :
VTR_LOGF_ERROR ( __FILE__ , __LINE__ ,
" Invalid SRAM organization type! \n " ) ;
exit ( 1 ) ;
}
2020-09-23 22:34:23 -05:00
VTR_LOG ( " Using reset will skip %g% (%lu/%lu) of configuration bitstream. \n " ,
100. * ( float ) num_zeros_to_skip / ( float ) fabric_bitstream . num_bits ( ) ,
num_zeros_to_skip , fabric_bitstream . num_bits ( ) ) ;
VTR_LOG ( " Using set will skip %g% (%lu/%lu) of configuration bitstream. \n " ,
100. * ( float ) num_ones_to_skip / ( float ) fabric_bitstream . num_bits ( ) ,
num_ones_to_skip , fabric_bitstream . num_bits ( ) ) ;
2020-09-23 22:25:06 -05:00
/* By default, we prefer to skip zeros (when the numbers are the same */
if ( num_ones_to_skip > num_zeros_to_skip ) {
2020-09-23 22:34:23 -05:00
VTR_LOG ( " Will use set signal in fast configuration \n " ) ;
2020-09-23 22:25:06 -05:00
bit_value_to_skip = true ;
2020-09-23 22:34:23 -05:00
} else {
VTR_LOG ( " Will use reset signal in fast configuration \n " ) ;
2020-09-23 22:25:06 -05:00
}
return bit_value_to_skip ;
}
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-09-23 22:25:06 -05:00
const bool & bit_value_to_skip ,
2020-09-29 13:22:10 -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
/* 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
*/
2020-09-29 13:22:10 -05:00
ModulePortId cc_head_port_id = module_manager . find_module_port ( top_module , generate_configuration_chain_head_name ( ) ) ;
BasicPort config_chain_head_port = module_manager . module_port ( top_module , cc_head_port_id ) ;
2020-02-26 22:30:21 -06:00
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-09-29 13:22:10 -05:00
/* Find the longest bitstream */
size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size ( fabric_bitstream ) ;
/* For fast configuration, the bitstream size counts from the first bit '1' */
size_t num_bits_to_skip = 0 ;
if ( true = = fast_configuration ) {
num_bits_to_skip = find_configuration_chain_fabric_bitstream_size_to_be_skipped ( fabric_bitstream , bitstream_manager , bit_value_to_skip ) ;
}
VTR_ASSERT ( num_bits_to_skip < regional_bitstream_max_size ) ;
/* Reorganize the regional bitstreams to be the same size */
std : : vector < std : : vector < bool > > regional_bitstreams ;
regional_bitstreams . reserve ( fabric_bitstream . regions ( ) . size ( ) ) ;
for ( const FabricBitRegionId & region : fabric_bitstream . regions ( ) ) {
std : : vector < bool > curr_regional_bitstream ;
curr_regional_bitstream . resize ( regional_bitstream_max_size , false ) ;
/* Starting index should consider the offset between the current bitstream size and
* the maximum size of regional bitstream
*/
size_t offset = regional_bitstream_max_size - fabric_bitstream . region_bits ( region ) . size ( ) ;
for ( const FabricBitId & bit_id : fabric_bitstream . region_bits ( region ) ) {
curr_regional_bitstream [ offset ] = bitstream_manager . bit_value ( fabric_bitstream . config_bit ( bit_id ) ) ;
offset + + ;
}
VTR_ASSERT ( offset = = regional_bitstream_max_size ) ;
/* Add the adapt sub-bitstream */
regional_bitstreams . push_back ( curr_regional_bitstream ) ;
}
2020-09-23 22:25:06 -05:00
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-09-29 13:22:10 -05:00
*
* Note that bitstream may come from different regions
* The bitstream value to be loaded should be organized as follows
*
* cycleA
* |
* Region 0 : 0 | 00000001111101010
* Region 1 : | 00000011010101
* Region 2 : | 0010101111000110
*
* Zero bits will be added to the head of those bitstreams are shorter
* than the longest bitstream
2020-02-26 22:30:21 -06:00
*/
2020-09-29 13:22:10 -05:00
for ( size_t ibit = num_bits_to_skip ; ibit < regional_bitstream_max_size ; + + ibit ) {
std : : vector < size_t > curr_cc_head_val ;
curr_cc_head_val . reserve ( fabric_bitstream . regions ( ) . size ( ) ) ;
for ( const auto & region_bitstream : regional_bitstreams ) {
curr_cc_head_val . push_back ( ( size_t ) region_bitstream [ ibit ] ) ;
2020-07-15 12:44:23 -05:00
}
2020-05-27 19:40:45 -05:00
fp < < " \t \t " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) ;
2020-09-29 13:22:10 -05:00
fp < < " ( " < < generate_verilog_constant_values ( curr_cc_head_val ) < < " ); " < < 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 ,
2020-09-23 22:25:06 -05:00
const bool & bit_value_to_skip ,
2020-05-30 21:04:44 -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-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-10-29 13:42:03 -05:00
fp < < " \t \t " ;
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 ;
2020-10-30 18:29:04 -05:00
/* Reorganize the fabric bitstream by the same address across regions */
std : : map < std : : pair < std : : string , std : : string > , std : : vector < bool > > fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address ( fabric_bitstream ) ;
2020-10-29 13:42:03 -05:00
for ( const auto & addr_din_pair : fabric_bits_by_addr ) {
/* When fast configuration is enabled,
* the rule to skip any configuration bit should consider the whole data input values .
* Only all the bits in the din port match the value to be skipped ,
* the programming cycle can be skipped !
*/
if ( true = = fast_configuration ) {
bool skip_curr_bits = true ;
for ( const bool & bit : addr_din_pair . second ) {
if ( bit_value_to_skip ! = bit ) {
skip_curr_bits = false ;
break ;
}
}
if ( true = = skip_curr_bits ) {
continue ;
}
2020-05-30 21:04:44 -05:00
}
fp < < " \t \t " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) ;
fp < < " ( " < < bl_addr_port . get_width ( ) < < " 'b " ;
2020-10-29 13:42:03 -05:00
VTR_ASSERT ( bl_addr_port . get_width ( ) = = addr_din_pair . first . first . length ( ) ) ;
fp < < addr_din_pair . first . first ;
2020-05-30 21:04:44 -05:00
fp < < " , " ;
fp < < wl_addr_port . get_width ( ) < < " 'b " ;
2020-10-29 13:42:03 -05:00
VTR_ASSERT ( wl_addr_port . get_width ( ) = = addr_din_pair . first . second . length ( ) ) ;
fp < < addr_din_pair . first . second ;
2020-05-30 21:04:44 -05:00
fp < < " , " ;
2020-10-29 13:42:03 -05:00
fp < < din_port . get_width ( ) < < " 'b " ;
VTR_ASSERT ( din_port . get_width ( ) = = addr_din_pair . second . size ( ) ) ;
for ( const bool & din_value : addr_din_pair . second ) {
if ( true = = din_value ) {
fp < < " 1 " ;
} else {
VTR_ASSERT ( false = = din_value ) ;
fp < < " 0 " ;
}
2020-05-30 21:04:44 -05:00
}
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-09-23 22:25:06 -05:00
const bool & bit_value_to_skip ,
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 ;
2020-10-30 18:29:04 -05:00
/* Reorganize the fabric bitstream by the same address across regions */
std : : map < std : : string , std : : vector < bool > > fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address ( fabric_bitstream ) ;
2020-10-30 11:43:11 -05:00
for ( const auto & addr_din_pair : fabric_bits_by_addr ) {
/* When fast configuration is enabled,
* the rule to skip any configuration bit should consider the whole data input values .
* Only all the bits in the din port match the value to be skipped ,
* the programming cycle can be skipped !
*/
if ( true = = fast_configuration ) {
bool skip_curr_bits = true ;
for ( const bool & bit : addr_din_pair . second ) {
if ( bit_value_to_skip ! = bit ) {
skip_curr_bits = false ;
break ;
}
}
if ( true = = skip_curr_bits ) {
continue ;
}
2020-05-29 19:07:21 -05:00
}
2020-05-27 19:40:45 -05:00
fp < < " \t \t " < < std : : string ( TOP_TESTBENCH_PROG_TASK_NAME ) ;
fp < < " ( " < < addr_port . get_width ( ) < < " 'b " ;
2020-10-30 11:43:11 -05:00
VTR_ASSERT ( addr_port . get_width ( ) = = addr_din_pair . first . size ( ) ) ;
fp < < addr_din_pair . first ;
2020-05-27 19:40:45 -05:00
fp < < " , " ;
2020-10-30 18:29:04 -05:00
fp < < din_port . get_width ( ) < < " 'b " ;
2020-10-30 11:43:11 -05:00
VTR_ASSERT ( din_port . get_width ( ) = = addr_din_pair . second . size ( ) ) ;
for ( const bool & din_value : addr_din_pair . second ) {
if ( true = = din_value ) {
fp < < " 1 " ;
} else {
VTR_ASSERT ( false = = din_value ) ;
fp < < " 0 " ;
}
2020-05-27 19:40:45 -05:00
}
fp < < " ); " < < std : : endl ;
}
2020-10-30 18:29:04 -05:00
/* Disable the address and din
2020-05-29 00:05:24 -05:00
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 < < " , " ;
2020-10-30 18:29:04 -05:00
fp < < generate_verilog_constant_values ( initial_din_values ) ;
2020-05-29 00:05:24 -05:00
fp < < " ); " < < std : : endl ;
2020-10-30 18:29:04 -05:00
*/
2020-05-29 00:05:24 -05:00
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 ,
2020-09-23 22:25:06 -05:00
const e_config_protocol_type & config_protocol_type ,
2020-05-29 19:07:21 -05:00
const bool & fast_configuration ,
2020-09-24 17:31:55 -05:00
const bool & bit_value_to_skip ,
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-09-23 22:25:06 -05:00
2020-02-26 22:30:21 -06:00
/* Branch on the type of configuration protocol */
2020-09-23 22:25:06 -05:00
switch ( config_protocol_type ) {
2020-02-26 22:30:21 -06:00
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-09-24 17:31:55 -05:00
print_verilog_top_testbench_configuration_chain_bitstream ( fp , fast_configuration ,
2020-09-23 22:25:06 -05:00
bit_value_to_skip ,
2020-09-29 13:22:10 -05:00
module_manager , top_module ,
2020-07-15 12:44:23 -05:00
bitstream_manager , fabric_bitstream ) ;
2020-02-26 22:30:21 -06:00
break ;
case CONFIG_MEM_MEMORY_BANK :
2020-09-24 17:31:55 -05:00
print_verilog_top_testbench_memory_bank_bitstream ( fp , fast_configuration ,
2020-09-23 22:25:06 -05:00
bit_value_to_skip ,
2020-05-30 21:04:44 -05:00
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-09-24 17:31:55 -05:00
print_verilog_top_testbench_frame_decoder_bitstream ( fp , fast_configuration ,
2020-09-23 22:25:06 -05:00
bit_value_to_skip ,
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-09-26 12:54:06 -05:00
/********************************************************************
* Add auto - check codes for the full testbench
* in particular for the configuration phase :
* - Check that the configuration done signal is raised , indicating
* that the configuration phase is finished
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
void print_verilog_top_testbench_check ( std : : fstream & fp ,
const std : : string & autochecked_preprocessing_flag ,
const std : : string & config_done_port_name ,
const std : : string & error_counter_name ) {
/* Validate the file stream */
valid_file_stream ( fp ) ;
/* Add output autocheck conditionally: only when a preprocessing flag is enable */
print_verilog_preprocessing_flag ( fp , autochecked_preprocessing_flag ) ;
print_verilog_comment ( fp , std : : string ( " ----- Configuration done must be raised in the end ------- " ) ) ;
BasicPort config_done_port ( config_done_port_name , 1 ) ;
write_tab_to_file ( fp , 1 ) ;
fp < < " always@(posedge " < < generate_verilog_port ( VERILOG_PORT_CONKT , config_done_port ) < < " ) begin " < < std : : endl ;
write_tab_to_file ( fp , 2 ) ;
fp < < error_counter_name < < " = " < < error_counter_name < < " - 1; " < < std : : endl ;
write_tab_to_file ( fp , 1 ) ;
fp < < " end " < < std : : endl ;
/* Condition ends */
print_verilog_endif ( fp ) ;
/* Add an empty line as splitter */
fp < < std : : endl ;
}
2020-02-26 22:30:21 -06:00
/********************************************************************
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-09-23 21:27:52 -05:00
const ConfigProtocol & config_protocol ,
2020-02-26 22:30:21 -06:00
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
2020-09-24 17:31:55 -05:00
/* Preparation: find all the reset/set ports for programming usage */
std : : vector < CircuitPortId > global_prog_reset_ports = find_global_programming_reset_ports ( circuit_lib , global_ports ) ;
std : : vector < CircuitPortId > global_prog_set_ports = find_global_programming_set_ports ( circuit_lib , global_ports ) ;
/* Identify if we can apply fast configuration */
bool apply_fast_configuration = fast_configuration ;
if ( ( global_prog_set_ports . empty ( ) & & global_prog_reset_ports . empty ( ) )
& & ( true = = fast_configuration ) ) {
VTR_LOG_WARN ( " None of global reset and set ports are defined for programming purpose. Fast configuration is turned off \n " ) ;
apply_fast_configuration = false ;
}
bool bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration ( config_protocol . type ( ) ,
apply_fast_configuration ,
global_prog_reset_ports ,
global_prog_set_ports ,
bitstream_manager , fabric_bitstream ) ;
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-09-25 22:05:20 -05:00
config_protocol ,
2020-09-23 21:27:52 -05:00
circuit_name ) ;
2020-02-26 22:30:21 -06:00
/* 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-09-23 21:27:52 -05:00
size_t num_config_clock_cycles = calculate_num_config_clock_cycles ( config_protocol . type ( ) ,
2020-09-24 17:31:55 -05:00
apply_fast_configuration ,
bit_value_to_skip ,
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 ) ;
2020-09-25 22:05:20 -05:00
/* Generate stimuli for programming interface */
print_verilog_top_testbench_configuration_protocol_stimulus ( fp ,
config_protocol . type ( ) ,
module_manager , top_module ,
prog_clock_period ,
VERILOG_SIM_TIMESCALE ) ;
2020-09-24 17:31:55 -05:00
/* Identify the stimulus for global reset/set for programming purpose:
* - If only reset port is seen we turn on Reset
* - If only set port is seen we turn on Reset
* - If both reset and set port is defined ,
* we pick the one which is consistent with the bit value to be skipped
*/
bool active_global_prog_reset = false ;
bool active_global_prog_set = false ;
if ( ! global_prog_reset_ports . empty ( ) ) {
active_global_prog_reset = true ;
}
if ( ! global_prog_set_ports . empty ( ) ) {
active_global_prog_set = true ;
}
/* Ensure that at most only one of the two switches is activated */
if ( ( true = = active_global_prog_reset )
& & ( true = = active_global_prog_set ) ) {
/* If we will skip logic '0', we will activate programming reset */
active_global_prog_reset = ! bit_value_to_skip ;
/* If we will skip logic '1', we will activate programming set */
active_global_prog_set = bit_value_to_skip ;
}
2020-02-26 22:30:21 -06:00
/* Generate stimuli for global ports or connect them to existed signals */
print_verilog_top_testbench_global_ports_stimuli ( fp ,
module_manager , top_module ,
2020-09-24 17:31:55 -05:00
circuit_lib , global_ports ,
active_global_prog_reset ,
active_global_prog_set ) ;
2020-02-26 22:30:21 -06:00
/* 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 ,
2020-09-23 21:27:52 -05:00
config_protocol . type ( ) ,
2020-05-27 19:40:45 -05:00
module_manager , top_module ) ;
2020-02-26 22:30:21 -06:00
/* load bitstream to FPGA fabric in a configuration phase */
2020-09-23 21:27:52 -05:00
print_verilog_top_testbench_bitstream ( fp , config_protocol . type ( ) ,
2020-09-24 17:31:55 -05:00
apply_fast_configuration ,
bit_value_to_skip ,
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
2020-09-26 12:54:06 -05:00
/* Add autocheck for configuration phase */
print_verilog_top_testbench_check ( fp ,
std : : string ( AUTOCHECKED_SIMULATION_FLAG ) ,
std : : string ( TOP_TB_CONFIG_DONE_PORT_NAME ) ,
std : : string ( TOP_TESTBENCH_ERROR_COUNTER ) ) ;
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 */