use char in fabric bitstream to save memory footprint
This commit is contained in:
parent
405824081b
commit
9f19c36a89
|
@ -73,4 +73,34 @@ std::vector<size_t> itobin_vec(const size_t& in_int,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Converter an integer to a binary vector
|
||||
* For example:
|
||||
* Input integer: 4
|
||||
* Binary length : 3
|
||||
* Output:
|
||||
* index | 0 | 1 | 2
|
||||
* ret | 0 | 0 | 1
|
||||
*
|
||||
* This function is optimized to return a vector of char
|
||||
* which has a smaller memory footprint than size_t
|
||||
********************************************************************/
|
||||
std::vector<char> itobin_charvec(const size_t& in_int,
|
||||
const size_t& bin_len) {
|
||||
std::vector<char> ret(bin_len, '0');
|
||||
|
||||
/* Make sure we do not have any overflow! */
|
||||
VTR_ASSERT ( (in_int < pow(2., bin_len)) );
|
||||
|
||||
size_t temp = in_int;
|
||||
for (size_t i = 0; i < bin_len; i++) {
|
||||
if (1 == temp % 2) {
|
||||
ret[i] = '1'; /* Keep a good sequence of bits */
|
||||
}
|
||||
temp = temp / 2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -18,6 +18,9 @@ std::vector<size_t> ito1hot_vec(const size_t& in_int,
|
|||
std::vector<size_t> itobin_vec(const size_t& in_int,
|
||||
const size_t& bin_len);
|
||||
|
||||
std::vector<char> itobin_charvec(const size_t& in_int,
|
||||
const size_t& bin_len);
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -158,11 +158,11 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana
|
|||
|
||||
/* Find BL address */
|
||||
size_t cur_bl_index = std::floor(cur_mem_index / num_bls);
|
||||
std::vector<size_t> bl_addr_bits_vec = itobin_vec(cur_bl_index, bl_addr_size);
|
||||
std::vector<char> bl_addr_bits_vec = itobin_charvec(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);
|
||||
std::vector<char> wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size);
|
||||
|
||||
/* Set BL address */
|
||||
fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec);
|
||||
|
@ -206,7 +206,7 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
|
|||
const std::vector<ConfigBlockId>& parent_blocks,
|
||||
const ModuleManager& module_manager,
|
||||
const std::vector<ModuleId>& parent_modules,
|
||||
const std::vector<size_t>& addr_code,
|
||||
const std::vector<char>& addr_code,
|
||||
FabricBitstream& fabric_bitstream) {
|
||||
|
||||
/* Depth-first search: if we have any children in the parent_block,
|
||||
|
@ -272,13 +272,13 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
|
|||
child_modules.push_back(child_module);
|
||||
|
||||
/* Set address, apply binary conversion from the first to the last element in the address list */
|
||||
std::vector<size_t> child_addr_code = addr_code;
|
||||
std::vector<char> child_addr_code = addr_code;
|
||||
|
||||
if (true == add_addr_code) {
|
||||
/* 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 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<char> addr_bits_vec = itobin_charvec(child_id, decoder_addr_port.get_width());
|
||||
|
||||
child_addr_code.insert(child_addr_code.begin(), addr_bits_vec.begin(), addr_bits_vec.end());
|
||||
|
||||
|
@ -316,7 +316,7 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
|
|||
const ModulePortId& child_addr_port_id = module_manager.find_module_port(child_module, std::string(DECODER_ADDRESS_PORT_NAME));
|
||||
const BasicPort& child_addr_port = module_manager.module_port(child_module, child_addr_port_id);
|
||||
if (0 < max_child_addr_code_size - child_addr_port.get_width()) {
|
||||
std::vector<size_t> dummy_codes(max_child_addr_code_size - child_addr_port.get_width(), 0);
|
||||
std::vector<char> dummy_codes(max_child_addr_code_size - child_addr_port.get_width(), '0');
|
||||
child_addr_code.insert(child_addr_code.begin(), dummy_codes.begin(), dummy_codes.end());
|
||||
}
|
||||
}
|
||||
|
@ -349,9 +349,9 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b
|
|||
for (size_t ibit = 0; ibit < bitstream_manager.block_bits(parent_blocks.back()).size(); ++ibit) {
|
||||
|
||||
ConfigBitId config_bit = bitstream_manager.block_bits(parent_blocks.back())[ibit];
|
||||
std::vector<size_t> addr_bits_vec = itobin_vec(ibit, decoder_addr_port.get_width());
|
||||
std::vector<char> addr_bits_vec = itobin_charvec(ibit, decoder_addr_port.get_width());
|
||||
|
||||
std::vector<size_t> child_addr_code = addr_code;
|
||||
std::vector<char> child_addr_code = addr_code;
|
||||
|
||||
child_addr_code.insert(child_addr_code.begin(), addr_bits_vec.begin(), addr_bits_vec.end());
|
||||
|
||||
|
@ -429,7 +429,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc
|
|||
std::vector<ConfigBlockId>(1, top_block),
|
||||
module_manager,
|
||||
std::vector<ModuleId>(1, top_module),
|
||||
std::vector<size_t>(),
|
||||
std::vector<char>(),
|
||||
fabric_bitstream);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -27,25 +27,25 @@ ConfigBitId FabricBitstream::config_bit(const FabricBitId& bit_id) const {
|
|||
return config_bit_ids_[bit_id];
|
||||
}
|
||||
|
||||
std::vector<size_t> FabricBitstream::bit_address(const FabricBitId& bit_id) const {
|
||||
std::vector<char> FabricBitstream::bit_address(const FabricBitId& bit_id) const {
|
||||
/* Ensure a valid id */
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
|
||||
return bit_addresses_[bit_id][0];
|
||||
}
|
||||
|
||||
std::vector<size_t> FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const {
|
||||
std::vector<char> 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 {
|
||||
std::vector<char> 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 {
|
||||
char FabricBitstream::bit_din(const FabricBitId& bit_id) const {
|
||||
/* Ensure a valid id */
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
|
||||
|
@ -74,24 +74,24 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) {
|
|||
}
|
||||
|
||||
void FabricBitstream::set_bit_address(const FabricBitId& bit_id,
|
||||
const std::vector<size_t>& address) {
|
||||
const std::vector<char>& address) {
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
bit_addresses_[bit_id][0] = address;
|
||||
}
|
||||
|
||||
void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id,
|
||||
const std::vector<size_t>& address) {
|
||||
const std::vector<char>& address) {
|
||||
set_bit_address(bit_id, address);
|
||||
}
|
||||
|
||||
void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id,
|
||||
const std::vector<size_t>& address) {
|
||||
const std::vector<char>& address) {
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
bit_addresses_[bit_id][1] = address;
|
||||
}
|
||||
|
||||
void FabricBitstream::set_bit_din(const FabricBitId& bit_id,
|
||||
const bool& din) {
|
||||
const char& din) {
|
||||
VTR_ASSERT(true == valid_bit_id(bit_id));
|
||||
bit_dins_[bit_id] = din;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ void FabricBitstream::reverse() {
|
|||
/******************************************************************************
|
||||
* Public Validators
|
||||
******************************************************************************/
|
||||
bool FabricBitstream::valid_bit_id(const FabricBitId& bit_id) const {
|
||||
char FabricBitstream::valid_bit_id(const FabricBitId& bit_id) const {
|
||||
return (size_t(bit_id) < bit_ids_.size()) && (bit_id == bit_ids_[bit_id]);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,12 +52,12 @@ class FabricBitstream {
|
|||
ConfigBitId config_bit(const FabricBitId& bit_id) const;
|
||||
|
||||
/* Find the address of bitstream */
|
||||
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;
|
||||
std::vector<char> bit_address(const FabricBitId& bit_id) const;
|
||||
std::vector<char> bit_bl_address(const FabricBitId& bit_id) const;
|
||||
std::vector<char> bit_wl_address(const FabricBitId& bit_id) const;
|
||||
|
||||
/* Find the data-in of bitstream */
|
||||
bool bit_din(const FabricBitId& bit_id) const;
|
||||
char bit_din(const FabricBitId& bit_id) const;
|
||||
|
||||
public: /* Public Mutators */
|
||||
/* Reserve config bits */
|
||||
|
@ -67,16 +67,16 @@ class FabricBitstream {
|
|||
FabricBitId add_bit(const ConfigBitId& config_bit_id);
|
||||
|
||||
void set_bit_address(const FabricBitId& bit_id,
|
||||
const std::vector<size_t>& address);
|
||||
const std::vector<char>& address);
|
||||
|
||||
void set_bit_bl_address(const FabricBitId& bit_id,
|
||||
const std::vector<size_t>& address);
|
||||
const std::vector<char>& address);
|
||||
|
||||
void set_bit_wl_address(const FabricBitId& bit_id,
|
||||
const std::vector<size_t>& address);
|
||||
const std::vector<char>& address);
|
||||
|
||||
void set_bit_din(const FabricBitId& bit_id,
|
||||
const bool& din);
|
||||
const char& din);
|
||||
|
||||
/* Reverse bit sequence of the fabric bitstream
|
||||
* This is required by configuration chain protocol
|
||||
|
@ -84,7 +84,7 @@ class FabricBitstream {
|
|||
void reverse();
|
||||
|
||||
public: /* Public Validators */
|
||||
bool valid_bit_id(const FabricBitId& bit_id) const;
|
||||
char valid_bit_id(const FabricBitId& bit_id) const;
|
||||
|
||||
private: /* Internal data */
|
||||
/* Unique id of a bit in the Bitstream */
|
||||
|
@ -97,10 +97,10 @@ class FabricBitstream {
|
|||
*
|
||||
* We use a 2-element array, as we may have a BL address and a WL address
|
||||
*/
|
||||
vtr::vector<FabricBitId, std::array<std::vector<size_t>, 2>> bit_addresses_;
|
||||
vtr::vector<FabricBitId, std::array<std::vector<char>, 2>> bit_addresses_;
|
||||
|
||||
/* Data input (Din) bits: this is designed for memory decoders */
|
||||
vtr::vector<FabricBitId, bool> bit_dins_;
|
||||
vtr::vector<FabricBitId, char> bit_dins_;
|
||||
};
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -50,11 +50,11 @@ int write_fabric_config_bit_to_text_file(std::fstream& fp,
|
|||
fp << bitstream_manager.bit_value(fabric_bitstream.config_bit(fabric_bit));
|
||||
break;
|
||||
case CONFIG_MEM_MEMORY_BANK: {
|
||||
for (const size_t& addr_bit : fabric_bitstream.bit_bl_address(fabric_bit)) {
|
||||
for (const char& addr_bit : fabric_bitstream.bit_bl_address(fabric_bit)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
write_space_to_file(fp, 1);
|
||||
for (const size_t& addr_bit : fabric_bitstream.bit_wl_address(fabric_bit)) {
|
||||
for (const char& addr_bit : fabric_bitstream.bit_wl_address(fabric_bit)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
write_space_to_file(fp, 1);
|
||||
|
@ -63,7 +63,7 @@ int write_fabric_config_bit_to_text_file(std::fstream& fp,
|
|||
break;
|
||||
}
|
||||
case CONFIG_MEM_FRAME_BASED: {
|
||||
for (const size_t& addr_bit : fabric_bitstream.bit_address(fabric_bit)) {
|
||||
for (const char& addr_bit : fabric_bitstream.bit_address(fabric_bit)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
write_space_to_file(fp, 1);
|
||||
|
|
|
@ -1223,14 +1223,14 @@ void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp,
|
|||
fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME);
|
||||
fp << "(" << bl_addr_port.get_width() << "'b";
|
||||
VTR_ASSERT(bl_addr_port.get_width() == fabric_bitstream.bit_bl_address(bit_id).size());
|
||||
for (const size_t& addr_bit : fabric_bitstream.bit_bl_address(bit_id)) {
|
||||
for (const char& addr_bit : fabric_bitstream.bit_bl_address(bit_id)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
|
||||
fp << ", ";
|
||||
fp << wl_addr_port.get_width() << "'b";
|
||||
VTR_ASSERT(wl_addr_port.get_width() == fabric_bitstream.bit_wl_address(bit_id).size());
|
||||
for (const size_t& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) {
|
||||
for (const char& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
|
||||
|
@ -1319,7 +1319,7 @@ void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp,
|
|||
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)) {
|
||||
for (const char& addr_bit : fabric_bitstream.bit_address(bit_id)) {
|
||||
fp << addr_bit;
|
||||
}
|
||||
fp << ", ";
|
||||
|
|
Loading…
Reference in New Issue