[Tool] Enable fast configuration when writing fabric bitstream

This commit is contained in:
tangxifan 2021-06-04 16:23:40 -06:00
parent 059e74b4ef
commit 061f832429
6 changed files with 199 additions and 1 deletions

View File

@ -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));
}

View File

@ -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");

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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 */