From ac22ba28e451ea7ffe7b3be277f7ede6e98edcd3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 12:26:59 -0600 Subject: [PATCH 01/25] add config protocol type information to simulation ini file --- openfpga/src/fpga_verilog/simulation_info_writer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga/src/fpga_verilog/simulation_info_writer.cpp b/openfpga/src/fpga_verilog/simulation_info_writer.cpp index de9f5f6af..134b34f0a 100644 --- a/openfpga/src/fpga_verilog/simulation_info_writer.cpp +++ b/openfpga/src/fpga_verilog/simulation_info_writer.cpp @@ -78,6 +78,7 @@ void print_verilog_simulation_info(const std::string& ini_fname, ini["SIMULATION_DECK"]["VERILOG_PATH "] = std::string(src_dir); ini["SIMULATION_DECK"]["VERILOG_FILE1"] = std::string(DEFINES_VERILOG_FILE_NAME); ini["SIMULATION_DECK"]["VERILOG_FILE2"] = std::string(circuit_name + std::string(TOP_INCLUDE_NETLIST_FILE_NAME_POSTFIX)); + ini["SIMULATION_DECK"]["CONFIG_PROTOCOL"] = std::string(CONFIG_PROTOCOL_TYPE_STRING[config_protocol_type]); /* Information required by UVM */ if (CONFIG_MEM_FRAME_BASED == config_protocol_type) { From b85af57971d96d326eb156a4b0549717d2dc57bc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 12:39:18 -0600 Subject: [PATCH 02/25] optimizing fabric bitsteream memory footprint --- openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp | 4 ++++ openfpga/src/fpga_bitstream/fabric_bitstream.cpp | 7 +++++++ openfpga/src/fpga_bitstream/fabric_bitstream.h | 3 +++ 3 files changed, 14 insertions(+) diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 240f19028..417959fd5 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -495,6 +495,10 @@ FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstre VTR_ASSERT(1 == top_block.size()); VTR_ASSERT(0 == top_module_name.compare(bitstream_manager.block_name(top_block[0]))); + /* Reserve bits before build-up */ + fabric_bitstream.reserve(bitstream_manager.bits().size()); + + /* Start build-up formally */ build_module_fabric_dependent_bitstream(config_protocol, bitstream_manager, top_block[0], module_manager, top_module, diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 1e318a530..01c064549 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -55,6 +55,13 @@ bool FabricBitstream::bit_din(const FabricBitId& bit_id) const { /****************************************************************************** * Public Mutators ******************************************************************************/ +void FabricBitstream::reserve(const size_t& num_bits) { + bit_ids_.reserve(num_bits); + config_bit_ids_.reserve(num_bits); + bit_addresses_.reserve(num_bits); + bit_dins_.reserve(num_bits); +} + FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) { FabricBitId bit = FabricBitId(bit_ids_.size()); /* Add a new bit, and allocate associated data structures */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index 519330dae..8554ea83c 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -60,6 +60,9 @@ class FabricBitstream { bool bit_din(const FabricBitId& bit_id) const; public: /* Public Mutators */ + /* Reserve config bits */ + void reserve(const size_t& num_bits); + /* Add a new configuration bit to the bitstream manager */ FabricBitId add_bit(const ConfigBitId& config_bit_id); From 405824081b53c5496e13ff995149e8f285627924 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 15:28:52 -0600 Subject: [PATCH 03/25] reserve configuration blocks and bits in bitstream manager builder to be memory efficient --- .../src/bitstream_manager.cpp | 7 ++ .../libfpgabitstream/src/bitstream_manager.h | 3 + .../fpga_bitstream/build_device_bitstream.cpp | 99 ++++++++++++++++++- 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index 66b4d1f23..c08aecb02 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -154,6 +154,13 @@ void BitstreamManager::reserve_blocks(const size_t& num_blocks) { child_block_ids_.reserve(num_blocks); } +void BitstreamManager::reserve_bits(const size_t& num_bits) { + bit_ids_.reserve(num_bits); + bit_values_.reserve(num_bits); + shared_config_bit_values_.reserve(num_bits); + bit_parent_block_ids_.reserve(num_bits); +} + ConfigBlockId BitstreamManager::create_block() { ConfigBlockId block = ConfigBlockId(block_ids_.size()); /* Add a new bit, and allocate associated data structures */ diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index 71bd63b43..c3a9372ee 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -98,6 +98,9 @@ class BitstreamManager { /* Reserve memory for a number of clocks */ void reserve_blocks(const size_t& num_blocks); + /* Reserve memory for a number of bits */ + void reserve_bits(const size_t& num_bits); + /* Create a new block of configuration bits */ ConfigBlockId create_block(); diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 6d13dfe6f..59dd9c788 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -20,6 +20,82 @@ /* begin namespace openfpga */ namespace openfpga { +/******************************************************************** + * Estimate the number of blocks to be added to the whole device bitstream + * This function will recursively walk through the module graph + * from the specified top module and count the number of configurable children + * which are the blocks that will be added to the bitstream manager + *******************************************************************/ +static +size_t rec_estimate_device_bitstream_num_blocks(const ModuleManager& module_manager, + const ModuleId& top_module) { + size_t num_blocks = 0; + + /* Those child modules which have no children are + * actually configurable memory elements + * We skip them in couting + */ + if (0 == module_manager.configurable_children(top_module).size()) { + return 0; + } + + size_t num_configurable_children = module_manager.configurable_children(top_module).size(); + for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { + ModuleId child_module = module_manager.configurable_children(top_module)[ichild]; + num_blocks += rec_estimate_device_bitstream_num_blocks(module_manager, child_module); + } + + /* Add the number of blocks at current level */ + num_blocks++; + + return num_blocks; +} + +/******************************************************************** + * Estimate the number of configuration bits to be added to the whole device bitstream + * This function will recursively walk through the module graph + * from the specified top module and count the number of leaf configurable children + * which are the bits that will be added to the bitstream manager + *******************************************************************/ +static +size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manager, + const ModuleId& top_module, + const e_config_protocol_type& config_protocol_type) { + size_t num_bits = 0; + + /* If a child module has no configurable children, this is a leaf node + * We can count it in. Otherwise, we should go recursively. + */ + if (0 == module_manager.configurable_children(top_module).size()) { + return 1; + } + + size_t num_configurable_children = module_manager.configurable_children(top_module).size(); + /* Frame-based configuration protocol will have 1 decoder + * if there are more than 1 configurable children + */ + if ( (CONFIG_MEM_FRAME_BASED == config_protocol_type) + && (2 <= num_configurable_children)) { + num_configurable_children--; + } + + /* Memory configuration protocol will have 2 decoders + * at the top-level + */ + if (CONFIG_MEM_MEMORY_BANK == config_protocol_type) { + std::string top_block_name = generate_fpga_top_module_name(); + if (top_module == module_manager.find_module(top_block_name)) { + num_configurable_children -= 2; + } + } + for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { + ModuleId child_module = module_manager.configurable_children(top_module)[ichild]; + num_bits += rec_estimate_device_bitstream_num_bits(module_manager, child_module, config_protocol_type); + } + + return num_bits; +} + /******************************************************************** * 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 @@ -52,6 +128,21 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, */ std::string top_block_name = generate_fpga_top_module_name(); ConfigBlockId top_block = bitstream_manager.add_block(top_block_name); + const ModuleId& top_module = openfpga_ctx.module_graph().find_module(top_block_name); + VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module)); + + /* Estimate the number of blocks to be added to the database */ + size_t num_blocks_to_reserve = rec_estimate_device_bitstream_num_blocks(openfpga_ctx.module_graph(), + top_module); + bitstream_manager.reserve_blocks(num_blocks_to_reserve); + VTR_LOGV(verbose, "Reserved %lu configurable blocks\n", num_blocks_to_reserve); + + /* Estimate the number of bits to be added to the database */ + size_t num_bits_to_reserve = rec_estimate_device_bitstream_num_bits(openfpga_ctx.module_graph(), + top_module, + openfpga_ctx.arch().config_protocol.type()); + bitstream_manager.reserve_bits(num_bits_to_reserve); + VTR_LOGV(verbose, "Reserved %lu configuration bits\n", num_bits_to_reserve); /* Create bitstream from grids */ VTR_LOGV(verbose, "Building grid bitstream...\n"); @@ -80,7 +171,13 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, openfpga_ctx.device_rr_gsb()); VTR_LOGV(verbose, "Done\n"); - VTR_LOGV(verbose, "Decoded %lu configuration bits\n", bitstream_manager.bits().size()); + VTR_LOGV(verbose, + "Decoded %lu configuration bits into %lu blocks\n", + bitstream_manager.bits().size(), + bitstream_manager.blocks().size()); + + //VTR_ASSERT(num_blocks_to_reserve == bitstream_manager.blocks().size()); + //VTR_ASSERT(num_bits_to_reserve == bitstream_manager.bits().size()); return bitstream_manager; } From 9f19c36a891b69eec8712bef1612a248cbf49a26 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 15:56:50 -0600 Subject: [PATCH 04/25] use char in fabric bitstream to save memory footprint --- .../libopenfpgautil/src/openfpga_decode.cpp | 30 +++++++++++++++++++ .../libopenfpgautil/src/openfpga_decode.h | 3 ++ .../fpga_bitstream/build_fabric_bitstream.cpp | 18 +++++------ .../src/fpga_bitstream/fabric_bitstream.cpp | 18 +++++------ .../src/fpga_bitstream/fabric_bitstream.h | 22 +++++++------- .../fabric_bitstream_writer.cpp | 6 ++-- .../fpga_verilog/verilog_top_testbench.cpp | 6 ++-- 7 files changed, 68 insertions(+), 35 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp index 06b3487b0..fb0e32a37 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp @@ -73,4 +73,34 @@ std::vector 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 itobin_charvec(const size_t& in_int, + const size_t& bin_len) { + std::vector 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 */ diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.h b/libopenfpga/libopenfpgautil/src/openfpga_decode.h index c79254f63..064717fbc 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.h @@ -18,6 +18,9 @@ std::vector ito1hot_vec(const size_t& in_int, std::vector itobin_vec(const size_t& in_int, const size_t& bin_len); +std::vector itobin_charvec(const size_t& in_int, + const size_t& bin_len); + } /* namespace openfpga ends */ #endif diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 417959fd5..1c78f8fc5 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -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 bl_addr_bits_vec = itobin_vec(cur_bl_index, bl_addr_size); + std::vector 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 wl_addr_bits_vec = itobin_vec(cur_wl_index, wl_addr_size); + std::vector 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& parent_blocks, const ModuleManager& module_manager, const std::vector& parent_modules, - const std::vector& addr_code, + const std::vector& 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 child_addr_code = addr_code; + std::vector 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 addr_bits_vec = itobin_vec(child_id, decoder_addr_port.get_width()); + std::vector 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 dummy_codes(max_child_addr_code_size - child_addr_port.get_width(), 0); + std::vector 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 addr_bits_vec = itobin_vec(ibit, decoder_addr_port.get_width()); + std::vector addr_bits_vec = itobin_charvec(ibit, decoder_addr_port.get_width()); - std::vector child_addr_code = addr_code; + std::vector 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(1, top_block), module_manager, std::vector(1, top_module), - std::vector(), + std::vector(), fabric_bitstream); break; } diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 01c064549..bc6b13d09 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -27,25 +27,25 @@ ConfigBitId FabricBitstream::config_bit(const FabricBitId& bit_id) const { return config_bit_ids_[bit_id]; } -std::vector FabricBitstream::bit_address(const FabricBitId& bit_id) const { +std::vector 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 FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const { +std::vector FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const { return bit_address(bit_id); } -std::vector FabricBitstream::bit_wl_address(const FabricBitId& bit_id) const { +std::vector 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& address) { + const std::vector& 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& address) { + const std::vector& address) { set_bit_address(bit_id, address); } void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id, - const std::vector& address) { + const std::vector& 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]); } diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index 8554ea83c..9c8f492b5 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -52,12 +52,12 @@ class FabricBitstream { ConfigBitId config_bit(const FabricBitId& bit_id) const; /* Find the address of bitstream */ - std::vector bit_address(const FabricBitId& bit_id) const; - std::vector bit_bl_address(const FabricBitId& bit_id) const; - std::vector bit_wl_address(const FabricBitId& bit_id) const; + std::vector bit_address(const FabricBitId& bit_id) const; + std::vector bit_bl_address(const FabricBitId& bit_id) const; + std::vector 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& address); + const std::vector& address); void set_bit_bl_address(const FabricBitId& bit_id, - const std::vector& address); + const std::vector& address); void set_bit_wl_address(const FabricBitId& bit_id, - const std::vector& address); + const std::vector& 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, 2>> bit_addresses_; + vtr::vector, 2>> bit_addresses_; /* Data input (Din) bits: this is designed for memory decoders */ - vtr::vector bit_dins_; + vtr::vector bit_dins_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp index 6317fd47d..60e626692 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp @@ -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); diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index c985c48f0..9bf51d6a4 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -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 << ", "; From 9608cefa8650b3630f05482f476448dc1cb19ecd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 16:08:50 -0600 Subject: [PATCH 05/25] remove id vector in fabric bitstream database and replace with more memory efficient implementation --- .../src/fpga_bitstream/fabric_bitstream.cpp | 18 ++++-- .../src/fpga_bitstream/fabric_bitstream.h | 61 ++++++++++++++++++- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index bc6b13d09..962fe02f6 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -9,12 +9,20 @@ /* begin namespace openfpga */ namespace openfpga { +/************************************************** + * Public Constructor + *************************************************/ +FabricBitstream::FabricBitstream() { + num_bits_ = 0; +} + /************************************************** * Public Accessors : Aggregates *************************************************/ /* Find all the configuration bits */ FabricBitstream::fabric_bit_range FabricBitstream::bits() const { - return vtr::make_range(bit_ids_.begin(), bit_ids_.end()); + return vtr::make_range(fabric_bit_iterator(FabricBitId(0), invalid_bit_ids_), + fabric_bit_iterator(FabricBitId(num_bits_), invalid_bit_ids_)); } /****************************************************************************** @@ -56,16 +64,15 @@ char FabricBitstream::bit_din(const FabricBitId& bit_id) const { * Public Mutators ******************************************************************************/ void FabricBitstream::reserve(const size_t& num_bits) { - bit_ids_.reserve(num_bits); config_bit_ids_.reserve(num_bits); bit_addresses_.reserve(num_bits); bit_dins_.reserve(num_bits); } FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) { - FabricBitId bit = FabricBitId(bit_ids_.size()); + FabricBitId bit = FabricBitId(num_bits_); /* Add a new bit, and allocate associated data structures */ - bit_ids_.push_back(bit); + num_bits_++; config_bit_ids_.push_back(config_bit_id); bit_addresses_.emplace_back(); bit_dins_.push_back(false); @@ -97,7 +104,6 @@ void FabricBitstream::set_bit_din(const FabricBitId& bit_id, } void FabricBitstream::reverse() { - std::reverse(config_bit_ids_.begin(), config_bit_ids_.end()); std::reverse(bit_addresses_.begin(), bit_addresses_.end()); std::reverse(bit_dins_.begin(), bit_dins_.end()); } @@ -106,7 +112,7 @@ void FabricBitstream::reverse() { * Public Validators ******************************************************************************/ char FabricBitstream::valid_bit_id(const FabricBitId& bit_id) const { - return (size_t(bit_id) < bit_ids_.size()) && (bit_id == bit_ids_[bit_id]); + return (size_t(bit_id) < num_bits_); } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index 9c8f492b5..ee0699b2d 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -29,6 +29,8 @@ #define FABRIC_BITSTREAM_H #include +#include +#include #include "vtr_vector.h" #include "bitstream_manager_fwd.h" @@ -38,11 +40,65 @@ namespace openfpga { class FabricBitstream { + public: /* Type implementations */ + /* + * This class (forward delcared above) is a template used to represent a lazily calculated + * iterator of the specified ID type. The key assumption made is that the ID space is + * contiguous and can be walked by incrementing the underlying ID value. To account for + * invalid IDs, it keeps a reference to the invalid ID set and returns ID::INVALID() for + * ID values in the set. + * + * It is used to lazily create an iteration range (e.g. as returned by RRGraph::edges() RRGraph::nodes()) + * just based on the count of allocated elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), + * and the set of any invalid IDs (i.e. RRGraph::invalid_node_ids_, RRGraph::invalid_edge_ids_). + */ + template + class lazy_id_iterator : public std::iterator { + public: + //Since we pass ID as a template to std::iterator we need to use an explicit 'typename' + //to bring the value_type and iterator names into scope + typedef typename std::iterator::value_type value_type; + typedef typename std::iterator::iterator iterator; + + lazy_id_iterator(value_type init, const std::unordered_set& invalid_ids) + : value_(init) + , invalid_ids_(invalid_ids) {} + + //Advance to the next ID value + iterator operator++() { + value_ = ID(size_t(value_) + 1); + return *this; + } + + //Advance to the previous ID value + iterator operator--() { + value_ = ID(size_t(value_) - 1); + return *this; + } + + //Dereference the iterator + value_type operator*() const { return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; } + + friend bool operator==(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return lhs.value_ == rhs.value_; } + friend bool operator!=(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return !(lhs == rhs); } + + private: + value_type value_; + const std::unordered_set& invalid_ids_; + }; + public: /* Types and ranges */ - typedef vtr::vector::const_iterator fabric_bit_iterator; + //Lazy iterator utility forward declaration + template + class lazy_id_iterator; + + typedef lazy_id_iterator fabric_bit_iterator; typedef vtr::Range fabric_bit_range; + public: /* Public constructor */ + FabricBitstream(); + public: /* Public aggregators */ /* Find all the configuration bits */ fabric_bit_range bits() const; @@ -88,7 +144,8 @@ class FabricBitstream { private: /* Internal data */ /* Unique id of a bit in the Bitstream */ - vtr::vector bit_ids_; + size_t num_bits_; + std::unordered_set invalid_bit_ids_; vtr::vector config_bit_ids_; /* Address bits: this is designed for memory decoders From e82d0d9f340f20feea64c46a393dadf32b3b46e2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 16:18:32 -0600 Subject: [PATCH 06/25] drop id list in bitstream manager to save memory usage --- .../src/bitstream_manager.cpp | 28 +++++--- .../libfpgabitstream/src/bitstream_manager.h | 66 +++++++++++++++++-- 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index c08aecb02..bc185a1e0 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -9,17 +9,27 @@ /* begin namespace openfpga */ namespace openfpga { +/************************************************** + * Public Constructors + *************************************************/ +BitstreamManager::BitstreamManager() { + num_blocks_ = 0; + num_bits_ = 0; +} + /************************************************** * 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()); + return vtr::make_range(config_bit_iterator(ConfigBitId(0), invalid_bit_ids_), + config_bit_iterator(ConfigBitId(num_bits_), invalid_bit_ids_)); } /* Find all the configuration blocks */ BitstreamManager::config_block_range BitstreamManager::blocks() const { - return vtr::make_range(block_ids_.begin(), block_ids_.end()); + return vtr::make_range(config_block_iterator(ConfigBlockId(0), invalid_block_ids_), + config_block_iterator(ConfigBlockId(num_blocks_), invalid_block_ids_)); } /****************************************************************************** @@ -133,9 +143,9 @@ std::vector BitstreamManager::block_output_net_ids(const ConfigBloc * Public Mutators ******************************************************************************/ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { - ConfigBitId bit = ConfigBitId(bit_ids_.size()); + ConfigBitId bit = ConfigBitId(num_bits_); /* Add a new bit, and allocate associated data structures */ - bit_ids_.push_back(bit); + num_bits_++; bit_values_.push_back(bit_value); shared_config_bit_values_.emplace_back(); bit_parent_block_ids_.push_back(ConfigBlockId::INVALID()); @@ -144,7 +154,6 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { } void BitstreamManager::reserve_blocks(const size_t& num_blocks) { - block_ids_.reserve(num_blocks); block_names_.reserve(num_blocks); block_bit_ids_.reserve(num_blocks); block_path_ids_.reserve(num_blocks); @@ -155,16 +164,15 @@ void BitstreamManager::reserve_blocks(const size_t& num_blocks) { } void BitstreamManager::reserve_bits(const size_t& num_bits) { - bit_ids_.reserve(num_bits); bit_values_.reserve(num_bits); shared_config_bit_values_.reserve(num_bits); bit_parent_block_ids_.reserve(num_bits); } ConfigBlockId BitstreamManager::create_block() { - ConfigBlockId block = ConfigBlockId(block_ids_.size()); + ConfigBlockId block = ConfigBlockId(num_blocks_); /* Add a new bit, and allocate associated data structures */ - block_ids_.push_back(block); + num_blocks_++; block_names_.emplace_back(); block_bit_ids_.emplace_back(); block_path_ids_.push_back(-2); @@ -259,11 +267,11 @@ void BitstreamManager::add_shared_config_bit_values(const ConfigBitId& bit, cons * 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]); + return (size_t(bit_id) < num_bits_); } bool BitstreamManager::valid_block_id(const ConfigBlockId& block_id) const { - return (size_t(block_id) < block_ids_.size()) && (block_id == block_ids_[block_id]); + return (size_t(block_id) < num_blocks_); } bool BitstreamManager::valid_block_path_id(const ConfigBlockId& block_id) const { diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index c3a9372ee..ce741df92 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -36,6 +36,8 @@ #include #include +#include +#include #include "vtr_vector.h" #include "bitstream_manager_fwd.h" @@ -44,9 +46,63 @@ namespace openfpga { class BitstreamManager { + public: /* Type implementations */ + /* + * This class (forward delcared above) is a template used to represent a lazily calculated + * iterator of the specified ID type. The key assumption made is that the ID space is + * contiguous and can be walked by incrementing the underlying ID value. To account for + * invalid IDs, it keeps a reference to the invalid ID set and returns ID::INVALID() for + * ID values in the set. + * + * It is used to lazily create an iteration range (e.g. as returned by RRGraph::edges() RRGraph::nodes()) + * just based on the count of allocated elements (i.e. RRGraph::num_nodes_ or RRGraph::num_edges_), + * and the set of any invalid IDs (i.e. RRGraph::invalid_node_ids_, RRGraph::invalid_edge_ids_). + */ + template + class lazy_id_iterator : public std::iterator { + public: + //Since we pass ID as a template to std::iterator we need to use an explicit 'typename' + //to bring the value_type and iterator names into scope + typedef typename std::iterator::value_type value_type; + typedef typename std::iterator::iterator iterator; + + lazy_id_iterator(value_type init, const std::unordered_set& invalid_ids) + : value_(init) + , invalid_ids_(invalid_ids) {} + + //Advance to the next ID value + iterator operator++() { + value_ = ID(size_t(value_) + 1); + return *this; + } + + //Advance to the previous ID value + iterator operator--() { + value_ = ID(size_t(value_) - 1); + return *this; + } + + //Dereference the iterator + value_type operator*() const { return (invalid_ids_.count(value_)) ? ID::INVALID() : value_; } + + friend bool operator==(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return lhs.value_ == rhs.value_; } + friend bool operator!=(const lazy_id_iterator lhs, const lazy_id_iterator rhs) { return !(lhs == rhs); } + + private: + value_type value_; + const std::unordered_set& invalid_ids_; + }; + + public: /* Public constructor */ + BitstreamManager(); + public: /* Types and ranges */ - typedef vtr::vector::const_iterator config_bit_iterator; - typedef vtr::vector::const_iterator config_block_iterator; + //Lazy iterator utility forward declaration + template + class lazy_id_iterator; + + typedef lazy_id_iterator config_bit_iterator; + typedef lazy_id_iterator config_block_iterator; typedef vtr::Range config_bit_range; typedef vtr::Range config_block_range; @@ -138,7 +194,8 @@ class BitstreamManager { private: /* Internal data */ /* Unique id of a block of bits in the Bitstream */ - vtr::vector block_ids_; + size_t num_blocks_; + std::unordered_set invalid_block_ids_; vtr::vector> block_bit_ids_; /* Back-annotation for the bits */ @@ -175,7 +232,8 @@ class BitstreamManager { vtr::vector> block_output_net_ids_; /* Unique id of a bit in the Bitstream */ - vtr::vector bit_ids_; + size_t num_bits_; + std::unordered_set invalid_bit_ids_; vtr::vector bit_parent_block_ids_; /* value of a bit in the Bitstream */ vtr::vector bit_values_; From adee87569d211ac1d1290cbe4e49081c059535f5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 16:25:36 -0600 Subject: [PATCH 07/25] enable fast bitstream building by creating a frame view of fabric --- openfpga/src/base/openfpga_build_fabric.cpp | 2 ++ openfpga/src/base/openfpga_setup_command.cpp | 3 +++ openfpga/src/fabric/build_device_module.cpp | 3 ++- openfpga/src/fabric/build_device_module.h | 1 + openfpga/src/fabric/build_top_module.cpp | 28 ++++++++++++-------- openfpga/src/fabric/build_top_module.h | 1 + 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index adbe8fce6..df407e949 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -67,6 +67,7 @@ void compress_routing_hierarchy(OpenfpgaContext& openfpga_ctx, int build_fabric(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { + CommandOptionId opt_frame_view = cmd.option("frame_view"); CommandOptionId opt_compress_routing = cmd.option("compress_routing"); CommandOptionId opt_duplicate_grid_pin = cmd.option("duplicate_grid_pin"); CommandOptionId opt_gen_random_fabric_key = cmd.option("generate_random_fabric_key"); @@ -96,6 +97,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, openfpga_ctx.mutable_decoder_lib(), const_cast(openfpga_ctx), g_vpr_ctx.device(), + cmd_context.option_enable(cmd, opt_frame_view), cmd_context.option_enable(cmd, opt_compress_routing), cmd_context.option_enable(cmd, opt_duplicate_grid_pin), predefined_fabric_key, diff --git a/openfpga/src/base/openfpga_setup_command.cpp b/openfpga/src/base/openfpga_setup_command.cpp index ca5864b2e..eb0e0430d 100644 --- a/openfpga/src/base/openfpga_setup_command.cpp +++ b/openfpga/src/base/openfpga_setup_command.cpp @@ -267,6 +267,9 @@ ShellCommandId add_openfpga_build_fabric_command(openfpga::Shell Date: Thu, 2 Jul 2020 16:31:22 -0600 Subject: [PATCH 08/25] add bitstream generation only test case to CI --- .travis/openfpga_vpr8_reg_test.sh | 3 ++ ...generate_bitstream_example_script.openfpga | 47 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga diff --git a/.travis/openfpga_vpr8_reg_test.sh b/.travis/openfpga_vpr8_reg_test.sh index 8c07480cd..c48959e58 100755 --- a/.travis/openfpga_vpr8_reg_test.sh +++ b/.travis/openfpga_vpr8_reg_test.sh @@ -99,6 +99,9 @@ python3 openfpga_flow/scripts/run_fpga_task.py openfpga_shell/generate_fabric -- echo -e "Testing Verilog testbench generation only"; python3 openfpga_flow/scripts/run_fpga_task.py openfpga_shell/generate_testbench --debug --show_thread_logs +echo -e "Testing bitstream generation only"; +python3 openfpga_flow/scripts/run_fpga_task.py openfpga_shell/generate_bitstream --debug --show_thread_logs + echo -e "Testing SDC generation with time units"; python3 openfpga_flow/scripts/run_fpga_task.py openfpga_shell/sdc_time_unit --debug --show_thread_logs diff --git a/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga b/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga new file mode 100644 index 000000000..e7c934513 --- /dev/null +++ b/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga @@ -0,0 +1,47 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enabled frame view creation to save runtime and memory +# Note that this is turned on when bitstream generation +# is the ONLY purpose of the flow!!! +build_fabric --compress_routing --frame_view #--verbose + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_indepenent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory From 81c9fcb7c0cbb78357ab0e0dc2a034d9bdba1d01 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 16:41:32 -0600 Subject: [PATCH 09/25] bug fix when optimizing the fabric bitstream data structure --- openfpga/src/fpga_bitstream/fabric_bitstream.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 962fe02f6..552e30c79 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -104,6 +104,7 @@ void FabricBitstream::set_bit_din(const FabricBitId& bit_id, } void FabricBitstream::reverse() { + std::reverse(config_bit_ids_.begin(), config_bit_ids_.end()); std::reverse(bit_addresses_.begin(), bit_addresses_.end()); std::reverse(bit_dins_.begin(), bit_dins_.end()); } From 1c634e460091e393ce5244a23cba1e850102397e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 17:24:51 -0600 Subject: [PATCH 10/25] add missing task file for generate bitstream test case --- .../generate_bitstream/config/task.conf | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 openfpga_flow/tasks/openfpga_shell/generate_bitstream/config/task.conf diff --git a/openfpga_flow/tasks/openfpga_shell/generate_bitstream/config/task.conf b/openfpga_flow/tasks/openfpga_shell/generate_bitstream/config/task.conf new file mode 100644 index 000000000..4c12ab08b --- /dev/null +++ b/openfpga_flow/tasks/openfpga_shell/generate_bitstream/config/task.conf @@ -0,0 +1,33 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/generate_bitstream_example_script.openfpga +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +external_fabric_key_file= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/vpr_only_templates/k6_frac_N10_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] From f97e3bfba62583a2c177fec882b30a2b879d7519 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 18:02:33 -0600 Subject: [PATCH 11/25] add timer to openfpga shell --- libopenfpga/libopenfpgashell/src/shell.h | 4 ++++ libopenfpga/libopenfpgashell/src/shell.tpp | 9 +++++++++ openfpga/src/main.cpp | 3 +-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libopenfpga/libopenfpgashell/src/shell.h b/libopenfpga/libopenfpgashell/src/shell.h index 1a49b313c..67dd4356d 100644 --- a/libopenfpga/libopenfpgashell/src/shell.h +++ b/libopenfpga/libopenfpgashell/src/shell.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "vtr_vector.h" #include "vtr_range.h" @@ -211,6 +212,9 @@ class Shell { std::map command_name2ids_; std::map command_class2ids_; vtr::vector> commands_by_classes_; + + /* Timer */ + std::clock_t time_start_; }; } /* End namespace openfpga */ diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp index 219287ee1..7c0ff7ce6 100644 --- a/libopenfpga/libopenfpgashell/src/shell.tpp +++ b/libopenfpga/libopenfpgashell/src/shell.tpp @@ -28,6 +28,7 @@ namespace openfpga { template Shell::Shell(const char* name) { name_ = std::string(name); + time_start_ = 0; } /************************************************************************ @@ -241,6 +242,9 @@ ShellCommandClassId Shell::add_command_class(const char* name) { template void Shell::run_interactive_mode(T& context, const bool& quiet_mode) { if (false == quiet_mode) { + /* Reset timer since it does not come from another mode */ + time_start_ = std::clock(); + VTR_LOG("Start interactive mode of %s...\n", name().c_str()); @@ -270,6 +274,8 @@ void Shell::run_interactive_mode(T& context, const bool& quiet_mode) { template void Shell::run_script_mode(const char* script_file_name, T& context) { + time_start_ = std::clock(); + VTR_LOG("Reading script file %s...\n", script_file_name); /* Print the title of the shell */ @@ -419,6 +425,9 @@ void Shell::exit() const { VTR_LOG("\nFinish execution with %d errors\n", num_err); + VTR_LOG("\nThe entire OpenFPGA flow took %g seconds\n", + (double)(std::clock() - time_start_) / (double)CLOCKS_PER_SEC); + VTR_LOG("\nThank you for using %s!\n", name().c_str()); diff --git a/openfpga/src/main.cpp b/openfpga/src/main.cpp index e1f813e9b..9f332263c 100644 --- a/openfpga/src/main.cpp +++ b/openfpga/src/main.cpp @@ -25,6 +25,7 @@ * Main function to start OpenFPGA shell interface *******************************************************************/ int main(int argc, char** argv) { + /* Create the command to launch shell in different modes */ openfpga::Command start_cmd("OpenFPGA"); /* Add two options: @@ -89,13 +90,11 @@ int main(int argc, char** argv) { /* Parse succeed. Start a shell */ if (true == start_cmd_context.option_enable(start_cmd, opt_interactive)) { - vtr::ScopedStartFinishTimer timer("OpenFPGA operating"); shell.run_interactive_mode(openfpga_context); return 0; } if (true == start_cmd_context.option_enable(start_cmd, opt_script_mode)) { - vtr::ScopedStartFinishTimer timer("OpenFPGA operating"); shell.run_script_mode(start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(), openfpga_context); return 0; From dee4be96af0875896ad135fb8c57ac1c96ac80f3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 19:17:34 -0600 Subject: [PATCH 12/25] reserve all the input/output net storage in bitstream manager --- .../src/bitstream_manager.cpp | 28 +++++++++++++++++-- .../libfpgabitstream/src/bitstream_manager.h | 14 +++++++--- .../fpga_bitstream/build_grid_bitstream.cpp | 2 ++ .../build_routing_bitstream.cpp | 4 +++ .../src/fpga_bitstream/fabric_bitstream.cpp | 1 + 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index bc185a1e0..8ee40287a 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -15,6 +15,8 @@ namespace openfpga { BitstreamManager::BitstreamManager() { num_blocks_ = 0; num_bits_ = 0; + invalid_block_ids_.clear(); + invalid_bit_ids_.clear(); } /************************************************** @@ -39,7 +41,7 @@ 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]; + return '1' == bit_values_[bit_id]; } std::string BitstreamManager::block_name(const ConfigBlockId& block_id) const { @@ -146,7 +148,11 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { ConfigBitId bit = ConfigBitId(num_bits_); /* Add a new bit, and allocate associated data structures */ num_bits_++; - bit_values_.push_back(bit_value); + if (true == bit_value) { + bit_values_.push_back('1'); + } else { + bit_values_.push_back('0'); + } shared_config_bit_values_.emplace_back(); bit_parent_block_ids_.push_back(ConfigBlockId::INVALID()); @@ -238,6 +244,14 @@ void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const in block_path_ids_[block] = path_id; } +void BitstreamManager::reserve_block_input_net_ids(const ConfigBlockId& block, + const size_t& num_input_net_ids) { + /* Ensure the input ids are valid */ + VTR_ASSERT(true == valid_block_id(block)); + + block_input_net_ids_[block].reserve(num_input_net_ids); +} + void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block, const std::string& input_net_id) { /* Ensure the input ids are valid */ @@ -247,6 +261,14 @@ void BitstreamManager::add_input_net_id_to_block(const ConfigBlockId& block, block_input_net_ids_[block].push_back(input_net_id); } +void BitstreamManager::reserve_block_output_net_ids(const ConfigBlockId& block, + const size_t& num_output_net_ids) { + /* Ensure the input ids are valid */ + VTR_ASSERT(true == valid_block_id(block)); + + block_output_net_ids_[block].reserve(num_output_net_ids); +} + void BitstreamManager::add_output_net_id_to_block(const ConfigBlockId& block, const std::string& output_net_id) { /* Ensure the input ids are valid */ @@ -256,7 +278,7 @@ void BitstreamManager::add_output_net_id_to_block(const ConfigBlockId& block, block_output_net_ids_[block].push_back(output_net_id); } -void BitstreamManager::add_shared_config_bit_values(const ConfigBitId& bit, const std::vector& shared_config_bits) { +void BitstreamManager::add_shared_config_bit_values(const ConfigBitId& bit, const std::vector& shared_config_bits) { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_bit_id(bit)); diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index ce741df92..9a7575383 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -175,15 +175,21 @@ class BitstreamManager { /* Add a path id to a block */ void add_path_id_to_block(const ConfigBlockId& block, const int& path_id); + + /* Reserve input net ids for a block */ + void reserve_block_input_net_ids(const ConfigBlockId& block, const size_t& num_input_net_ids); /* Add an input net id to a block */ void add_input_net_id_to_block(const ConfigBlockId& block, const std::string& input_net_id); + /* Reserve output net ids for a block */ + void reserve_block_output_net_ids(const ConfigBlockId& block, const size_t& num_output_net_ids); + /* Add an output net id to a block */ void add_output_net_id_to_block(const ConfigBlockId& block, const std::string& output_net_id); /* Add share configuration bits to a configuration bit */ - void add_shared_config_bit_values(const ConfigBitId& bit, const std::vector& shared_config_bits); + void add_shared_config_bit_values(const ConfigBitId& bit, const std::vector& shared_config_bits); public: /* Public Validators */ bool valid_bit_id(const ConfigBitId& bit_id) const; @@ -220,7 +226,7 @@ class BitstreamManager { * -Bitstream manager will NOT check if the id is good for bitstream builders * It just store the results */ - vtr::vector block_path_ids_; + vtr::vector block_path_ids_; /* Net ids that are mapped to inputs and outputs of this block * @@ -236,9 +242,9 @@ class BitstreamManager { std::unordered_set invalid_bit_ids_; vtr::vector bit_parent_block_ids_; /* value of a bit in the Bitstream */ - vtr::vector bit_values_; + vtr::vector bit_values_; /* value of a shared configuration bits in the Bitstream */ - vtr::vector> shared_config_bit_values_; + vtr::vector> shared_config_bit_values_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index c3de6cbfe..33ae3fa4b 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -221,6 +221,7 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag } /* Record path ids, input and output nets */ bitstream_manager.add_path_id_to_block(mux_mem_block, mux_input_pin_id); + bitstream_manager.reserve_block_input_net_ids(mux_mem_block, input_nets.size()); for (const AtomNetId& input_net : input_nets) { if (true == atom_ctx.nlist.valid_net_id(input_net)) { bitstream_manager.add_input_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(input_net)); @@ -229,6 +230,7 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag } } if (true == atom_ctx.nlist.valid_net_id(output_net)) { + bitstream_manager.reserve_block_output_net_ids(mux_mem_block, 1); bitstream_manager.add_output_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(output_net)); } else { bitstream_manager.add_output_net_id_to_block(mux_mem_block, std::string("unmapped")); diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp index 457b1d004..a1df3eeb9 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -105,6 +105,7 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, } /* Record path ids, input and output nets */ bitstream_manager.add_path_id_to_block(mux_mem_block, path_id); + bitstream_manager.reserve_block_input_net_ids(mux_mem_block, input_nets.size()); for (const ClusterNetId& input_net : input_nets) { AtomNetId input_atom_net = atom_ctx.lookup.atom_net(input_net); if (true == atom_ctx.nlist.valid_net_id(input_atom_net)) { @@ -114,6 +115,7 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, } } AtomNetId output_atom_net = atom_ctx.lookup.atom_net(output_net); + bitstream_manager.reserve_block_output_net_ids(mux_mem_block, 1); if (true == atom_ctx.nlist.valid_net_id(output_atom_net)) { bitstream_manager.add_output_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(output_atom_net)); } else { @@ -296,6 +298,7 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, } /* Record path ids, input and output nets */ bitstream_manager.add_path_id_to_block(mux_mem_block, path_id); + bitstream_manager.reserve_block_input_net_ids(mux_mem_block, input_nets.size()); for (const ClusterNetId& input_net : input_nets) { AtomNetId input_atom_net = atom_ctx.lookup.atom_net(input_net); if (true == atom_ctx.nlist.valid_net_id(input_atom_net)) { @@ -305,6 +308,7 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, } } AtomNetId output_atom_net = atom_ctx.lookup.atom_net(output_net); + bitstream_manager.reserve_block_output_net_ids(mux_mem_block, 1); if (true == atom_ctx.nlist.valid_net_id(output_atom_net)) { bitstream_manager.add_output_net_id_to_block(mux_mem_block, atom_ctx.nlist.net_name(output_atom_net)); } else { diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 552e30c79..8108da263 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -14,6 +14,7 @@ namespace openfpga { *************************************************/ FabricBitstream::FabricBitstream() { num_bits_ = 0; + invalid_bit_ids_.clear(); } /************************************************** From 9799fea48f19b6472009c349c2ec10dea36b1bc9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 19:33:53 -0600 Subject: [PATCH 13/25] optimizing bitstream storage --- libopenfpga/libfpgabitstream/src/bitstream_manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index 9a7575383..13e3f47a6 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -226,7 +226,7 @@ class BitstreamManager { * -Bitstream manager will NOT check if the id is good for bitstream builders * It just store the results */ - vtr::vector block_path_ids_; + vtr::vector block_path_ids_; /* Net ids that are mapped to inputs and outputs of this block * From 043fb54206b516a082fa218e5dbc99b16888246b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 20:53:18 -0600 Subject: [PATCH 14/25] remove unused data in bitstream database --- libopenfpga/libfpgabitstream/src/bitstream_manager.cpp | 9 --------- libopenfpga/libfpgabitstream/src/bitstream_manager.h | 5 ----- 2 files changed, 14 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index 8ee40287a..07c4c6057 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -153,7 +153,6 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { } else { bit_values_.push_back('0'); } - shared_config_bit_values_.emplace_back(); bit_parent_block_ids_.push_back(ConfigBlockId::INVALID()); return bit; @@ -171,7 +170,6 @@ void BitstreamManager::reserve_blocks(const size_t& num_blocks) { void BitstreamManager::reserve_bits(const size_t& num_bits) { bit_values_.reserve(num_bits); - shared_config_bit_values_.reserve(num_bits); bit_parent_block_ids_.reserve(num_bits); } @@ -278,13 +276,6 @@ void BitstreamManager::add_output_net_id_to_block(const ConfigBlockId& block, block_output_net_ids_[block].push_back(output_net_id); } -void BitstreamManager::add_shared_config_bit_values(const ConfigBitId& bit, const std::vector& 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 ******************************************************************************/ diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index 13e3f47a6..f94fef472 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -188,9 +188,6 @@ class BitstreamManager { /* Add an output net id to a block */ void add_output_net_id_to_block(const ConfigBlockId& block, const std::string& output_net_id); - /* Add share configuration bits to a configuration bit */ - void add_shared_config_bit_values(const ConfigBitId& bit, const std::vector& shared_config_bits); - public: /* Public Validators */ bool valid_bit_id(const ConfigBitId& bit_id) const; @@ -243,8 +240,6 @@ class BitstreamManager { vtr::vector bit_parent_block_ids_; /* value of a bit in the Bitstream */ vtr::vector bit_values_; - /* value of a shared configuration bits in the Bitstream */ - vtr::vector> shared_config_bit_values_; }; } /* end namespace openfpga */ From 246b4d5ac6f69ce342f3c878db5804d5296905d5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 21:52:32 -0600 Subject: [PATCH 15/25] reserve block bits to save memory --- libopenfpga/libfpgabitstream/src/bitstream_manager.cpp | 8 ++++++++ libopenfpga/libfpgabitstream/src/bitstream_manager.h | 4 ++++ openfpga/src/fpga_bitstream/build_grid_bitstream.cpp | 3 +++ openfpga/src/fpga_bitstream/build_routing_bitstream.cpp | 2 ++ 4 files changed, 17 insertions(+) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index 07c4c6057..557bca551 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -220,6 +220,14 @@ void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const parent_block_ids_[child_block] = parent_block; } +void BitstreamManager::reserve_block_bits(const ConfigBlockId& block, + const size_t& num_bits) { + /* Ensure the input ids are valid */ + VTR_ASSERT(true == valid_block_id(block)); + + block_bit_ids_[block].reserve(num_bits); +} + 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)); diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index f94fef472..151f0817a 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -170,6 +170,10 @@ class BitstreamManager { /* Set a block as a child block of another */ void add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block); + /* Reserve a number of configuration bits for a block */ + void reserve_block_bits(const ConfigBlockId& block, + const size_t& num_bits); + /* Add a configuration bit to a block */ void add_bit_to_block(const ConfigBlockId& block, const ConfigBitId& bit); diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index 33ae3fa4b..577402706 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -106,6 +106,7 @@ void build_primitive_bitstream(BitstreamManager& bitstream_manager, bitstream_manager.add_child_block(parent_configurable_block, mem_block); /* Add the bitstream to the bitstream manager */ + bitstream_manager.reserve_block_bits(mem_block, mode_select_bitstream.size()); for (const bool& bit : mode_select_bitstream) { ConfigBitId config_bit = bitstream_manager.add_bit(bit); /* Link the memory bits to the mux mem block */ @@ -214,6 +215,7 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); /* Add the bistream to the bitstream manager */ + bitstream_manager.reserve_block_bits(mux_mem_block, mux_bitstream.size()); for (const bool& bit : mux_bitstream) { ConfigBitId config_bit = bitstream_manager.add_bit(bit); /* Link the memory bits to the mux mem block */ @@ -467,6 +469,7 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager, bitstream_manager.add_child_block(parent_configurable_block, mem_block); /* Add the bitstream to the bitstream manager */ + bitstream_manager.reserve_block_bits(mem_block, lut_bitstream.size()); for (const bool& bit : lut_bitstream) { ConfigBitId config_bit = bitstream_manager.add_bit(bit); /* Link the memory bits to the mux mem block */ diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp index a1df3eeb9..c4dec00db 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -98,6 +98,7 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); /* Add the bistream to the bitstream manager */ + bitstream_manager.reserve_block_bits(mux_mem_block, mux_bitstream.size()); for (const bool& bit : mux_bitstream) { ConfigBitId config_bit = bitstream_manager.add_bit(bit); /* Link the memory bits to the mux mem block */ @@ -291,6 +292,7 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); /* Add the bistream to the bitstream manager */ + bitstream_manager.reserve_block_bits(mux_mem_block, mux_bitstream.size()); for (const bool& bit : mux_bitstream) { ConfigBitId config_bit = bitstream_manager.add_bit(bit); /* Link the memory bits to the mux mem block */ From 8a45e48a1ca420989c29cb7bfca9f1a0d2ef5e4c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Jul 2020 22:27:48 -0600 Subject: [PATCH 16/25] minor fix --- openfpga/src/fpga_bitstream/fabric_bitstream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 8108da263..6b51adfd2 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -76,7 +76,7 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) { num_bits_++; config_bit_ids_.push_back(config_bit_id); bit_addresses_.emplace_back(); - bit_dins_.push_back(false); + bit_dins_.push_back('0'); return bit; } From 7ca1a5bdc17bd6844a90184de6078f7105f7c8a8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 10:17:03 -0600 Subject: [PATCH 17/25] Fabric bitstream now allocates vectors in conditions for memory efficiency --- .../fpga_bitstream/build_fabric_bitstream.cpp | 18 +++++- .../src/fpga_bitstream/fabric_bitstream.cpp | 64 +++++++++++++++---- .../src/fpga_bitstream/fabric_bitstream.h | 27 +++++++- 3 files changed, 93 insertions(+), 16 deletions(-) diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 1c78f8fc5..3e80ebfb9 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -379,12 +379,18 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: { + /* Reserve bits before build-up */ + fabric_bitstream.reserve_bits(bitstream_manager.bits().size()); + rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, top_block, module_manager, top_module, fabric_bitstream); break; } case CONFIG_MEM_SCAN_CHAIN: { + /* Reserve bits before build-up */ + fabric_bitstream.reserve_bits(bitstream_manager.bits().size()); + rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, top_block, module_manager, top_module, fabric_bitstream); @@ -392,6 +398,11 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc break; } case CONFIG_MEM_MEMORY_BANK: { + /* Reserve bits before build-up */ + fabric_bitstream.set_use_address(true); + fabric_bitstream.set_use_wl_address(true); + fabric_bitstream.reserve_bits(bitstream_manager.bits().size()); + size_t cur_mem_index = 0; /* Find BL address port size */ ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); @@ -425,6 +436,10 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc break; } case CONFIG_MEM_FRAME_BASED: { + /* Reserve bits before build-up */ + fabric_bitstream.set_use_address(true); + fabric_bitstream.reserve_bits(bitstream_manager.bits().size()); + rec_build_module_fabric_dependent_frame_bitstream(bitstream_manager, std::vector(1, top_block), module_manager, @@ -495,9 +510,6 @@ FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstre VTR_ASSERT(1 == top_block.size()); VTR_ASSERT(0 == top_module_name.compare(bitstream_manager.block_name(top_block[0]))); - /* Reserve bits before build-up */ - fabric_bitstream.reserve(bitstream_manager.bits().size()); - /* Start build-up formally */ build_module_fabric_dependent_bitstream(config_protocol, bitstream_manager, top_block[0], diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 6b51adfd2..34d37471c 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -39,8 +39,9 @@ ConfigBitId FabricBitstream::config_bit(const FabricBitId& bit_id) const { std::vector FabricBitstream::bit_address(const FabricBitId& bit_id) const { /* Ensure a valid id */ VTR_ASSERT(true == valid_bit_id(bit_id)); + VTR_ASSERT(true == use_address_); - return bit_addresses_[bit_id][0]; + return bit_addresses_[bit_id]; } std::vector FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const { @@ -50,24 +51,42 @@ std::vector FabricBitstream::bit_bl_address(const FabricBitId& bit_id) con std::vector FabricBitstream::bit_wl_address(const FabricBitId& bit_id) const { /* Ensure a valid id */ VTR_ASSERT(true == valid_bit_id(bit_id)); + VTR_ASSERT(true == use_address_); + VTR_ASSERT(true == use_wl_address_); - return bit_addresses_[bit_id][1]; + return bit_wl_addresses_[bit_id]; } char FabricBitstream::bit_din(const FabricBitId& bit_id) const { /* Ensure a valid id */ VTR_ASSERT(true == valid_bit_id(bit_id)); + VTR_ASSERT(true == use_address_); return bit_dins_[bit_id]; } +bool FabricBitstream::use_address() const { + return use_address_; +} + +bool FabricBitstream::use_wl_address() const { + return use_wl_address_; +} + /****************************************************************************** * Public Mutators ******************************************************************************/ -void FabricBitstream::reserve(const size_t& num_bits) { +void FabricBitstream::reserve_bits(const size_t& num_bits) { config_bit_ids_.reserve(num_bits); - bit_addresses_.reserve(num_bits); - bit_dins_.reserve(num_bits); + + if (true == use_address_) { + bit_addresses_.reserve(num_bits); + bit_dins_.reserve(num_bits); + + if (true == use_wl_address_) { + bit_wl_addresses_.reserve(num_bits); + } + } } FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) { @@ -75,8 +94,6 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) { /* Add a new bit, and allocate associated data structures */ num_bits_++; config_bit_ids_.push_back(config_bit_id); - bit_addresses_.emplace_back(); - bit_dins_.push_back('0'); return bit; } @@ -84,7 +101,8 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) { void FabricBitstream::set_bit_address(const FabricBitId& bit_id, const std::vector& address) { VTR_ASSERT(true == valid_bit_id(bit_id)); - bit_addresses_[bit_id][0] = address; + VTR_ASSERT(true == use_address_); + bit_addresses_[bit_id] = address; } void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id, @@ -95,19 +113,43 @@ void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id, void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id, const std::vector& address) { VTR_ASSERT(true == valid_bit_id(bit_id)); - bit_addresses_[bit_id][1] = address; + VTR_ASSERT(true == use_address_); + VTR_ASSERT(true == use_wl_address_); + bit_wl_addresses_[bit_id] = address; } void FabricBitstream::set_bit_din(const FabricBitId& bit_id, const char& din) { VTR_ASSERT(true == valid_bit_id(bit_id)); + VTR_ASSERT(true == use_address_); bit_dins_[bit_id] = din; } void FabricBitstream::reverse() { std::reverse(config_bit_ids_.begin(), config_bit_ids_.end()); - std::reverse(bit_addresses_.begin(), bit_addresses_.end()); - std::reverse(bit_dins_.begin(), bit_dins_.end()); + + if (true == use_address_) { + std::reverse(bit_addresses_.begin(), bit_addresses_.end()); + std::reverse(bit_dins_.begin(), bit_dins_.end()); + + if (true == use_wl_address_) { + std::reverse(bit_wl_addresses_.begin(), bit_wl_addresses_.end()); + } + } +} + +void FabricBitstream::set_use_address(const bool& enable) { + /* Add a lock, only can be modified when num bits are zero*/ + if (0 == num_bits_) { + use_address_ = enable; + } +} + +void FabricBitstream::set_use_wl_address(const bool& enable) { + /* Add a lock, only can be modified when num bits are zero*/ + if (0 == num_bits_) { + use_wl_address_ = enable; + } } /****************************************************************************** diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index ee0699b2d..79b4a91cc 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -115,9 +115,13 @@ class FabricBitstream { /* Find the data-in of bitstream */ char bit_din(const FabricBitId& bit_id) const; + /* Check if address data is accessible or not*/ + bool use_address() const; + bool use_wl_address() const; + public: /* Public Mutators */ /* Reserve config bits */ - void reserve(const size_t& num_bits); + void reserve_bits(const size_t& num_bits); /* Add a new configuration bit to the bitstream manager */ FabricBitId add_bit(const ConfigBitId& config_bit_id); @@ -139,6 +143,20 @@ class FabricBitstream { */ void reverse(); + /* Enable the use of address-related data + * When this is enabled, data allocation will be applied to these data + * and users can access/modify the data + * Otherwise, it will NOT be allocated and accessible. + * + * This function is only applicable before any bits are added + */ + void set_use_address(const bool& enable); + + /* Enable the use of WL-address related data + * Same priniciple as the set_use_address() + */ + void set_use_wl_address(const bool& enable); + public: /* Public Validators */ char valid_bit_id(const FabricBitId& bit_id) const; @@ -148,13 +166,18 @@ class FabricBitstream { std::unordered_set invalid_bit_ids_; vtr::vector config_bit_ids_; + /* Flags to indicate if the addresses and din should be enabled */ + bool use_address_; + bool use_wl_address_; + /* Address bits: this is designed for memory decoders * Here we store the binary format of the address, which can be loaded * to the configuration protocol directly * * We use a 2-element array, as we may have a BL address and a WL address */ - vtr::vector, 2>> bit_addresses_; + vtr::vector> bit_addresses_; + vtr::vector> bit_wl_addresses_; /* Data input (Din) bits: this is designed for memory decoders */ vtr::vector bit_dins_; From 6397cbe9d21fb3dcd928dd9c6bb7b30fc6036acb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 10:35:35 -0600 Subject: [PATCH 18/25] remove unused data in bitstream manager to compact memory usage --- .../src/bitstream_manager.cpp | 32 ------------------- .../libfpgabitstream/src/bitstream_manager.h | 7 ---- 2 files changed, 39 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index 557bca551..2e9c833a4 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -72,31 +72,6 @@ std::vector BitstreamManager::block_bits(const ConfigBlockId& block 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 { @@ -153,7 +128,6 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { } else { bit_values_.push_back('0'); } - bit_parent_block_ids_.push_back(ConfigBlockId::INVALID()); return bit; } @@ -170,7 +144,6 @@ void BitstreamManager::reserve_blocks(const size_t& num_blocks) { void BitstreamManager::reserve_bits(const size_t& num_bits) { bit_values_.reserve(num_bits); - bit_parent_block_ids_.reserve(num_bits); } ConfigBlockId BitstreamManager::create_block() { @@ -233,13 +206,8 @@ void BitstreamManager::add_bit_to_block(const ConfigBlockId& block, const Config 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_path_id_to_block(const ConfigBlockId& block, const int& path_id) { diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index 151f0817a..b3553cb15 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -129,12 +129,6 @@ class BitstreamManager { /* Find all the bits that belong to a block */ std::vector 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; @@ -241,7 +235,6 @@ class BitstreamManager { /* Unique id of a bit in the Bitstream */ size_t num_bits_; std::unordered_set invalid_bit_ids_; - vtr::vector bit_parent_block_ids_; /* value of a bit in the Bitstream */ vtr::vector bit_values_; }; From 6ea857ae6cee11dbe1eb1f165d05e1b8aa8e3bb6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 10:55:25 -0600 Subject: [PATCH 19/25] use fast method to inquire number of bits and blocks in bitstream databases --- .../libfpgabitstream/src/bitstream_manager.cpp | 8 ++++++++ libopenfpga/libfpgabitstream/src/bitstream_manager.h | 2 ++ .../src/fpga_bitstream/build_device_bitstream.cpp | 8 ++++---- .../src/fpga_bitstream/build_fabric_bitstream.cpp | 12 ++++++------ openfpga/src/fpga_bitstream/fabric_bitstream.cpp | 4 ++++ openfpga/src/fpga_bitstream/fabric_bitstream.h | 1 + .../src/fpga_bitstream/fabric_bitstream_writer.cpp | 2 +- openfpga/src/fpga_verilog/verilog_api.cpp | 2 +- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 2 +- 9 files changed, 28 insertions(+), 13 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index 2e9c833a4..345426b24 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -23,11 +23,19 @@ BitstreamManager::BitstreamManager() { * Public Accessors : Aggregates *************************************************/ /* Find all the configuration bits */ +size_t BitstreamManager::num_bits() const { + return num_bits_; +} + BitstreamManager::config_bit_range BitstreamManager::bits() const { return vtr::make_range(config_bit_iterator(ConfigBitId(0), invalid_bit_ids_), config_bit_iterator(ConfigBitId(num_bits_), invalid_bit_ids_)); } +size_t BitstreamManager::num_blocks() const { + return num_blocks_; +} + /* Find all the configuration blocks */ BitstreamManager::config_block_range BitstreamManager::blocks() const { return vtr::make_range(config_block_iterator(ConfigBlockId(0), invalid_block_ids_), diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index b3553cb15..af69fd499 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -109,8 +109,10 @@ class BitstreamManager { public: /* Public aggregators */ /* Find all the configuration bits */ + size_t num_bits() const; config_bit_range bits() const; + size_t num_blocks() const; config_block_range blocks() const; public: /* Public Accessors */ diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 59dd9c788..7e37b5943 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -173,11 +173,11 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, VTR_LOGV(verbose, "Decoded %lu configuration bits into %lu blocks\n", - bitstream_manager.bits().size(), - bitstream_manager.blocks().size()); + bitstream_manager.num_bits(), + bitstream_manager.num_blocks()); - //VTR_ASSERT(num_blocks_to_reserve == bitstream_manager.blocks().size()); - //VTR_ASSERT(num_bits_to_reserve == bitstream_manager.bits().size()); + //VTR_ASSERT(num_blocks_to_reserve == bitstream_manager.num_blocks()); + //VTR_ASSERT(num_bits_to_reserve == bitstream_manager.num_bits()); return bitstream_manager; } diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 3e80ebfb9..38724aad8 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -380,7 +380,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: { /* Reserve bits before build-up */ - fabric_bitstream.reserve_bits(bitstream_manager.bits().size()); + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, top_block, module_manager, top_module, @@ -389,7 +389,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc } case CONFIG_MEM_SCAN_CHAIN: { /* Reserve bits before build-up */ - fabric_bitstream.reserve_bits(bitstream_manager.bits().size()); + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); rec_build_module_fabric_dependent_chain_bitstream(bitstream_manager, top_block, module_manager, top_module, @@ -401,7 +401,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc /* Reserve bits before build-up */ fabric_bitstream.set_use_address(true); fabric_bitstream.set_use_wl_address(true); - fabric_bitstream.reserve_bits(bitstream_manager.bits().size()); + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); size_t cur_mem_index = 0; /* Find BL address port size */ @@ -438,7 +438,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc case CONFIG_MEM_FRAME_BASED: { /* Reserve bits before build-up */ fabric_bitstream.set_use_address(true); - fabric_bitstream.reserve_bits(bitstream_manager.bits().size()); + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); rec_build_module_fabric_dependent_frame_bitstream(bitstream_manager, std::vector(1, top_block), @@ -474,7 +474,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc */ /* Ensure our fabric bitstream is in the same size as device bistream */ - VTR_ASSERT(bitstream_manager.bits().size() == fabric_bitstream.bits().size()); + VTR_ASSERT(bitstream_manager.num_bits() == fabric_bitstream.num_bits()); } /******************************************************************** @@ -518,7 +518,7 @@ FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstre VTR_LOGV(verbose, "Built %lu configuration bits for fabric\n", - fabric_bitstream.bits().size()); + fabric_bitstream.num_bits()); return fabric_bitstream; } diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 34d37471c..f8f3a956f 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -20,6 +20,10 @@ FabricBitstream::FabricBitstream() { /************************************************** * Public Accessors : Aggregates *************************************************/ +size_t FabricBitstream::num_bits() const { + return num_bits_; +} + /* Find all the configuration bits */ FabricBitstream::fabric_bit_range FabricBitstream::bits() const { return vtr::make_range(fabric_bit_iterator(FabricBitId(0), invalid_bit_ids_), diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index 79b4a91cc..ea64b4590 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -101,6 +101,7 @@ class FabricBitstream { public: /* Public aggregators */ /* Find all the configuration bits */ + size_t num_bits() const; fabric_bit_range bits() const; public: /* Public Accessors */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp index 60e626692..2991dd6a0 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream_writer.cpp @@ -101,7 +101,7 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage VTR_LOG_ERROR("Received empty file name to output bitstream!\n\tPlease specify a valid file name.\n"); } - std::string timer_message = std::string("Write ") + std::to_string(fabric_bitstream.bits().size()) + std::string(" fabric bitstream into plain text file '") + fname + std::string("'"); + std::string timer_message = std::string("Write ") + std::to_string(fabric_bitstream.num_bits()) + std::string(" fabric bitstream into plain text file '") + fname + std::string("'"); vtr::ScopedStartFinishTimer timer(timer_message); /* Create the file stream */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index ff7872999..0e2f84124 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -234,7 +234,7 @@ namespace openfpga atom_ctx, place_ctx, io_location_map, module_manager, config_protocol_type, - bitstream_manager.bits().size(), + bitstream_manager.num_bits(), simulation_setting.num_clock_cycles(), simulation_setting.programming_clock_frequency(), simulation_setting.operating_clock_frequency()); diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 9bf51d6a4..9e7bde572 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -562,7 +562,7 @@ static size_t calculate_num_config_clock_cycles(const e_config_protocol_type& sram_orgz_type, const bool& fast_configuration, const FabricBitstream& fabric_bitstream) { - size_t num_config_clock_cycles = 1 + fabric_bitstream.bits().size(); + size_t num_config_clock_cycles = 1 + fabric_bitstream.num_bits(); /* Branch on the type of configuration protocol */ switch (sram_orgz_type) { From 2783fda344458429bf0095548eb25b217210b7d0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 11:42:38 -0600 Subject: [PATCH 20/25] use index range instead of vector for block bitstream --- .../src/bitstream_manager.cpp | 39 ++++++++++++------- .../libfpgabitstream/src/bitstream_manager.h | 12 +++--- .../src/read_xml_arch_bitstream.cpp | 9 +++-- .../fpga_bitstream/build_grid_bitstream.cpp | 21 ++-------- .../build_routing_bitstream.cpp | 14 +------ 5 files changed, 39 insertions(+), 56 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index 345426b24..b2d894427 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -77,7 +77,16 @@ std::vector BitstreamManager::block_bits(const ConfigBlockId& block /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block_id)); - return block_bit_ids_[block_id]; + size_t lsb = block_bit_id_lsbs_[block_id]; + size_t msb = block_bit_id_msbs_[block_id]; + + std::vector bits(msb - lsb + 1, ConfigBitId::INVALID()); + + for (size_t i = lsb; i < msb + 1; ++i) { + bits[i - lsb] = ConfigBitId(i); + } + + return bits; } /* Find the child block in a bitstream manager with a given name */ @@ -142,7 +151,8 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { void BitstreamManager::reserve_blocks(const size_t& num_blocks) { block_names_.reserve(num_blocks); - block_bit_ids_.reserve(num_blocks); + block_bit_id_lsbs_.reserve(num_blocks); + block_bit_id_msbs_.reserve(num_blocks); block_path_ids_.reserve(num_blocks); block_input_net_ids_.reserve(num_blocks); block_output_net_ids_.reserve(num_blocks); @@ -159,7 +169,8 @@ ConfigBlockId BitstreamManager::create_block() { /* Add a new bit, and allocate associated data structures */ num_blocks_++; block_names_.emplace_back(); - block_bit_ids_.emplace_back(); + block_bit_id_lsbs_.emplace_back(0); + block_bit_id_msbs_.emplace_back(-1); block_path_ids_.push_back(-2); block_input_net_ids_.emplace_back(); block_output_net_ids_.emplace_back(); @@ -201,21 +212,19 @@ void BitstreamManager::add_child_block(const ConfigBlockId& parent_block, const parent_block_ids_[child_block] = parent_block; } -void BitstreamManager::reserve_block_bits(const ConfigBlockId& block, - const size_t& num_bits) { +void BitstreamManager::add_block_bits(const ConfigBlockId& block, + const std::vector& block_bitstream) { /* Ensure the input ids are valid */ VTR_ASSERT(true == valid_block_id(block)); - block_bit_ids_[block].reserve(num_bits); -} - -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)); - - /* Add the bit to the block */ - block_bit_ids_[block].push_back(bit); + /* Add the bit to the block, record anchors in bit indexing for block-level searching */ + size_t lsb = num_bits_; + size_t msb = num_bits_ + block_bitstream.size() - 1; + for (const bool& bit : block_bitstream) { + add_bit(bit); + } + block_bit_id_lsbs_[block] = lsb; + block_bit_id_msbs_[block] = msb; } void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const int& path_id) { diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index af69fd499..dd724fac9 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -166,12 +166,9 @@ class BitstreamManager { /* Set a block as a child block of another */ void add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block); - /* Reserve a number of configuration bits for a block */ - void reserve_block_bits(const ConfigBlockId& block, - const size_t& num_bits); - - /* Add a configuration bit to a block */ - void add_bit_to_block(const ConfigBlockId& block, const ConfigBitId& bit); + /* Add a bitstream to a block */ + void add_block_bits(const ConfigBlockId& block, + const std::vector& block_bitstream); /* Add a path id to a block */ void add_path_id_to_block(const ConfigBlockId& block, const int& path_id); @@ -199,7 +196,8 @@ class BitstreamManager { /* Unique id of a block of bits in the Bitstream */ size_t num_blocks_; std::unordered_set invalid_block_ids_; - vtr::vector> block_bit_ids_; + vtr::vector block_bit_id_lsbs_; + vtr::vector block_bit_id_msbs_; /* Back-annotation for the bits */ /* Parent block of a bit in the Bitstream diff --git a/libopenfpga/libfpgabitstream/src/read_xml_arch_bitstream.cpp b/libopenfpga/libfpgabitstream/src/read_xml_arch_bitstream.cpp index 3895b85b6..04e0918f1 100644 --- a/libopenfpga/libfpgabitstream/src/read_xml_arch_bitstream.cpp +++ b/libopenfpga/libfpgabitstream/src/read_xml_arch_bitstream.cpp @@ -101,16 +101,17 @@ void rec_read_xml_bitstream_block(pugi::xml_node& xml_bitstream_block, } /* Find the child paths/nets */ + std::vector block_bits; for (pugi::xml_node xml_bit : xml_bitstream.children()) { /* We only care child bitstream blocks here */ if (xml_bit.name() != std::string("bit")) { bad_tag(xml_bit, loc_data, xml_bitstream, {"bit"}); } const int& bit_value = get_attribute(xml_bit, "value", loc_data).as_int(); - ConfigBitId bit = bitstream_manager.add_bit(1 == bit_value); - /* Link the bit to parent block */ - bitstream_manager.add_bit_to_block(curr_block, bit); - } + block_bits.push_back(1 == bit_value); + } + /* Link the bit to parent block */ + bitstream_manager.add_block_bits(curr_block, block_bits); } /* Go recursively: find all the child blocks and parse */ diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index 577402706..436c04697 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -106,12 +106,7 @@ void build_primitive_bitstream(BitstreamManager& bitstream_manager, bitstream_manager.add_child_block(parent_configurable_block, mem_block); /* Add the bitstream to the bitstream manager */ - bitstream_manager.reserve_block_bits(mem_block, mode_select_bitstream.size()); - for (const bool& bit : mode_select_bitstream) { - ConfigBitId config_bit = bitstream_manager.add_bit(bit); - /* Link the memory bits to the mux mem block */ - bitstream_manager.add_bit_to_block(mem_block, config_bit); - } + bitstream_manager.add_block_bits(mem_block, mode_select_bitstream); } /******************************************************************** @@ -215,12 +210,7 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); /* Add the bistream to the bitstream manager */ - bitstream_manager.reserve_block_bits(mux_mem_block, mux_bitstream.size()); - for (const bool& bit : mux_bitstream) { - ConfigBitId config_bit = bitstream_manager.add_bit(bit); - /* Link the memory bits to the mux mem block */ - bitstream_manager.add_bit_to_block(mux_mem_block, config_bit); - } + bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ bitstream_manager.add_path_id_to_block(mux_mem_block, mux_input_pin_id); bitstream_manager.reserve_block_input_net_ids(mux_mem_block, input_nets.size()); @@ -469,12 +459,7 @@ void build_lut_bitstream(BitstreamManager& bitstream_manager, bitstream_manager.add_child_block(parent_configurable_block, mem_block); /* Add the bitstream to the bitstream manager */ - bitstream_manager.reserve_block_bits(mem_block, lut_bitstream.size()); - for (const bool& bit : lut_bitstream) { - ConfigBitId config_bit = bitstream_manager.add_bit(bit); - /* Link the memory bits to the mux mem block */ - bitstream_manager.add_bit_to_block(mem_block, config_bit); - } + bitstream_manager.add_block_bits(mem_block, lut_bitstream); } /******************************************************************** diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp index c4dec00db..1e6b8d3c6 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -98,12 +98,7 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager, VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); /* Add the bistream to the bitstream manager */ - bitstream_manager.reserve_block_bits(mux_mem_block, mux_bitstream.size()); - for (const bool& bit : mux_bitstream) { - ConfigBitId config_bit = bitstream_manager.add_bit(bit); - /* Link the memory bits to the mux mem block */ - bitstream_manager.add_bit_to_block(mux_mem_block, config_bit); - } + bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ bitstream_manager.add_path_id_to_block(mux_mem_block, path_id); bitstream_manager.reserve_block_input_net_ids(mux_mem_block, input_nets.size()); @@ -292,12 +287,7 @@ void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager, VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width()); /* Add the bistream to the bitstream manager */ - bitstream_manager.reserve_block_bits(mux_mem_block, mux_bitstream.size()); - for (const bool& bit : mux_bitstream) { - ConfigBitId config_bit = bitstream_manager.add_bit(bit); - /* Link the memory bits to the mux mem block */ - bitstream_manager.add_bit_to_block(mux_mem_block, config_bit); - } + bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ bitstream_manager.add_path_id_to_block(mux_mem_block, path_id); bitstream_manager.reserve_block_input_net_ids(mux_mem_block, input_nets.size()); From 7d9c36aae12e4ea5aad7ce7a28e94dc94c9d3c00 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 12:06:15 -0600 Subject: [PATCH 21/25] use length instead of msb in bitstream manager for block bits to save memory --- .../src/bitstream_manager.cpp | 22 ++++++++++--------- .../libfpgabitstream/src/bitstream_manager.h | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index b2d894427..d8622617d 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -78,11 +78,15 @@ std::vector BitstreamManager::block_bits(const ConfigBlockId& block VTR_ASSERT(true == valid_block_id(block_id)); size_t lsb = block_bit_id_lsbs_[block_id]; - size_t msb = block_bit_id_msbs_[block_id]; + size_t length = block_bit_lengths_[block_id]; - std::vector bits(msb - lsb + 1, ConfigBitId::INVALID()); + std::vector bits(length, ConfigBitId::INVALID()); - for (size_t i = lsb; i < msb + 1; ++i) { + if (0 == length) { + return bits; + } + + for (size_t i = lsb; i < lsb + length; ++i) { bits[i - lsb] = ConfigBitId(i); } @@ -152,7 +156,7 @@ ConfigBitId BitstreamManager::add_bit(const bool& bit_value) { void BitstreamManager::reserve_blocks(const size_t& num_blocks) { block_names_.reserve(num_blocks); block_bit_id_lsbs_.reserve(num_blocks); - block_bit_id_msbs_.reserve(num_blocks); + block_bit_lengths_.reserve(num_blocks); block_path_ids_.reserve(num_blocks); block_input_net_ids_.reserve(num_blocks); block_output_net_ids_.reserve(num_blocks); @@ -169,8 +173,8 @@ ConfigBlockId BitstreamManager::create_block() { /* Add a new bit, and allocate associated data structures */ num_blocks_++; block_names_.emplace_back(); - block_bit_id_lsbs_.emplace_back(0); - block_bit_id_msbs_.emplace_back(-1); + block_bit_id_lsbs_.emplace_back(-1); + block_bit_lengths_.emplace_back(0); block_path_ids_.push_back(-2); block_input_net_ids_.emplace_back(); block_output_net_ids_.emplace_back(); @@ -218,13 +222,11 @@ void BitstreamManager::add_block_bits(const ConfigBlockId& block, VTR_ASSERT(true == valid_block_id(block)); /* Add the bit to the block, record anchors in bit indexing for block-level searching */ - size_t lsb = num_bits_; - size_t msb = num_bits_ + block_bitstream.size() - 1; + block_bit_id_lsbs_[block] = num_bits_; + block_bit_lengths_[block] = block_bitstream.size(); for (const bool& bit : block_bitstream) { add_bit(bit); } - block_bit_id_lsbs_[block] = lsb; - block_bit_id_msbs_[block] = msb; } void BitstreamManager::add_path_id_to_block(const ConfigBlockId& block, const int& path_id) { diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index dd724fac9..fbc5d39c3 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -197,7 +197,7 @@ class BitstreamManager { size_t num_blocks_; std::unordered_set invalid_block_ids_; vtr::vector block_bit_id_lsbs_; - vtr::vector block_bit_id_msbs_; + vtr::vector block_bit_lengths_; /* Back-annotation for the bits */ /* Parent block of a bit in the Bitstream From 70d96785782d4c288ff14f6bf48ec3526746a542 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 14:04:10 -0600 Subject: [PATCH 22/25] reserve child block in bistream manager --- libopenfpga/libfpgabitstream/src/bitstream_manager.cpp | 9 +++++++++ libopenfpga/libfpgabitstream/src/bitstream_manager.h | 4 ++++ openfpga/src/fpga_bitstream/build_device_bitstream.cpp | 4 ++++ 3 files changed, 17 insertions(+) diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp index d8622617d..990423802 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.cpp @@ -198,6 +198,15 @@ void BitstreamManager::set_block_name(const ConfigBlockId& block_id, block_names_[block_id] = block_name; } +void BitstreamManager::reserve_child_blocks(const ConfigBlockId& parent_block, + const size_t& num_children) { + /* Ensure the input ids are valid */ + VTR_ASSERT(true == valid_block_id(parent_block)); + + /* Add the child_block to the parent_block */ + child_block_ids_[parent_block].reserve(num_children); +} + 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)); diff --git a/libopenfpga/libfpgabitstream/src/bitstream_manager.h b/libopenfpga/libfpgabitstream/src/bitstream_manager.h index fbc5d39c3..6f2e56c38 100644 --- a/libopenfpga/libfpgabitstream/src/bitstream_manager.h +++ b/libopenfpga/libfpgabitstream/src/bitstream_manager.h @@ -163,6 +163,10 @@ class BitstreamManager { void set_block_name(const ConfigBlockId& block_id, const std::string& block_name); + /* Reserve child blocks for a block to be memory efficient */ + void reserve_child_blocks(const ConfigBlockId& parent_block, + const size_t& num_children); + /* Set a block as a child block of another */ void add_child_block(const ConfigBlockId& parent_block, const ConfigBlockId& child_block); diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 7e37b5943..3f38e03a7 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -144,6 +144,10 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, bitstream_manager.reserve_bits(num_bits_to_reserve); VTR_LOGV(verbose, "Reserved %lu configuration bits\n", num_bits_to_reserve); + /* Reserve child blocks for the top level block */ + bitstream_manager.reserve_child_blocks(top_block, + openfpga_ctx.module_graph().configurable_children(top_module).size()); + /* Create bitstream from grids */ VTR_LOGV(verbose, "Building grid bitstream...\n"); build_grid_bitstream(bitstream_manager, top_block, From 1f38e1711108e675afa984d0a74dc107ac2f28e4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 14:12:13 -0600 Subject: [PATCH 23/25] bug fix for naming conflicts in mux local encoder and architecture decoders --- openfpga/src/base/openfpga_naming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 84366b1ab..f4a72ff61 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -134,7 +134,7 @@ std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib, ***********************************************/ std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size, const size_t& data_size) { - std::string subckt_name = "decoder"; + std::string subckt_name = "local_encoder"; subckt_name += std::to_string(addr_size); subckt_name += "to"; subckt_name += std::to_string(data_size); From 2a9377b3f45a0c58c45ac1b68356f218d267c119 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 15:12:29 -0600 Subject: [PATCH 24/25] use encoded address in storage of fabric bitstream to save memory --- .../libopenfpgautil/src/openfpga_decode.cpp | 25 ++++++++++++++++ .../libopenfpgautil/src/openfpga_decode.h | 2 ++ .../fpga_bitstream/build_fabric_bitstream.cpp | 17 ++++++++--- .../src/fpga_bitstream/fabric_bitstream.cpp | 29 ++++++++++++++++--- .../src/fpga_bitstream/fabric_bitstream.h | 10 +++++-- 5 files changed, 73 insertions(+), 10 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp index fb0e32a37..168f98e42 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp @@ -103,4 +103,29 @@ std::vector itobin_charvec(const size_t& in_int, return ret; } +/******************************************************************** + * Converter a binary vector to an integer + * For example: + * Binary length : 3 + * Input: + * index | 0 | 1 | 2 + * ret | 0 | 0 | 1 + * + * Output integer: 4 + * + * This function is optimized to return a vector of char + * which has a smaller memory footprint than size_t + ********************************************************************/ +size_t bintoi_charvec(const std::vector& bin) { + size_t ret = 0; + + for (size_t i = 0; i < bin.size(); ++i) { + if ('1' == bin[i]) { + ret += pow(2., i); + } + } + + return ret; +} + } /* end namespace openfpga */ diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.h b/libopenfpga/libopenfpgautil/src/openfpga_decode.h index 064717fbc..ab6778c86 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.h @@ -21,6 +21,8 @@ std::vector itobin_vec(const size_t& in_int, std::vector itobin_charvec(const size_t& in_int, const size_t& bin_len); +size_t bintoi_charvec(const std::vector& bin); + } /* namespace openfpga ends */ #endif diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 38724aad8..b960d188a 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -398,10 +398,6 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc break; } case CONFIG_MEM_MEMORY_BANK: { - /* Reserve bits before build-up */ - fabric_bitstream.set_use_address(true); - fabric_bitstream.set_use_wl_address(true); - fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); size_t cur_mem_index = 0; /* Find BL address port size */ @@ -426,6 +422,13 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc ModulePortId wl_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); BasicPort wl_port_info = module_manager.module_port(wl_decoder_module, wl_port); + /* Reserve bits before build-up */ + fabric_bitstream.set_use_address(true); + fabric_bitstream.set_use_wl_address(true); + fabric_bitstream.set_bl_address_length(bl_port_info.get_width()); + fabric_bitstream.set_wl_address_length(wl_port_info.get_width()); + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); + rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, top_block, module_manager, top_module, top_module, bl_addr_port_info.get_width(), @@ -436,9 +439,15 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc break; } case CONFIG_MEM_FRAME_BASED: { + + /* Find address port size */ + ModulePortId addr_port = module_manager.find_module_port(top_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort addr_port_info = module_manager.module_port(top_module, addr_port); + /* Reserve bits before build-up */ fabric_bitstream.set_use_address(true); fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); + fabric_bitstream.set_address_length(addr_port_info.get_width()); rec_build_module_fabric_dependent_frame_bitstream(bitstream_manager, std::vector(1, top_block), diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index f8f3a956f..750cc0296 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -4,6 +4,7 @@ #include #include "vtr_assert.h" +#include "openfpga_decode.h" #include "fabric_bitstream.h" /* begin namespace openfpga */ @@ -15,6 +16,8 @@ namespace openfpga { FabricBitstream::FabricBitstream() { num_bits_ = 0; invalid_bit_ids_.clear(); + address_length_ = 0; + wl_address_length_ = 0; } /************************************************** @@ -45,7 +48,7 @@ std::vector FabricBitstream::bit_address(const FabricBitId& bit_id) const VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); - return bit_addresses_[bit_id]; + return itobin_charvec(bit_addresses_[bit_id], address_length_); } std::vector FabricBitstream::bit_bl_address(const FabricBitId& bit_id) const { @@ -58,7 +61,7 @@ std::vector FabricBitstream::bit_wl_address(const FabricBitId& bit_id) con VTR_ASSERT(true == use_address_); VTR_ASSERT(true == use_wl_address_); - return bit_wl_addresses_[bit_id]; + return itobin_charvec(bit_wl_addresses_[bit_id], wl_address_length_); } char FabricBitstream::bit_din(const FabricBitId& bit_id) const { @@ -106,7 +109,8 @@ void FabricBitstream::set_bit_address(const FabricBitId& bit_id, const std::vector& address) { VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); - bit_addresses_[bit_id] = address; + VTR_ASSERT(address_length_ == address.size()); + bit_addresses_[bit_id] = bintoi_charvec(address); } void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id, @@ -119,7 +123,8 @@ void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id, VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); VTR_ASSERT(true == use_wl_address_); - bit_wl_addresses_[bit_id] = address; + VTR_ASSERT(wl_address_length_ == address.size()); + bit_wl_addresses_[bit_id] = bintoi_charvec(address); } void FabricBitstream::set_bit_din(const FabricBitId& bit_id, @@ -149,6 +154,16 @@ void FabricBitstream::set_use_address(const bool& enable) { } } +void FabricBitstream::set_address_length(const size_t& length) { + if (true == use_address_) { + address_length_ = length; + } +} + +void FabricBitstream::set_bl_address_length(const size_t& length) { + set_address_length(length); +} + void FabricBitstream::set_use_wl_address(const bool& enable) { /* Add a lock, only can be modified when num bits are zero*/ if (0 == num_bits_) { @@ -156,6 +171,12 @@ void FabricBitstream::set_use_wl_address(const bool& enable) { } } +void FabricBitstream::set_wl_address_length(const size_t& length) { + if (true == use_address_) { + wl_address_length_ = length; + } +} + /****************************************************************************** * Public Validators ******************************************************************************/ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index ea64b4590..9869fffed 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -152,11 +152,14 @@ class FabricBitstream { * This function is only applicable before any bits are added */ void set_use_address(const bool& enable); + void set_address_length(const size_t& length); + void set_bl_address_length(const size_t& length); /* Enable the use of WL-address related data * Same priniciple as the set_use_address() */ void set_use_wl_address(const bool& enable); + void set_wl_address_length(const size_t& length); public: /* Public Validators */ char valid_bit_id(const FabricBitId& bit_id) const; @@ -171,14 +174,17 @@ class FabricBitstream { bool use_address_; bool use_wl_address_; + size_t address_length_; + size_t wl_address_length_; + /* Address bits: this is designed for memory decoders * Here we store the binary format of the address, which can be loaded * to the configuration protocol directly * * We use a 2-element array, as we may have a BL address and a WL address */ - vtr::vector> bit_addresses_; - vtr::vector> bit_wl_addresses_; + vtr::vector bit_addresses_; + vtr::vector bit_wl_addresses_; /* Data input (Din) bits: this is designed for memory decoders */ vtr::vector bit_dins_; From 8067a133466a6a1ea890188e12942d8f45d49383 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Jul 2020 15:56:20 -0600 Subject: [PATCH 25/25] bug fix for memory bank due to encoding bl/wl addresses in fabric bitstream --- openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index b960d188a..05e93d22a 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -425,8 +425,8 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc /* Reserve bits before build-up */ fabric_bitstream.set_use_address(true); fabric_bitstream.set_use_wl_address(true); - fabric_bitstream.set_bl_address_length(bl_port_info.get_width()); - fabric_bitstream.set_wl_address_length(wl_port_info.get_width()); + fabric_bitstream.set_bl_address_length(bl_addr_port_info.get_width()); + fabric_bitstream.set_wl_address_length(wl_addr_port_info.get_width()); fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, top_block,