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