add fabric bitstream support for memory bank configuration protocol
This commit is contained in:
parent
0e16ee1030
commit
51e1559352
|
@ -15,6 +15,7 @@
|
||||||
#include "openfpga_reserved_words.h"
|
#include "openfpga_reserved_words.h"
|
||||||
#include "openfpga_naming.h"
|
#include "openfpga_naming.h"
|
||||||
|
|
||||||
|
#include "decoder_library_utils.h"
|
||||||
#include "bitstream_manager_utils.h"
|
#include "bitstream_manager_utils.h"
|
||||||
#include "build_fabric_bitstream.h"
|
#include "build_fabric_bitstream.h"
|
||||||
|
|
||||||
|
@ -73,6 +74,90 @@ void rec_build_module_fabric_dependent_chain_bitstream(const BitstreamManager& b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function aims to build a bitstream for memory-bank protocol
|
||||||
|
* It will walk through all the configurable children under a module
|
||||||
|
* in a recursive way, following a Depth-First Search (DFS) strategy
|
||||||
|
* For each configuration child, we use its instance name as a key to spot the
|
||||||
|
* configuration bits in bitstream manager.
|
||||||
|
* Note that it is guarentee that the instance name in module manager is
|
||||||
|
* consistent with the block names in bitstream manager
|
||||||
|
* We use this link to reorganize the bitstream in the sequence of memories as we stored
|
||||||
|
* in the configurable_children() and configurable_child_instances() of each module of module manager
|
||||||
|
*
|
||||||
|
* In such configuration organization, each memory cell has an unique index.
|
||||||
|
* Using this index, we can infer the address codes for both BL and WL decoders.
|
||||||
|
* Note that, we must get the number of BLs and WLs before using this function!
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamManager& bitstream_manager,
|
||||||
|
const ConfigBlockId& parent_block,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& parent_module,
|
||||||
|
const size_t& bl_addr_size,
|
||||||
|
const size_t& wl_addr_size,
|
||||||
|
const size_t& num_bls,
|
||||||
|
const size_t& num_wls,
|
||||||
|
size_t& cur_mem_index,
|
||||||
|
FabricBitstream& fabric_bitstream) {
|
||||||
|
|
||||||
|
/* Depth-first search: if we have any children in the parent_block,
|
||||||
|
* we dive to the next level first!
|
||||||
|
*/
|
||||||
|
if (0 < bitstream_manager.block_children(parent_block).size()) {
|
||||||
|
for (size_t child_id = 0; child_id < module_manager.configurable_children(parent_module).size(); ++child_id) {
|
||||||
|
ModuleId child_module = module_manager.configurable_children(parent_module)[child_id];
|
||||||
|
size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id];
|
||||||
|
/* Get the instance name and ensure it is not empty */
|
||||||
|
std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance);
|
||||||
|
|
||||||
|
/* Find the child block that matches the instance name! */
|
||||||
|
ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name);
|
||||||
|
/* We must have one valid block id! */
|
||||||
|
if (true != bitstream_manager.valid_block_id(child_block))
|
||||||
|
VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block));
|
||||||
|
|
||||||
|
/* Go recursively */
|
||||||
|
rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, child_block,
|
||||||
|
module_manager, child_module,
|
||||||
|
bl_addr_size, wl_addr_size,
|
||||||
|
num_bls, num_wls,
|
||||||
|
cur_mem_index,
|
||||||
|
fabric_bitstream);
|
||||||
|
}
|
||||||
|
/* Ensure that there should be no configuration bits in the parent block */
|
||||||
|
VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that, reach here, it means that this is a leaf node.
|
||||||
|
* We add the configuration bits to the fabric_bitstream,
|
||||||
|
* And then, we can return
|
||||||
|
*/
|
||||||
|
for (const ConfigBitId& config_bit : bitstream_manager.block_bits(parent_block)) {
|
||||||
|
FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit);
|
||||||
|
|
||||||
|
/* Find BL address */
|
||||||
|
size_t cur_bl_index = cur_mem_index / num_bls;
|
||||||
|
std::vector<size_t> bl_addr_bits_vec = itobin_vec(cur_bl_index, bl_addr_size);
|
||||||
|
|
||||||
|
/* Find WL address */
|
||||||
|
size_t cur_wl_index = cur_mem_index % num_wls;
|
||||||
|
std::vector<size_t> wl_addr_bits_vec = itobin_vec(cur_wl_index, wl_addr_size);
|
||||||
|
|
||||||
|
/* Set BL address */
|
||||||
|
fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec);
|
||||||
|
|
||||||
|
/* Set WL address */
|
||||||
|
fabric_bitstream.set_bit_wl_address(fabric_bit, wl_addr_bits_vec);
|
||||||
|
|
||||||
|
/* Set data input */
|
||||||
|
fabric_bitstream.set_bit_din(fabric_bit, bitstream_manager.bit_value(config_bit));
|
||||||
|
|
||||||
|
/* Increase the memory index */
|
||||||
|
cur_mem_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* This function aims to build a bitstream for frame-based configuration protocol
|
* This function aims to build a bitstream for frame-based configuration protocol
|
||||||
* It will walk through all the configurable children under a module
|
* It will walk through all the configurable children under a module
|
||||||
|
@ -287,6 +372,23 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CONFIG_MEM_MEMORY_BANK: {
|
case CONFIG_MEM_MEMORY_BANK: {
|
||||||
|
size_t cur_mem_index = 0;
|
||||||
|
/* Find BL address port size */
|
||||||
|
ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(MEMORY_BL_PORT_NAME));
|
||||||
|
BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port);
|
||||||
|
size_t num_bls = find_memory_decoder_data_size(bl_addr_port_info.get_width());
|
||||||
|
|
||||||
|
/* Find WL address port size */
|
||||||
|
ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(MEMORY_WL_PORT_NAME));
|
||||||
|
BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port);
|
||||||
|
size_t num_wls = find_memory_decoder_data_size(wl_addr_port_info.get_width());
|
||||||
|
|
||||||
|
rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, top_block,
|
||||||
|
module_manager, top_module,
|
||||||
|
bl_addr_port_info.get_width(),
|
||||||
|
wl_addr_port_info.get_width(),
|
||||||
|
num_bls, num_wls,
|
||||||
|
cur_mem_index, fabric_bitstream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CONFIG_MEM_FRAME_BASED: {
|
case CONFIG_MEM_FRAME_BASED: {
|
||||||
|
|
|
@ -31,7 +31,18 @@ std::vector<size_t> FabricBitstream::bit_address(const FabricBitId& bit_id) cons
|
||||||
/* Ensure a valid id */
|
/* Ensure a valid id */
|
||||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||||
|
|
||||||
return bit_addresses_[bit_id];
|
return bit_addresses_[bit_id][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const {
|
||||||
|
return bit_address(bit_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> FabricBitstream::bit_wl_address(const FabricBitId& bit_id) const {
|
||||||
|
/* Ensure a valid id */
|
||||||
|
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||||
|
|
||||||
|
return bit_addresses_[bit_id][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FabricBitstream::bit_din(const FabricBitId& bit_id) const {
|
bool FabricBitstream::bit_din(const FabricBitId& bit_id) const {
|
||||||
|
@ -58,7 +69,18 @@ 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<size_t>& 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][0] = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id,
|
||||||
|
const std::vector<size_t>& address) {
|
||||||
|
set_bit_address(bit_id, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id,
|
||||||
|
const std::vector<size_t>& address) {
|
||||||
|
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||||
|
bit_addresses_[bit_id][1] = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FabricBitstream::set_bit_din(const FabricBitId& bit_id,
|
void FabricBitstream::set_bit_din(const FabricBitId& bit_id,
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
* By using the link between ArchBitstreamManager and FabricBitstream,
|
* By using the link between ArchBitstreamManager and FabricBitstream,
|
||||||
* we can build a sequence of configuration bits to fit different configuration protocols.
|
* we can build a sequence of configuration bits to fit different configuration protocols.
|
||||||
*
|
*
|
||||||
* +----------------------+ +--------------------------+
|
* +----------------------+ +-------------------+
|
||||||
* | | ConfigBitId | |
|
* | | ConfigBitId | |
|
||||||
* | ArchBitstreamManager |---------------->| FabricBitstream |
|
* | ArchBitstreamManager |---------------->| FabricBitstream |
|
||||||
* | | | |
|
* | | | |
|
||||||
* +----------------------+ +--------------------------+
|
* +----------------------+ +-------------------+
|
||||||
*
|
*
|
||||||
* Restrictions:
|
* Restrictions:
|
||||||
* 1. Each block inside BitstreamManager should have only 1 parent block
|
* 1. Each block inside BitstreamManager should have only 1 parent block
|
||||||
|
@ -53,6 +53,8 @@ class FabricBitstream {
|
||||||
|
|
||||||
/* Find the address of bitstream */
|
/* Find the address of bitstream */
|
||||||
std::vector<size_t> bit_address(const FabricBitId& bit_id) const;
|
std::vector<size_t> bit_address(const FabricBitId& bit_id) const;
|
||||||
|
std::vector<size_t> bit_bl_address(const FabricBitId& bit_id) const;
|
||||||
|
std::vector<size_t> bit_wl_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;
|
||||||
|
@ -64,6 +66,12 @@ class FabricBitstream {
|
||||||
void set_bit_address(const FabricBitId& bit_id,
|
void set_bit_address(const FabricBitId& bit_id,
|
||||||
const std::vector<size_t>& address);
|
const std::vector<size_t>& address);
|
||||||
|
|
||||||
|
void set_bit_bl_address(const FabricBitId& bit_id,
|
||||||
|
const std::vector<size_t>& address);
|
||||||
|
|
||||||
|
void set_bit_wl_address(const FabricBitId& bit_id,
|
||||||
|
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);
|
||||||
|
|
||||||
|
@ -83,8 +91,10 @@ class FabricBitstream {
|
||||||
/* Address bits: this is designed for memory decoders
|
/* Address bits: this is designed for memory decoders
|
||||||
* 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
|
||||||
|
*
|
||||||
|
* We use a 2-element array, as we may have a BL address and a WL address
|
||||||
*/
|
*/
|
||||||
vtr::vector<FabricBitId, std::vector<size_t>> bit_addresses_;
|
vtr::vector<FabricBitId, std::array<std::vector<size_t>, 2>> 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_;
|
||||||
|
|
Loading…
Reference in New Issue