break the configuration testbench. This commit is to spot which modification leads to the problem
This commit is contained in:
parent
85921dcc05
commit
cff5b5cfc1
|
@ -101,7 +101,7 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
|
||||||
const std::vector<ConfigBlockId>& parent_blocks,
|
const std::vector<ConfigBlockId>& parent_blocks,
|
||||||
const ModuleManager& module_manager,
|
const ModuleManager& module_manager,
|
||||||
const std::vector<ModuleId>& parent_modules,
|
const std::vector<ModuleId>& parent_modules,
|
||||||
const std::vector<bool>& addr_code,
|
const std::vector<size_t>& addr_code,
|
||||||
FabricBitstream& fabric_bitstream) {
|
FabricBitstream& fabric_bitstream) {
|
||||||
|
|
||||||
/* Depth-first search: if we have any children in the parent_block,
|
/* Depth-first search: if we have any children in the parent_block,
|
||||||
|
@ -154,17 +154,14 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
|
||||||
child_modules.push_back(child_module);
|
child_modules.push_back(child_module);
|
||||||
|
|
||||||
/* Set address, apply binary conversion from the first to the last element in the address list */
|
/* Set address, apply binary conversion from the first to the last element in the address list */
|
||||||
std::vector<bool> child_addr_code = addr_code;
|
std::vector<size_t> child_addr_code = addr_code;
|
||||||
|
|
||||||
if (true == add_addr_code) {
|
if (true == add_addr_code) {
|
||||||
/* Find the address port from the decoder module */
|
/* Find the address port from the decoder module */
|
||||||
const ModulePortId& decoder_addr_port_id = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
|
const ModulePortId& decoder_addr_port_id = module_manager.find_module_port(decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
|
||||||
const BasicPort& decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id);
|
const BasicPort& decoder_addr_port = module_manager.module_port(decoder_module, decoder_addr_port_id);
|
||||||
std::vector<size_t> addr_bits_vec = itobin_vec(child_id, decoder_addr_port.get_width());
|
std::vector<size_t> addr_bits_vec = itobin_vec(child_id, decoder_addr_port.get_width());
|
||||||
for (const size_t& bit : addr_bits_vec) {
|
child_addr_code.insert(child_addr_code.end(), addr_bits_vec.begin(), addr_bits_vec.end());
|
||||||
VTR_ASSERT((0 == bit) || (1 == bit));
|
|
||||||
child_addr_code.push_back(bit);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Go recursively */
|
/* Go recursively */
|
||||||
|
@ -226,7 +223,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc
|
||||||
std::vector<ConfigBlockId>(1, top_block),
|
std::vector<ConfigBlockId>(1, top_block),
|
||||||
module_manager,
|
module_manager,
|
||||||
std::vector<ModuleId>(1, top_module),
|
std::vector<ModuleId>(1, top_module),
|
||||||
std::vector<bool>(),
|
std::vector<size_t>(),
|
||||||
fabric_bitstream);
|
fabric_bitstream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ ConfigBitId FabricBitstream::config_bit(const FabricBitId& bit_id) const {
|
||||||
return config_bit_ids_[bit_id];
|
return config_bit_ids_[bit_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<bool> FabricBitstream::bit_address(const FabricBitId& bit_id) const {
|
std::vector<size_t> FabricBitstream::bit_address(const FabricBitId& bit_id) const {
|
||||||
/* Ensure a valid id */
|
/* Ensure a valid id */
|
||||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FabricBitstream::set_bit_address(const FabricBitId& bit_id,
|
void FabricBitstream::set_bit_address(const FabricBitId& bit_id,
|
||||||
const std::vector<bool>& address) {
|
const std::vector<size_t>& address) {
|
||||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||||
bit_addresses_[bit_id] = address;
|
bit_addresses_[bit_id] = address;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ class FabricBitstream {
|
||||||
ConfigBitId config_bit(const FabricBitId& bit_id) const;
|
ConfigBitId config_bit(const FabricBitId& bit_id) const;
|
||||||
|
|
||||||
/* Find the address of bitstream */
|
/* Find the address of bitstream */
|
||||||
std::vector<bool> bit_address(const FabricBitId& bit_id) const;
|
std::vector<size_t> bit_address(const FabricBitId& bit_id) const;
|
||||||
|
|
||||||
/* Find the data-in of bitstream */
|
/* Find the data-in of bitstream */
|
||||||
bool bit_din(const FabricBitId& bit_id) const;
|
bool bit_din(const FabricBitId& bit_id) const;
|
||||||
|
@ -62,7 +62,7 @@ class FabricBitstream {
|
||||||
FabricBitId add_bit(const ConfigBitId& config_bit_id);
|
FabricBitId add_bit(const ConfigBitId& config_bit_id);
|
||||||
|
|
||||||
void set_bit_address(const FabricBitId& bit_id,
|
void set_bit_address(const FabricBitId& bit_id,
|
||||||
const std::vector<bool>& address);
|
const std::vector<size_t>& address);
|
||||||
|
|
||||||
void set_bit_din(const FabricBitId& bit_id,
|
void set_bit_din(const FabricBitId& bit_id,
|
||||||
const bool& din);
|
const bool& din);
|
||||||
|
@ -84,7 +84,7 @@ class FabricBitstream {
|
||||||
* Here we store the binary format of the address, which can be loaded
|
* Here we store the binary format of the address, which can be loaded
|
||||||
* to the configuration protocol directly
|
* to the configuration protocol directly
|
||||||
*/
|
*/
|
||||||
vtr::vector<FabricBitId, std::vector<bool>> bit_addresses_;
|
vtr::vector<FabricBitId, std::vector<size_t>> bit_addresses_;
|
||||||
|
|
||||||
/* Data input (Din) bits: this is designed for memory decoders */
|
/* Data input (Din) bits: this is designed for memory decoders */
|
||||||
vtr::vector<FabricBitId, bool> bit_dins_;
|
vtr::vector<FabricBitId, bool> bit_dins_;
|
||||||
|
|
|
@ -41,7 +41,7 @@ constexpr char* TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX = "_fpga";
|
||||||
|
|
||||||
constexpr char* TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX = "_flag";
|
constexpr char* TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX = "_flag";
|
||||||
|
|
||||||
constexpr char* TOP_TESTBENCH_CC_PROG_TASK_NAME = "prog_cycle_task";
|
constexpr char* TOP_TESTBENCH_PROG_TASK_NAME = "prog_cycle_task";
|
||||||
|
|
||||||
constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start";
|
constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start";
|
||||||
|
|
||||||
|
@ -79,12 +79,49 @@ void print_verilog_top_testbench_config_chain_port(std::fstream& fp) {
|
||||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, config_chain_tail_port) << ";" << std::endl;
|
fp << generate_verilog_port(VERILOG_PORT_WIRE, config_chain_tail_port) << ";" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Print local wires for frame-based decoder protocols
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
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);
|
||||||
|
fp << generate_verilog_port(VERILOG_PORT_WIRE, din_port) << ";" << std::endl;
|
||||||
|
|
||||||
|
/* Wire the programming clock to the enable signal */
|
||||||
|
print_verilog_comment(fp, std::string("---- Wire enable port of frame-based decoder to programming clock -----"));
|
||||||
|
ModulePortId en_port_id = module_manager.find_module_port(top_module,
|
||||||
|
std::string(DECODER_ENABLE_PORT_NAME));
|
||||||
|
BasicPort en_port = module_manager.module_port(top_module, en_port_id);
|
||||||
|
BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1);
|
||||||
|
|
||||||
|
print_verilog_wire_connection(fp, en_port, prog_clock_port, false);
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Print local wires for different types of configuration protocols
|
* Print local wires for different types of configuration protocols
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static
|
static
|
||||||
void print_verilog_top_testbench_config_protocol_port(std::fstream& fp,
|
void print_verilog_top_testbench_config_protocol_port(std::fstream& fp,
|
||||||
const e_config_protocol_type& sram_orgz_type) {
|
const e_config_protocol_type& sram_orgz_type,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module) {
|
||||||
switch(sram_orgz_type) {
|
switch(sram_orgz_type) {
|
||||||
case CONFIG_MEM_STANDALONE:
|
case CONFIG_MEM_STANDALONE:
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
@ -95,6 +132,9 @@ void print_verilog_top_testbench_config_protocol_port(std::fstream& fp,
|
||||||
case CONFIG_MEM_MEMORY_BANK:
|
case CONFIG_MEM_MEMORY_BANK:
|
||||||
/* TODO */
|
/* TODO */
|
||||||
break;
|
break;
|
||||||
|
case CONFIG_MEM_FRAME_BASED:
|
||||||
|
print_verilog_top_testbench_frame_decoder_port(fp, module_manager, top_module);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
"Invalid type of SRAM organization!\n");
|
"Invalid type of SRAM organization!\n");
|
||||||
|
@ -398,7 +438,8 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
|
||||||
fp << generate_verilog_port(VERILOG_PORT_REG, set_port) << ";" << std::endl;
|
fp << generate_verilog_port(VERILOG_PORT_REG, set_port) << ";" << std::endl;
|
||||||
|
|
||||||
/* Configuration ports depend on the organization of SRAMs */
|
/* Configuration ports depend on the organization of SRAMs */
|
||||||
print_verilog_top_testbench_config_protocol_port(fp, sram_orgz_type);
|
print_verilog_top_testbench_config_protocol_port(fp, sram_orgz_type,
|
||||||
|
module_manager, top_module);
|
||||||
|
|
||||||
/* Create a clock port if the benchmark have one but not in the default name!
|
/* Create a clock port if the benchmark have one but not in the default name!
|
||||||
* We will wire the clock directly to the operating clock directly
|
* We will wire the clock directly to the operating clock directly
|
||||||
|
@ -506,15 +547,72 @@ void print_verilog_top_testbench_load_bitstream_task_configuration_chain(std::fs
|
||||||
* It aims at avoid racing the programming clock (scan-chain data changes at the rising edge).
|
* It aims at avoid racing the programming clock (scan-chain data changes at the rising edge).
|
||||||
*/
|
*/
|
||||||
print_verilog_comment(fp, std::string("----- Task: input values during a programming clock cycle -----"));
|
print_verilog_comment(fp, std::string("----- Task: input values during a programming clock cycle -----"));
|
||||||
fp << "task " << std::string(TOP_TESTBENCH_CC_PROG_TASK_NAME) << ";" << std::endl;
|
fp << "task " << std::string(TOP_TESTBENCH_PROG_TASK_NAME) << ";" << std::endl;
|
||||||
fp << generate_verilog_port(VERILOG_PORT_INPUT, cc_head_value) << ";" << std::endl;
|
fp << generate_verilog_port(VERILOG_PORT_INPUT, cc_head_value) << ";" << std::endl;
|
||||||
fp << "\tbegin" << std::endl;
|
fp << "\tbegin" << std::endl;
|
||||||
fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl;
|
fp << "\t\t@(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl;
|
||||||
fp << "\t\t\t";
|
fp << "\t\t\t";
|
||||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, cc_head_port);
|
print_verilog_wire_connection(fp, cc_head_port, cc_head_value, false);
|
||||||
fp << " = ";
|
fp << std::endl;
|
||||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, cc_head_value);
|
|
||||||
fp << ";" << std::endl;
|
fp << "\tend" << std::endl;
|
||||||
|
fp << "endtask" << std::endl;
|
||||||
|
|
||||||
|
/* Add an empty line as splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* 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:
|
||||||
|
* 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
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
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);
|
||||||
|
|
||||||
|
BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Feed the address and data input at each rising edge of programming clock
|
||||||
|
* 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: address and data values during a programming clock cycle -----"));
|
||||||
|
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 << "\tbegin" << std::endl;
|
||||||
|
fp << "\t\t@(posedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ");" << std::endl;
|
||||||
|
|
||||||
|
fp << "\t\t\t";
|
||||||
|
print_verilog_wire_connection(fp, addr_port, addr_value, false);
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
fp << "\t\t\t";
|
||||||
|
print_verilog_wire_connection(fp, din_port, din_value, false);
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
fp << "\tend" << std::endl;
|
fp << "\tend" << std::endl;
|
||||||
fp << "endtask" << std::endl;
|
fp << "endtask" << std::endl;
|
||||||
|
@ -528,7 +626,9 @@ void print_verilog_top_testbench_load_bitstream_task_configuration_chain(std::fs
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static
|
static
|
||||||
void print_verilog_top_testbench_load_bitstream_task(std::fstream& fp,
|
void print_verilog_top_testbench_load_bitstream_task(std::fstream& fp,
|
||||||
const e_config_protocol_type& sram_orgz_type) {
|
const e_config_protocol_type& sram_orgz_type,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module) {
|
||||||
switch (sram_orgz_type) {
|
switch (sram_orgz_type) {
|
||||||
case CONFIG_MEM_STANDALONE:
|
case CONFIG_MEM_STANDALONE:
|
||||||
break;
|
break;
|
||||||
|
@ -540,6 +640,11 @@ void print_verilog_top_testbench_load_bitstream_task(std::fstream& fp,
|
||||||
dump_verilog_top_testbench_stimuli_serial_version_tasks_memory_bank(cur_sram_orgz_info, fp);
|
dump_verilog_top_testbench_stimuli_serial_version_tasks_memory_bank(cur_sram_orgz_info, fp);
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
|
case CONFIG_MEM_FRAME_BASED:
|
||||||
|
print_verilog_top_testbench_load_bitstream_task_frame_decoder(fp,
|
||||||
|
module_manager,
|
||||||
|
top_module);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
"Invalid type of SRAM organization!\n");
|
"Invalid type of SRAM organization!\n");
|
||||||
|
@ -721,7 +826,7 @@ void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp,
|
||||||
* We will visit the fabric bitstream in a reverse way
|
* We will visit the fabric bitstream in a reverse way
|
||||||
*/
|
*/
|
||||||
for (const FabricBitId& bit_id : fabric_bitstream.bits()) {
|
for (const FabricBitId& bit_id : fabric_bitstream.bits()) {
|
||||||
fp << "\t\t" << std::string(TOP_TESTBENCH_CC_PROG_TASK_NAME);
|
fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME);
|
||||||
fp << "(1'b" << (size_t)bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)) << ");" << std::endl;
|
fp << "(1'b" << (size_t)bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id)) << ");" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,6 +846,86 @@ void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp,
|
||||||
print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----");
|
print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Print stimulus for a FPGA fabric with a frame-based configuration protocol
|
||||||
|
* where configuration bits are programming in serial (one by one)
|
||||||
|
*
|
||||||
|
* We will use the programming task function created before
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const FabricBitstream& fabric_bitstream) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
valid_file_stream(fp);
|
||||||
|
|
||||||
|
/* Feed addresss and data input pair one by one
|
||||||
|
* Note: the first cycle is reserved for programming reset
|
||||||
|
* We should give dummy values
|
||||||
|
*/
|
||||||
|
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 << "\tbegin" << 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 << ";";
|
||||||
|
|
||||||
|
print_verilog_comment(fp, "----- Data-input port default input -----");
|
||||||
|
fp << "\t\t";
|
||||||
|
fp << generate_verilog_port_constant_values(din_port, initial_din_values);
|
||||||
|
fp << ";";
|
||||||
|
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Attention: the configuration chain protcol requires the last configuration bit is fed first
|
||||||
|
* We will visit the fabric bitstream in a reverse way
|
||||||
|
*/
|
||||||
|
for (const FabricBitId& bit_id : fabric_bitstream.bits()) {
|
||||||
|
fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME);
|
||||||
|
fp << "(" << addr_port.get_width() << "'b";
|
||||||
|
VTR_ASSERT(addr_port.get_width() == fabric_bitstream.bit_address(bit_id).size());
|
||||||
|
for (const size_t& addr_bit : fabric_bitstream.bit_address(bit_id)) {
|
||||||
|
fp << addr_bit;
|
||||||
|
}
|
||||||
|
fp << ", ";
|
||||||
|
fp <<"1'b";
|
||||||
|
if (true == fabric_bitstream.bit_din(bit_id)) {
|
||||||
|
fp << "1";
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT(false == fabric_bitstream.bit_din(bit_id));
|
||||||
|
fp << "0";
|
||||||
|
}
|
||||||
|
fp << ");" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
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 << "\tend" << std::endl;
|
||||||
|
print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----");
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Generate the stimuli for the top-level testbench
|
* Generate the stimuli for the top-level testbench
|
||||||
* The simulation consists of two phases: configuration phase and operation phase
|
* The simulation consists of two phases: configuration phase and operation phase
|
||||||
|
@ -750,6 +935,8 @@ void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp,
|
||||||
static
|
static
|
||||||
void print_verilog_top_testbench_bitstream(std::fstream& fp,
|
void print_verilog_top_testbench_bitstream(std::fstream& fp,
|
||||||
const e_config_protocol_type& sram_orgz_type,
|
const e_config_protocol_type& sram_orgz_type,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
const BitstreamManager& bitstream_manager,
|
const BitstreamManager& bitstream_manager,
|
||||||
const FabricBitstream& fabric_bitstream) {
|
const FabricBitstream& fabric_bitstream) {
|
||||||
/* Branch on the type of configuration protocol */
|
/* Branch on the type of configuration protocol */
|
||||||
|
@ -763,6 +950,11 @@ void print_verilog_top_testbench_bitstream(std::fstream& fp,
|
||||||
case CONFIG_MEM_MEMORY_BANK:
|
case CONFIG_MEM_MEMORY_BANK:
|
||||||
/* TODO */
|
/* TODO */
|
||||||
break;
|
break;
|
||||||
|
case CONFIG_MEM_FRAME_BASED:
|
||||||
|
print_verilog_top_testbench_frame_decoder_bitstream(fp,
|
||||||
|
module_manager, top_module,
|
||||||
|
fabric_bitstream);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||||
"Invalid SRAM organization type!\n");
|
"Invalid SRAM organization type!\n");
|
||||||
|
@ -875,10 +1067,13 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
|
||||||
explicit_port_mapping);
|
explicit_port_mapping);
|
||||||
|
|
||||||
/* Print tasks used for loading bitstreams */
|
/* Print tasks used for loading bitstreams */
|
||||||
print_verilog_top_testbench_load_bitstream_task(fp, sram_orgz_type);
|
print_verilog_top_testbench_load_bitstream_task(fp,
|
||||||
|
sram_orgz_type,
|
||||||
|
module_manager, top_module);
|
||||||
|
|
||||||
/* load bitstream to FPGA fabric in a configuration phase */
|
/* load bitstream to FPGA fabric in a configuration phase */
|
||||||
print_verilog_top_testbench_bitstream(fp, sram_orgz_type,
|
print_verilog_top_testbench_bitstream(fp, sram_orgz_type,
|
||||||
|
module_manager, top_module,
|
||||||
bitstream_manager, fabric_bitstream);
|
bitstream_manager, fabric_bitstream);
|
||||||
|
|
||||||
/* Add stimuli for reset, set, clock and iopad signals */
|
/* Add stimuli for reset, set, clock and iopad signals */
|
||||||
|
|
Loading…
Reference in New Issue