[Tool] Enable fast configuration when writing fabric bitstream
This commit is contained in:
parent
059e74b4ef
commit
061f832429
|
@ -91,6 +91,7 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
|
|||
CommandOptionId opt_verbose = cmd.option("verbose");
|
||||
CommandOptionId opt_file = cmd.option("file");
|
||||
CommandOptionId opt_file_format = cmd.option("format");
|
||||
CommandOptionId opt_fast_config = cmd.option("fast_configuration");
|
||||
|
||||
/* Write fabric bitstream if required */
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
@ -119,7 +120,9 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx,
|
|||
status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(),
|
||||
openfpga_ctx.fabric_bitstream(),
|
||||
openfpga_ctx.arch().config_protocol,
|
||||
openfpga_ctx.fabric_global_port_info(),
|
||||
cmd_context.option_value(cmd, opt_file),
|
||||
cmd_context.option_enable(cmd, opt_fast_config),
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
}
|
||||
|
||||
|
|
|
@ -151,6 +151,9 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell<Openf
|
|||
CommandOptionId opt_file_format = shell_cmd.add_option("format", false, "file format of fabric bitstream [plain_text|xml]. Default: plain_text");
|
||||
shell_cmd.set_option_require_value(opt_file_format, openfpga::OPT_STRING);
|
||||
|
||||
/* Add an option '--fast_configuration' */
|
||||
shell_cmd.add_option("fast_configuration", false, "Reduce the size of bitstream to be downloaded");
|
||||
|
||||
/* Add an option '--verbose' */
|
||||
shell_cmd.add_option("verbose", false, "Enable verbose output");
|
||||
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that are used to create
|
||||
* an auto-check top-level testbench for a FPGA fabric
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "fabric_global_port_info_utils.h"
|
||||
#include "fast_configuration.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* Identify if fast configuration is applicable base on the availability
|
||||
* of programming reset and programming set ports of the FPGA fabric
|
||||
*******************************************************************/
|
||||
bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports) {
|
||||
/* Preparation: find all the reset/set ports for programming usage */
|
||||
std::vector<FabricGlobalPortId> global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports);
|
||||
std::vector<FabricGlobalPortId> global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports);
|
||||
|
||||
/* Identify if we can apply fast configuration */
|
||||
if (global_prog_set_ports.empty() && global_prog_reset_ports.empty()) {
|
||||
VTR_LOG_WARN("None of global reset and set ports are defined for programming purpose. Fast configuration is not applicable\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* 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
|
||||
*******************************************************************/
|
||||
bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const BitstreamManager& bitstream_manager,
|
||||
const FabricBitstream& fabric_bitstream) {
|
||||
/* Preparation: find all the reset/set ports for programming usage */
|
||||
std::vector<FabricGlobalPortId> global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports);
|
||||
std::vector<FabricGlobalPortId> global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* If both types of ports are not defined, the fast configuration is not applicable */
|
||||
VTR_ASSERT(!global_prog_set_ports.empty() && !global_prog_reset_ports.empty());
|
||||
bool bit_value_to_skip = false;
|
||||
|
||||
VTR_LOG("Both reset and set ports are defined for programming controls, selecting the best-fit one...\n");
|
||||
|
||||
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 configuration protocol type!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
/* By default, we prefer to skip zeros (when the numbers are the same */
|
||||
if (num_ones_to_skip > num_zeros_to_skip) {
|
||||
VTR_LOG("Will use set signal in fast configuration\n");
|
||||
bit_value_to_skip = true;
|
||||
} else {
|
||||
VTR_LOG("Will use reset signal in fast configuration\n");
|
||||
}
|
||||
|
||||
return bit_value_to_skip;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef FAST_CONFIGURATION_H
|
||||
#define FAST_CONFIGURATION_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "fabric_global_port_info.h"
|
||||
#include "config_protocol.h"
|
||||
#include "bitstream_manager.h"
|
||||
#include "fabric_bitstream.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
bool is_fast_configuration_applicable(const FabricGlobalPortInfo& global_ports);
|
||||
|
||||
bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const BitstreamManager& bitstream_manager,
|
||||
const FabricBitstream& fabric_bitstream);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "openfpga_naming.h"
|
||||
|
||||
#include "fast_configuration.h"
|
||||
#include "bitstream_manager_utils.h"
|
||||
#include "fabric_bitstream_utils.h"
|
||||
#include "write_text_fabric_bitstream.h"
|
||||
|
@ -118,6 +119,8 @@ int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp,
|
|||
*******************************************************************/
|
||||
static
|
||||
int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp,
|
||||
const bool& fast_configuration,
|
||||
const bool& bit_value_to_skip,
|
||||
const BitstreamManager& bitstream_manager,
|
||||
const FabricBitstream& fabric_bitstream) {
|
||||
int status = 0;
|
||||
|
@ -125,7 +128,18 @@ int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp,
|
|||
size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream);
|
||||
ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream);
|
||||
|
||||
for (size_t ibit = 0; ibit < regional_bitstream_max_size; ++ibit) {
|
||||
/* 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);
|
||||
|
||||
VTR_LOG("Fast configuration will skip %g% (%lu/%lu) of configuration bitstream.\n",
|
||||
100. * (float) num_bits_to_skip / (float) regional_bitstream_max_size,
|
||||
num_bits_to_skip, regional_bitstream_max_size);
|
||||
|
||||
for (size_t ibit = num_bits_to_skip; ibit < regional_bitstream_max_size; ++ibit) {
|
||||
for (const auto& region_bitstream : regional_bitstreams) {
|
||||
fp << region_bitstream[ibit];
|
||||
}
|
||||
|
@ -214,7 +228,9 @@ int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp,
|
|||
int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
|
||||
const FabricBitstream& fabric_bitstream,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const std::string& fname,
|
||||
const bool& fast_configuration,
|
||||
const bool& verbose) {
|
||||
/* Ensure that we have a valid file name */
|
||||
if (true == fname.empty()) {
|
||||
|
@ -230,6 +246,19 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage
|
|||
|
||||
check_file_stream(fname.c_str(), fp);
|
||||
|
||||
bool apply_fast_configuration = is_fast_configuration_applicable(global_ports);
|
||||
if (fast_configuration && apply_fast_configuration != fast_configuration) {
|
||||
VTR_LOG_WARN("Disable fast configuration even it is enabled by user\n");
|
||||
}
|
||||
|
||||
bool bit_value_to_skip = false;
|
||||
if (apply_fast_configuration) {
|
||||
bit_value_to_skip = find_bit_value_to_skip_for_fast_configuration(config_protocol.type(),
|
||||
global_ports,
|
||||
bitstream_manager,
|
||||
fabric_bitstream);
|
||||
}
|
||||
|
||||
/* Output fabric bitstream to the file */
|
||||
int status = 0;
|
||||
switch (config_protocol.type()) {
|
||||
|
@ -241,6 +270,8 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage
|
|||
break;
|
||||
case CONFIG_MEM_SCAN_CHAIN:
|
||||
status = write_config_chain_fabric_bitstream_to_text_file(fp,
|
||||
apply_fast_configuration,
|
||||
bit_value_to_skip,
|
||||
bitstream_manager,
|
||||
fabric_bitstream);
|
||||
break;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "bitstream_manager.h"
|
||||
#include "fabric_bitstream.h"
|
||||
#include "config_protocol.h"
|
||||
#include "fabric_global_port_info.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
|
@ -20,7 +21,9 @@ namespace openfpga {
|
|||
int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager,
|
||||
const FabricBitstream& fabric_bitstream,
|
||||
const ConfigProtocol& config_protocol,
|
||||
const FabricGlobalPortInfo& global_ports,
|
||||
const std::string& fname,
|
||||
const bool& fast_configuration,
|
||||
const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
Loading…
Reference in New Issue