start integrating fpga_bitstream. Bring data structures online
This commit is contained in:
parent
9583731531
commit
2d17395e13
|
@ -0,0 +1,28 @@
|
|||
/********************************************************************
|
||||
* This file includes functions to build bitstream database
|
||||
*******************************************************************/
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_time.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
#include "build_device_bitstream.h"
|
||||
#include "openfpga_bitstream.h"
|
||||
|
||||
/* Include global variables of VPR */
|
||||
#include "globals.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* A wrapper function to call the fabric_verilog function of FPGA-Verilog
|
||||
*******************************************************************/
|
||||
void fpga_bitstream(OpenfpgaContext& openfpga_ctx,
|
||||
const Command& cmd, const CommandContext& cmd_context) {
|
||||
|
||||
CommandOptionId opt_verbose = cmd.option("verbose");
|
||||
|
||||
openfpga_ctx.mutable_bitstream_manager() = build_device_bitstream(g_vpr_ctx, openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose));
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef OPENFPGA_BITSTREAM_H
|
||||
#define OPENFPGA_BITSTREAM_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "command.h"
|
||||
#include "command_context.h"
|
||||
#include "openfpga_context.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
void fpga_bitstream(OpenfpgaContext& openfpga_ctx,
|
||||
const Command& cmd, const CommandContext& cmd_context);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -5,6 +5,7 @@
|
|||
* - repack : create physical pbs and redo packing
|
||||
*******************************************************************/
|
||||
#include "openfpga_repack.h"
|
||||
#include "openfpga_bitstream.h"
|
||||
#include "openfpga_bitstream_command.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
|
@ -33,6 +34,25 @@ void add_openfpga_bitstream_commands(openfpga::Shell<OpenfpgaContext>& shell) {
|
|||
std::vector<ShellCommandId> cmd_dependency_repack;
|
||||
cmd_dependency_repack.push_back(shell_cmd_build_fabric_id);
|
||||
shell.set_command_dependency(shell_cmd_repack_id, cmd_dependency_repack);
|
||||
|
||||
/********************************
|
||||
* Command 'fpga_bitstream'
|
||||
*/
|
||||
Command shell_cmd_fpga_bitstream("fpga_bitstream");
|
||||
/* Add an option '--verbose' */
|
||||
shell_cmd_fpga_bitstream.add_option("fabric_dependent", false, "Enable the bitstream construction for the FPGA fabric");
|
||||
shell_cmd_fpga_bitstream.add_option("verbose", false, "Enable verbose output");
|
||||
|
||||
/* Add command 'fpga_bitstream' to the Shell */
|
||||
ShellCommandId shell_cmd_fpga_bitstream_id = shell.add_command(shell_cmd_fpga_bitstream, "Build bitstream database");
|
||||
shell.set_command_class(shell_cmd_fpga_bitstream_id, openfpga_bitstream_cmd_class);
|
||||
shell.set_command_execute_function(shell_cmd_fpga_bitstream_id, fpga_bitstream);
|
||||
|
||||
/* The 'fpga_bitstream' command should NOT be executed before 'repack' */
|
||||
std::vector<ShellCommandId> cmd_dependency_fpga_bitstream;
|
||||
cmd_dependency_fpga_bitstream.push_back(shell_cmd_repack_id);
|
||||
shell.set_command_dependency(shell_cmd_fpga_bitstream_id, cmd_dependency_fpga_bitstream);
|
||||
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "tile_direct.h"
|
||||
#include "module_manager.h"
|
||||
#include "openfpga_flow_manager.h"
|
||||
#include "bitstream_manager.h"
|
||||
#include "device_rr_gsb.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -52,6 +53,7 @@ class OpenfpgaContext : public Context {
|
|||
const openfpga::TileDirect& tile_direct() const { return tile_direct_; }
|
||||
const openfpga::ModuleManager& module_graph() const { return module_graph_; }
|
||||
const openfpga::FlowManager& flow_manager() const { return flow_manager_; }
|
||||
const openfpga::BitstreamManager& bitstream_manager() const { return bitstream_manager_; }
|
||||
public: /* Public mutators */
|
||||
openfpga::Arch& mutable_arch() { return arch_; }
|
||||
openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() { return vpr_device_annotation_; }
|
||||
|
@ -63,6 +65,7 @@ class OpenfpgaContext : public Context {
|
|||
openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; }
|
||||
openfpga::ModuleManager& mutable_module_graph() { return module_graph_; }
|
||||
openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; }
|
||||
openfpga::BitstreamManager& mutable_bitstream_manager() { return bitstream_manager_; }
|
||||
private: /* Internal data */
|
||||
/* Data structure to store information from read_openfpga_arch library */
|
||||
openfpga::Arch arch_;
|
||||
|
@ -90,6 +93,9 @@ class OpenfpgaContext : public Context {
|
|||
|
||||
/* Fabric module graph */
|
||||
openfpga::ModuleManager module_graph_;
|
||||
|
||||
/* Bitstream database */
|
||||
openfpga::BitstreamManager bitstream_manager_;
|
||||
|
||||
/* Flow status */
|
||||
openfpga::FlowManager flow_manager_;
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
/******************************************************************************
|
||||
* This file includes member functions for data structure BitstreamManager
|
||||
******************************************************************************/
|
||||
#include <algorithm>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "bitstream_manager.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/**************************************************
|
||||
* Public Accessors : Aggregates
|
||||
*************************************************/
|
||||
/* Find all the configuration bits */
|
||||
BitstreamManager::config_bit_range BitstreamManager::bits() const {
|
||||
return vtr::make_range(bit_ids_.begin(), bit_ids_.end());
|
||||
}
|
||||
|
||||
/* Find all the configuration blocks */
|
||||
BitstreamManager::config_block_range BitstreamManager::blocks() const {
|
||||
return vtr::make_range(block_ids_.begin(), block_ids_.end());
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public Accessors
|
||||
******************************************************************************/
|
||||
bool BitstreamManager::bit_value(const ConfigBitId& bit_id) const {
|
||||
/* Ensure a valid id */
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
|
||||
return bit_values_[bit_id];
|
||||
}
|
||||
|
||||
std::string BitstreamManager::block_name(const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
return block_names_[block_id];
|
||||
}
|
||||
|
||||
ConfigBlockId BitstreamManager::block_parent(const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
return parent_block_ids_[block_id];
|
||||
}
|
||||
|
||||
std::vector<ConfigBlockId> BitstreamManager::block_children(const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
return child_block_ids_[block_id];
|
||||
}
|
||||
|
||||
std::vector<ConfigBitId> BitstreamManager::block_bits(const ConfigBlockId& block_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
return block_bit_ids_[block_id];
|
||||
}
|
||||
|
||||
ConfigBlockId BitstreamManager::bit_parent_block(const ConfigBitId& bit_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
|
||||
return bit_parent_block_ids_[bit_id];
|
||||
}
|
||||
|
||||
size_t BitstreamManager::bit_index_in_parent_block(const ConfigBitId& bit_id) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
|
||||
ConfigBlockId bit_parent_block = bit_parent_block_ids_[bit_id];
|
||||
|
||||
VTR_ASSERT(true == valid_block_id(bit_parent_block));
|
||||
|
||||
for (size_t index = 0; index < block_bits(bit_parent_block).size(); ++index) {
|
||||
if (bit_id == block_bits(bit_parent_block)[index]) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found, return in valid value */
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
/* Find the child block in a bitstream manager with a given name */
|
||||
ConfigBlockId BitstreamManager::find_child_block(const ConfigBlockId& block_id,
|
||||
const std::string& child_block_name) const {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block_id));
|
||||
|
||||
std::vector<ConfigBlockId> candidates;
|
||||
|
||||
for (const ConfigBlockId& child : block_children(block_id)) {
|
||||
if (0 == child_block_name.compare(block_name(child))) {
|
||||
candidates.push_back(child);
|
||||
}
|
||||
}
|
||||
|
||||
/* We should have 0 or 1 candidate! */
|
||||
VTR_ASSERT(0 == candidates.size() || 1 == candidates.size());
|
||||
if (0 == candidates.size()) {
|
||||
/* Not found, return an invalid value */
|
||||
return ConfigBlockId::INVALID();
|
||||
}
|
||||
return candidates[0];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public Mutators
|
||||
******************************************************************************/
|
||||
ConfigBitId BitstreamManager::add_bit(const bool& bit_value) {
|
||||
ConfigBitId bit = ConfigBitId(bit_ids_.size());
|
||||
/* Add a new bit, and allocate associated data structures */
|
||||
bit_ids_.push_back(bit);
|
||||
bit_values_.push_back(bit_value);
|
||||
shared_config_bit_values_.emplace_back();
|
||||
bit_parent_block_ids_.push_back(ConfigBlockId::INVALID());
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
ConfigBlockId BitstreamManager::add_block(const std::string& block_name) {
|
||||
ConfigBlockId block = ConfigBlockId(block_ids_.size());
|
||||
/* Add a new bit, and allocate associated data structures */
|
||||
block_ids_.push_back(block);
|
||||
block_names_.push_back(block_name);
|
||||
block_bit_ids_.emplace_back();
|
||||
parent_block_ids_.push_back(ConfigBlockId::INVALID());
|
||||
child_block_ids_.emplace_back();
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block) {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(parent_block));
|
||||
VTR_ASSERT(true == valid_block_id(child_block));
|
||||
|
||||
/* We should have only a parent block for each block! */
|
||||
VTR_ASSERT(ConfigBlockId::INVALID() == parent_block_ids_[child_block]);
|
||||
|
||||
/* Ensure the child block is not in the list of children of the parent block */
|
||||
std::vector<ConfigBlockId>::iterator it = std::find(child_block_ids_[parent_block].begin(), child_block_ids_[parent_block].end(), child_block);
|
||||
VTR_ASSERT(it == child_block_ids_[parent_block].end());
|
||||
|
||||
/* Add the child_block to the parent_block */
|
||||
child_block_ids_[parent_block].push_back(child_block);
|
||||
/* Register the block in the parent of the block */
|
||||
parent_block_ids_[child_block] = parent_block;
|
||||
}
|
||||
|
||||
void BitstreamManager::add_bit_to_block(const ConfigBlockId& block, const ConfigBitId& bit) {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_block_id(block));
|
||||
VTR_ASSERT(true == valid_bit_id(bit));
|
||||
|
||||
/* We should have only a parent block for each bit! */
|
||||
VTR_ASSERT(ConfigBlockId::INVALID() == bit_parent_block_ids_[bit]);
|
||||
|
||||
/* Add the bit to the block */
|
||||
block_bit_ids_[block].push_back(bit);
|
||||
/* Register the block in the parent of the bit */
|
||||
bit_parent_block_ids_[bit] = block;
|
||||
}
|
||||
|
||||
void BitstreamManager::add_shared_config_bit_values(const ConfigBitId& bit, const std::vector<bool>& shared_config_bits) {
|
||||
/* Ensure the input ids are valid */
|
||||
VTR_ASSERT(true == valid_bit_id(bit));
|
||||
|
||||
shared_config_bit_values_[bit] = shared_config_bits;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public Validators
|
||||
******************************************************************************/
|
||||
bool BitstreamManager::valid_bit_id(const ConfigBitId& bit_id) const {
|
||||
return (size_t(bit_id) < bit_ids_.size()) && (bit_id == bit_ids_[bit_id]);
|
||||
}
|
||||
|
||||
bool BitstreamManager::valid_block_id(const ConfigBlockId& block_id) const {
|
||||
return (size_t(block_id) < block_ids_.size()) && (block_id == block_ids_[block_id]);
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,133 @@
|
|||
/******************************************************************************
|
||||
* This file introduces a data structure to store bitstream-related information
|
||||
*
|
||||
* General concept
|
||||
* ---------------
|
||||
* The idea is to create a unified data structure that stores all the configuration bits
|
||||
* with proper annotation to which modules in FPGA fabric it belongs to.
|
||||
* 1. It can be easily organized in fabric-dependent representation
|
||||
* (generate a sequence of bitstream which exactly fit the configuration protocol of FPGA fabric)
|
||||
* 2. Or it can be easily organized in fabric-independent representation (think about XML file)
|
||||
*
|
||||
* Cross-reference
|
||||
* ---------------
|
||||
* May be used only when you want to bind the bitstream to a specific FPGA fabric!
|
||||
* If you do so, please make sure the block name is exactly same as the instance name
|
||||
* of a child module in ModuleManager!!!
|
||||
* The configurable modules/instances in module manager are arranged
|
||||
* in the sequence to fit different configuration protocol.
|
||||
* By using the link between ModuleManager and BitstreamManager,
|
||||
* we can build a sequence of configuration bits to fit different configuration protocols.
|
||||
*
|
||||
* +------------------+ +-----------------+
|
||||
* | | block_name == instance_name | |
|
||||
* | BitstreamManager |-------------------------------->| ModuleManager |
|
||||
* | | | |
|
||||
* +------------------+ +-----------------+
|
||||
*
|
||||
* Restrictions:
|
||||
* 1. Each block inside BitstreamManager should have only 1 parent block
|
||||
* and multiple child block
|
||||
* 2. Each bit inside BitstreamManager should have only 1 parent block
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BITSTREAM_MANAGER_H
|
||||
#define BITSTREAM_MANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "vtr_vector.h"
|
||||
|
||||
#include "bitstream_manager_fwd.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
class BitstreamManager {
|
||||
public: /* Types and ranges */
|
||||
typedef vtr::vector<ConfigBitId, ConfigBitId>::const_iterator config_bit_iterator;
|
||||
typedef vtr::vector<ConfigBlockId, ConfigBlockId>::const_iterator config_block_iterator;
|
||||
|
||||
typedef vtr::Range<config_bit_iterator> config_bit_range;
|
||||
typedef vtr::Range<config_block_iterator> config_block_range;
|
||||
|
||||
public: /* Public aggregators */
|
||||
/* Find all the configuration bits */
|
||||
config_bit_range bits() const;
|
||||
|
||||
config_block_range blocks() const;
|
||||
|
||||
public: /* Public Accessors */
|
||||
/* Find the value of bitstream */
|
||||
bool bit_value(const ConfigBitId& bit_id) const;
|
||||
|
||||
/* Find a name of a block */
|
||||
std::string block_name(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find the parent of a block */
|
||||
ConfigBlockId block_parent(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find the children of a block */
|
||||
std::vector<ConfigBlockId> block_children(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find all the bits that belong to a block */
|
||||
std::vector<ConfigBitId> block_bits(const ConfigBlockId& block_id) const;
|
||||
|
||||
/* Find the parent block of a bit */
|
||||
ConfigBlockId bit_parent_block(const ConfigBitId& bit_id) const;
|
||||
|
||||
/* Find the index of a configuration bit in its parent block */
|
||||
size_t bit_index_in_parent_block(const ConfigBitId& bit_id) const;
|
||||
|
||||
/* Find the child block in a bitstream manager with a given name */
|
||||
ConfigBlockId find_child_block(const ConfigBlockId& block_id, const std::string& child_block_name) const;
|
||||
|
||||
public: /* Public Mutators */
|
||||
/* Add a new configuration bit to the bitstream manager */
|
||||
ConfigBitId add_bit(const bool& bit_value);
|
||||
|
||||
/* Add a new block of configuration bits to the bitstream manager */
|
||||
ConfigBlockId add_block(const std::string& block_name);
|
||||
|
||||
/* Set a block as a child block of another */
|
||||
void add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block);
|
||||
|
||||
/* Add a configuration bit to a block */
|
||||
void add_bit_to_block(const ConfigBlockId& block, const ConfigBitId& bit);
|
||||
|
||||
/* Add share configuration bits to a configuration bit */
|
||||
void add_shared_config_bit_values(const ConfigBitId& bit, const std::vector<bool>& shared_config_bits);
|
||||
|
||||
public: /* Public Validators */
|
||||
bool valid_bit_id(const ConfigBitId& bit_id) const;
|
||||
|
||||
bool valid_block_id(const ConfigBlockId& block_id) const;
|
||||
|
||||
private: /* Internal data */
|
||||
/* Unique id of a block of bits in the Bitstream */
|
||||
vtr::vector<ConfigBlockId, ConfigBlockId> block_ids_;
|
||||
vtr::vector<ConfigBlockId, std::vector<ConfigBitId>> block_bit_ids_;
|
||||
|
||||
/* Back-annotation for the bits */
|
||||
/* Parent block of a bit in the Bitstream
|
||||
* For each bit, the block name can be designed to be same as the instance name in a module
|
||||
* to reflect its position in the module tree (ModuleManager)
|
||||
* Note that the blocks here all unique, unlike ModuleManager where modules can be instanciated
|
||||
* Therefore, this block graph can be considered as a flattened graph of ModuleGraph
|
||||
*/
|
||||
vtr::vector<ConfigBlockId, std::string> block_names_;
|
||||
vtr::vector<ConfigBlockId, ConfigBlockId> parent_block_ids_;
|
||||
vtr::vector<ConfigBlockId, std::vector<ConfigBlockId>> child_block_ids_;
|
||||
|
||||
/* Unique id of a bit in the Bitstream */
|
||||
vtr::vector<ConfigBitId, ConfigBitId> bit_ids_;
|
||||
vtr::vector<ConfigBitId, ConfigBlockId> bit_parent_block_ids_;
|
||||
/* value of a bit in the Bitstream */
|
||||
vtr::vector<ConfigBitId, bool> bit_values_;
|
||||
/* value of a shared configuration bits in the Bitstream */
|
||||
vtr::vector<ConfigBitId, std::vector<bool>> shared_config_bit_values_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,25 @@
|
|||
/**************************************************
|
||||
* This file includes only declarations for
|
||||
* the data structures for bitstream database
|
||||
* Please refer to bitstream_manager.h for more details
|
||||
*************************************************/
|
||||
#ifndef BITSTREAM_MANAGER_FWD_H
|
||||
#define BITSTREAM_MANAGER_FWD_H
|
||||
|
||||
#include "vtr_strong_id.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/* Strong Ids for BitstreamContext */
|
||||
struct config_block_id_tag;
|
||||
struct config_bit_id_tag;
|
||||
|
||||
typedef vtr::StrongId<config_block_id_tag> ConfigBlockId;
|
||||
typedef vtr::StrongId<config_bit_id_tag> ConfigBitId;
|
||||
|
||||
class BitstreamManager;
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
/********************************************************************
|
||||
* This file includes most utilized functions for data structure
|
||||
* BitstreamManager
|
||||
*
|
||||
* Note: These functions are not generic enough so that they
|
||||
* should NOT be a member function!
|
||||
*******************************************************************/
|
||||
#include <algorithm>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "bitstream_manager_utils.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* Recursively find the hierarchy of a block of bitstream manager
|
||||
* Return a vector of the block ids, where the top-level block
|
||||
* locates in the head, while the leaf block locates in the tail
|
||||
* top, next, ... , block
|
||||
*******************************************************************/
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_block_hierarchy(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block) {
|
||||
std::vector<ConfigBlockId> block_hierarchy;
|
||||
ConfigBlockId temp_block = block;
|
||||
|
||||
/* Generate a tree of parent block */
|
||||
while (true == bitstream_manager.valid_block_id(temp_block)) {
|
||||
block_hierarchy.push_back(temp_block);
|
||||
/* Go to upper level */
|
||||
temp_block = bitstream_manager.block_parent(temp_block);
|
||||
}
|
||||
|
||||
/* Reverse the vector, so that top block stay in the first */
|
||||
std::reverse(block_hierarchy.begin(), block_hierarchy.end());
|
||||
|
||||
return block_hierarchy;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Find all the top-level blocks in a bitstream manager,
|
||||
* which have no parents
|
||||
*******************************************************************/
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_top_blocks(const BitstreamManager& bitstream_manager) {
|
||||
std::vector<ConfigBlockId> top_blocks;
|
||||
for (const ConfigBlockId& blk : bitstream_manager.blocks()) {
|
||||
if (ConfigBlockId::INVALID() != bitstream_manager.block_parent(blk)) {
|
||||
continue;
|
||||
}
|
||||
top_blocks.push_back(blk);
|
||||
}
|
||||
|
||||
return top_blocks;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef BITSTREAM_MANAGER_UTILS_H
|
||||
#define BITSTREAM_MANAGER_UTILS_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
#include "bitstream_manager.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_block_hierarchy(const BitstreamManager& bitstream_manager,
|
||||
const ConfigBlockId& block);
|
||||
|
||||
std::vector<ConfigBlockId> find_bitstream_manager_top_blocks(const BitstreamManager& bitstream_manager);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
/********************************************************************
|
||||
* This file includes functions to build bitstream from a mapped
|
||||
* FPGA fabric.
|
||||
* We decode the bitstream from configuration of routing multiplexers
|
||||
* and Look-Up Tables (LUTs) which locate in CLBs and global routing architecture
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
#include "openfpga_naming.h"
|
||||
|
||||
//#include "build_grid_bitstream.h"
|
||||
//#include "build_routing_bitstream.h"
|
||||
#include "build_device_bitstream.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* A top-level function to build a bistream from the FPGA device
|
||||
* 1. It will organize the bitstream w.r.t. the hierarchy of module graphs
|
||||
* describing the FPGA fabric
|
||||
* 2. It will decode configuration bits from routing multiplexers used in
|
||||
* global routing architecture
|
||||
* 3. It will decode configuration bits from routing multiplexers and LUTs
|
||||
* used in CLBs
|
||||
*
|
||||
* Note: this function create a bitstream which is binding to the module graphs
|
||||
* of the FPGA fabric that FPGA-X2P generates!
|
||||
* But it can be used to output a generic bitstream for VPR mapping FPGA
|
||||
*******************************************************************/
|
||||
BitstreamManager build_device_bitstream(const VprContext& vpr_ctx,
|
||||
const OpenfpgaContext& openfpga_ctx,
|
||||
const bool& verbose) {
|
||||
|
||||
std::string timer_message = std::string("\nBuild fabric-independent bitstream for implementation '") + vpr_ctx.atom().nlist.netlist_name() + std::string("'\n");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Bitstream manager to be built */
|
||||
BitstreamManager bitstream_manager;
|
||||
|
||||
/* Assign the SRAM model applied to the FPGA fabric */
|
||||
CircuitModelId sram_model = openfpga_ctx.arch().config_protocol.memory_model();
|
||||
VTR_ASSERT(true == openfpga_ctx.arch().circuit_lib.valid_model_id(sram_model));
|
||||
|
||||
/* Create the top-level block for bitstream
|
||||
* This is related to the top-level module of fpga
|
||||
*/
|
||||
std::string top_block_name = generate_fpga_top_module_name();
|
||||
ConfigBlockId top_block = bitstream_manager.add_block(top_block_name);
|
||||
|
||||
/* Create bitstream from grids */
|
||||
VTR_LOGV(verbose, "Building grid bitstream...\n");
|
||||
//build_grid_bitstream(bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, device_size, grids);
|
||||
VTR_LOGV(verbose, "Done\n");
|
||||
|
||||
/* Create bitstream from routing architectures */
|
||||
VTR_LOGV(verbose, "Building routing bitstream...\n");
|
||||
//build_routing_bitstream(bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, rr_switches, L_rr_node, L_device_rr_gsb);
|
||||
VTR_LOGV(verbose, "Done\n");
|
||||
|
||||
return bitstream_manager;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef BUILD_DEVICE_BITSTREAM_H
|
||||
#define BUILD_DEVICE_BITSTREAM_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
#include "vpr_context.h"
|
||||
#include "openfpga_context.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
BitstreamManager build_device_bitstream(const VprContext& vpr_ctx,
|
||||
const OpenfpgaContext& openfpga_ctx,
|
||||
const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue