[FPGA-Verilog] Upgrade testbench generator to support QL memory bank
This commit is contained in:
parent
6f09f5f7ad
commit
1aac3197eb
|
@ -29,46 +29,14 @@
|
|||
#include "verilog_constants.h"
|
||||
#include "verilog_writer_utils.h"
|
||||
#include "verilog_testbench_utils.h"
|
||||
#include "verilog_top_testbench_memory_bank.h"
|
||||
#include "verilog_top_testbench.h"
|
||||
|
||||
#include "verilog_top_testbench_constants.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";
|
||||
|
||||
constexpr char* TOP_TESTBENCH_PROG_TASK_NAME = "prog_cycle_task";
|
||||
|
||||
constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start";
|
||||
|
||||
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_OP_CLOCK_PORT_PREFIX = "operating_clk_";
|
||||
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* TOP_TB_BITSTREAM_LENGTH_VARIABLE = "BITSTREAM_LENGTH";
|
||||
constexpr char* TOP_TB_BITSTREAM_WIDTH_VARIABLE = "BITSTREAM_WIDTH";
|
||||
constexpr char* TOP_TB_BITSTREAM_MEM_REG_NAME = "bit_mem";
|
||||
constexpr char* TOP_TB_BITSTREAM_INDEX_REG_NAME = "bit_index";
|
||||
constexpr char* TOP_TB_BITSTREAM_ITERATOR_REG_NAME = "ibit";
|
||||
constexpr char* TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME = "skip_bits";
|
||||
|
||||
constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb";
|
||||
|
||||
/********************************************************************
|
||||
* Generate a simulation clock port name
|
||||
* This function is designed to produce a uniform clock naming for these ports
|
||||
|
@ -1735,6 +1703,13 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp,
|
|||
module_manager, top_module,
|
||||
fabric_bitstream);
|
||||
break;
|
||||
case CONFIG_MEM_QL_MEMORY_BANK:
|
||||
print_verilog_full_testbench_ql_memory_bank_bitstream(fp, bitstream_file,
|
||||
fast_configuration,
|
||||
bit_value_to_skip,
|
||||
module_manager, top_module,
|
||||
fabric_bitstream);
|
||||
break;
|
||||
case CONFIG_MEM_FRAME_BASED:
|
||||
print_verilog_full_testbench_frame_decoder_bitstream(fp, bitstream_file,
|
||||
fast_configuration,
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef VERILOG_TOP_TESTBENCH_CONSTANTS
|
||||
#define VERILOG_TOP_TESTBENCH_CONSTANTS
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
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";
|
||||
|
||||
constexpr char* TOP_TESTBENCH_PROG_TASK_NAME = "prog_cycle_task";
|
||||
|
||||
constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start";
|
||||
|
||||
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_OP_CLOCK_PORT_PREFIX = "operating_clk_";
|
||||
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* TOP_TB_BITSTREAM_LENGTH_VARIABLE = "BITSTREAM_LENGTH";
|
||||
constexpr char* TOP_TB_BITSTREAM_WIDTH_VARIABLE = "BITSTREAM_WIDTH";
|
||||
constexpr char* TOP_TB_BITSTREAM_MEM_REG_NAME = "bit_mem";
|
||||
constexpr char* TOP_TB_BITSTREAM_INDEX_REG_NAME = "bit_index";
|
||||
constexpr char* TOP_TB_BITSTREAM_ITERATOR_REG_NAME = "ibit";
|
||||
constexpr char* TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME = "skip_bits";
|
||||
|
||||
constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb";
|
||||
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,175 @@
|
|||
/********************************************************************
|
||||
* 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"
|
||||
|
||||
#include "openfpga_reserved_words.h"
|
||||
#include "openfpga_naming.h"
|
||||
#include "simulation_utils.h"
|
||||
#include "openfpga_atom_netlist_utils.h"
|
||||
|
||||
#include "fast_configuration.h"
|
||||
#include "fabric_bitstream_utils.h"
|
||||
#include "fabric_global_port_info_utils.h"
|
||||
|
||||
#include "verilog_constants.h"
|
||||
#include "verilog_writer_utils.h"
|
||||
#include "verilog_testbench_utils.h"
|
||||
#include "verilog_top_testbench_memory_bank.h"
|
||||
|
||||
#include "verilog_top_testbench_constants.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp,
|
||||
const std::string& bitstream_file,
|
||||
const bool& fast_configuration,
|
||||
const bool& bit_value_to_skip,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const FabricBitstream& fabric_bitstream) {
|
||||
/* Validate the file stream */
|
||||
valid_file_stream(fp);
|
||||
|
||||
/* Reorganize the fabric bitstream by the same address across regions */
|
||||
MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream);
|
||||
|
||||
/* For fast configuration, identify the final bitstream size to be used */
|
||||
size_t num_bits_to_skip = 0;
|
||||
if (true == fast_configuration) {
|
||||
num_bits_to_skip = fabric_bits_by_addr.size() - find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip);
|
||||
}
|
||||
VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size());
|
||||
|
||||
/* Feed address and data input pair one by one
|
||||
* Note: the first cycle is reserved for programming reset
|
||||
* We should give dummy values
|
||||
*/
|
||||
ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module,
|
||||
std::string(DECODER_BL_ADDRESS_PORT_NAME));
|
||||
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,
|
||||
std::string(DECODER_WL_ADDRESS_PORT_NAME));
|
||||
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);
|
||||
|
||||
/* Define a constant for the bitstream length */
|
||||
print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size() - num_bits_to_skip);
|
||||
print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), bl_addr_port.get_width() + wl_addr_port.get_width() + din_port.get_width());
|
||||
|
||||
/* Declare local variables for bitstream loading in Verilog */
|
||||
print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----");
|
||||
fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] ";
|
||||
fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];";
|
||||
fp << std::endl;
|
||||
|
||||
fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl;
|
||||
|
||||
print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----");
|
||||
fp << "initial begin" << std::endl;
|
||||
fp << "\t";
|
||||
fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");";
|
||||
fp << std::endl;
|
||||
|
||||
print_verilog_comment(fp, "----- Bit-Line Address port default input -----");
|
||||
fp << "\t";
|
||||
fp << generate_verilog_port_constant_values(bl_addr_port, initial_bl_addr_values);
|
||||
fp << ";";
|
||||
fp << std::endl;
|
||||
|
||||
print_verilog_comment(fp, "----- Word-Line Address port default input -----");
|
||||
fp << "\t";
|
||||
fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values);
|
||||
fp << ";";
|
||||
fp << std::endl;
|
||||
|
||||
print_verilog_comment(fp, "----- Data-input port default input -----");
|
||||
fp << "\t";
|
||||
fp << generate_verilog_port_constant_values(din_port, initial_din_values);
|
||||
fp << ";";
|
||||
fp << std::endl;
|
||||
|
||||
fp << "\t";
|
||||
fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0";
|
||||
fp << ";";
|
||||
fp << std::endl;
|
||||
|
||||
fp << "end";
|
||||
fp << std::endl;
|
||||
|
||||
print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----");
|
||||
BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1);
|
||||
fp << "always";
|
||||
fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")";
|
||||
fp << " begin";
|
||||
fp << std::endl;
|
||||
|
||||
fp << "\t";
|
||||
fp << "if (";
|
||||
fp << TOP_TB_BITSTREAM_INDEX_REG_NAME;
|
||||
fp << " >= ";
|
||||
fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE;
|
||||
fp << ") begin";
|
||||
fp << std::endl;
|
||||
|
||||
BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1);
|
||||
fp << "\t\t";
|
||||
std::vector<size_t> config_done_final_values(config_done_port.get_width(), 1);
|
||||
fp << generate_verilog_port_constant_values(config_done_port, config_done_final_values, true);
|
||||
fp << ";" << std::endl;
|
||||
|
||||
fp << "\t";
|
||||
fp << "end else begin";
|
||||
fp << std::endl;
|
||||
|
||||
fp << "\t\t";
|
||||
fp << "{";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port);
|
||||
fp << ", ";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port);
|
||||
fp << ", ";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port);
|
||||
fp << "}";
|
||||
fp << " <= ";
|
||||
fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME << "]";
|
||||
fp << ";" << std::endl;
|
||||
|
||||
fp << "\t\t";
|
||||
fp << TOP_TB_BITSTREAM_INDEX_REG_NAME;
|
||||
fp << " <= ";
|
||||
fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1";
|
||||
fp << ";" << std::endl;
|
||||
|
||||
fp << "\t";
|
||||
fp << "end";
|
||||
fp << std::endl;
|
||||
|
||||
fp << "end";
|
||||
fp << std::endl;
|
||||
|
||||
print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----");
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef VERILOG_TOP_TESTBENCH_MEMORY_BANK
|
||||
#define VERILOG_TOP_TESTBENCH_MEMORY_BANK
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "module_manager.h"
|
||||
#include "bitstream_manager.h"
|
||||
#include "fabric_bitstream.h"
|
||||
#include "circuit_library.h"
|
||||
#include "config_protocol.h"
|
||||
#include "vpr_context.h"
|
||||
#include "pin_constraints.h"
|
||||
#include "io_location_map.h"
|
||||
#include "fabric_global_port_info.h"
|
||||
#include "vpr_netlist_annotation.h"
|
||||
#include "simulation_setting.h"
|
||||
#include "verilog_testbench_options.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/**
|
||||
* @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol
|
||||
* where configuration bits are programming in serial (one by one)
|
||||
*/
|
||||
void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp,
|
||||
const std::string& bitstream_file,
|
||||
const bool& fast_configuration,
|
||||
const bool& bit_value_to_skip,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const FabricBitstream& fabric_bitstream);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue