Skip to content

Commit

Permalink
Merge pull request #1756 from chungshien/openfpga-overwrite-bits
Browse files Browse the repository at this point in the history
Openfpga support setting bitstream bit manually
  • Loading branch information
tangxifan authored Jul 31, 2024
2 parents 4defb9e + b3c8c52 commit 6ea1feb
Show file tree
Hide file tree
Showing 18 changed files with 553 additions and 19 deletions.
36 changes: 33 additions & 3 deletions docs/source/manual/file_formats/bitstream_setting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab
<non_fabric name="<string>" file="<string>">
<pb name="<string>" type="<string>" content="<string>"/>
</non_fabric>
<overwrite_bitstream>
<bit value="<0 or 1>" path="<string>"/>
</overwrite_bitstream>
</openfpga_bitstream_setting>
pb_type-related Settings
Expand Down Expand Up @@ -75,7 +78,7 @@ The following syntax are applicable to the XML definition tagged by ``interconne
The default path can be either ``iopad.inpad`` or ``ff.Q`` which corresponds to the first input and the second input respectively.

non_fabric-related Settings
^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is special syntax to extract PB defined parameter or attribute and save the data into dedicated JSON file outside of fabric bitstream

Expand All @@ -97,7 +100,7 @@ The following syntax are applicable to the XML definition tagged by ``non_fabric
file="bram.json"
.. option:: ``pb`` child element name="<string: pb_type child name>"
.. option:: pb child element name="<string: pb_type child name>"

Together with ``pb_type`` top level name, that is the source of the ``pb_type`` bitstream

Expand All @@ -112,6 +115,33 @@ The following syntax are applicable to the XML definition tagged by ``non_fabric
The final ``pb_type`` name is "bram.bram_lr[mem_36K_tdp].mem_36K"

.. option:: ``pb`` child element content="<string>"
.. option:: pb child element content="<string>"

The content of the ``pb_type`` data to be extracted. For example, ``content=".param INIT_i"`` means that the data will be extracted from the ``.param INIT_i`` line defined under the ``.blif model``.

overwrite_bitstream-related Settings
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is to allow user to set value of a list of bits which is represented using full path in the hierarchy of FPGA fabric

This ``overwrite_bitstream`` settings has the highest priority than loading any external bitstream file

Each bit to overwrite is represented by one ``bit`` child node/tag

The following syntax are applicable to the XML definition tagged by ``bit`` node under ``overwrite_bitstream`` setting.

.. option:: value="<0 or 1>"

The boolean ``0`` or ``1`` that will be set. For example,

.. code-block:: xml
value="0"
.. option:: path="<string>"

``path`` represents the location of this block in FPGA fabric, i.e., the full path in the hierarchy of FPGA fabric.

.. code-block:: xml
path="fpga_top.grid_clb_1__2_.logical_tile_clb_mode_clb__0.mem_fle_9_in_5[0]"
43 changes: 43 additions & 0 deletions libs/libarchopenfpga/src/bitstream_setting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ BitstreamSetting::interconnect_settings() const {
interconnect_setting_ids_.end());
}

BitstreamSetting::overwrite_bitstream_range
BitstreamSetting::overwrite_bitstreams() const {
return vtr::make_range(overwrite_bitstream_ids_.begin(),
overwrite_bitstream_ids_.end());
}

/************************************************************************
* Constructors
***********************************************************************/
Expand Down Expand Up @@ -106,6 +112,18 @@ std::vector<NonFabricBitstreamSetting> BitstreamSetting::non_fabric() const {
return non_fabric_;
}

std::string BitstreamSetting::overwrite_bitstream_path(
const OverwriteBitstreamId& id) const {
VTR_ASSERT(true == valid_overwrite_bitstream_id(id));
return overwrite_bitstream_paths_[id];
}

bool BitstreamSetting::overwrite_bitstream_value(
const OverwriteBitstreamId& id) const {
VTR_ASSERT(true == valid_overwrite_bitstream_id(id));
return overwrite_bitstream_values_[id];
}

/************************************************************************
* Public Mutators
***********************************************************************/
Expand Down Expand Up @@ -178,6 +196,21 @@ void BitstreamSetting::add_non_fabric_pb(const std::string& pb,
}
}

OverwriteBitstreamId BitstreamSetting::add_overwrite_bitstream(
const std::string& path, const bool& value) {
VTR_ASSERT(path.size());
VTR_ASSERT(overwrite_bitstream_ids_.size() ==
overwrite_bitstream_paths_.size());
VTR_ASSERT(overwrite_bitstream_paths_.size() ==
overwrite_bitstream_values_.size());
OverwriteBitstreamId id =
OverwriteBitstreamId(overwrite_bitstream_ids_.size());
overwrite_bitstream_ids_.push_back(id);
overwrite_bitstream_paths_.push_back(path);
overwrite_bitstream_values_.push_back(value);
return id;
}

/************************************************************************
* Public Validators
***********************************************************************/
Expand All @@ -194,4 +227,14 @@ bool BitstreamSetting::valid_bitstream_interconnect_setting_id(
interconnect_setting_ids_[interconnect_setting_id]);
}

bool BitstreamSetting::valid_overwrite_bitstream_id(
const OverwriteBitstreamId& id) const {
VTR_ASSERT(overwrite_bitstream_ids_.size() ==
overwrite_bitstream_paths_.size());
VTR_ASSERT(overwrite_bitstream_paths_.size() ==
overwrite_bitstream_values_.size());
return (size_t(id) < overwrite_bitstream_ids_.size()) &&
(id == overwrite_bitstream_ids_[id]);
}

} // namespace openfpga
15 changes: 15 additions & 0 deletions libs/libarchopenfpga/src/bitstream_setting.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,23 @@ class BitstreamSetting {
typedef vtr::vector<BitstreamInterconnectSettingId,
BitstreamInterconnectSettingId>::const_iterator
bitstream_interconnect_setting_iterator;
typedef vtr::vector<OverwriteBitstreamId,
OverwriteBitstreamId>::const_iterator
overwrite_bitstream_iterator;
/* Create range */
typedef vtr::Range<bitstream_pb_type_setting_iterator>
bitstream_pb_type_setting_range;
typedef vtr::Range<bitstream_interconnect_setting_iterator>
bitstream_interconnect_setting_range;
typedef vtr::Range<overwrite_bitstream_iterator> overwrite_bitstream_range;

public: /* Constructors */
BitstreamSetting();

public: /* Accessors: aggregates */
bitstream_pb_type_setting_range pb_type_settings() const;
bitstream_interconnect_setting_range interconnect_settings() const;
overwrite_bitstream_range overwrite_bitstreams() const;

public: /* Public Accessors */
std::string pb_type_name(
Expand All @@ -98,6 +103,8 @@ class BitstreamSetting {
std::string default_path(
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
std::vector<NonFabricBitstreamSetting> non_fabric() const;
std::string overwrite_bitstream_path(const OverwriteBitstreamId& id) const;
bool overwrite_bitstream_value(const OverwriteBitstreamId& id) const;

public: /* Public Mutators */
BitstreamPbTypeSettingId add_bitstream_pb_type_setting(
Expand All @@ -120,11 +127,15 @@ class BitstreamSetting {
void add_non_fabric(const std::string& name, const std::string& file);
void add_non_fabric_pb(const std::string& pb, const std::string& content);

OverwriteBitstreamId add_overwrite_bitstream(const std::string& path,
const bool& value);

public: /* Public Validators */
bool valid_bitstream_pb_type_setting_id(
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
bool valid_bitstream_interconnect_setting_id(
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
bool valid_overwrite_bitstream_id(const OverwriteBitstreamId& id) const;

private: /* Internal data */
/* Pb type -related settings
Expand Down Expand Up @@ -162,6 +173,10 @@ class BitstreamSetting {
vtr::vector<BitstreamInterconnectSettingId, std::string>
interconnect_default_paths_;
std::vector<NonFabricBitstreamSetting> non_fabric_;
vtr::vector<OverwriteBitstreamId, OverwriteBitstreamId>
overwrite_bitstream_ids_;
vtr::vector<OverwriteBitstreamId, std::string> overwrite_bitstream_paths_;
vtr::vector<OverwriteBitstreamId, bool> overwrite_bitstream_values_;
};

} // namespace openfpga
Expand Down
2 changes: 2 additions & 0 deletions libs/libarchopenfpga/src/bitstream_setting_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@

struct bitstream_pb_type_setting_id_tag;
struct bitstream_interconnect_setting_id_tag;
struct overwrite_bitstream_id_tag;

typedef vtr::StrongId<bitstream_pb_type_setting_id_tag>
BitstreamPbTypeSettingId;
typedef vtr::StrongId<bitstream_interconnect_setting_id_tag>
BitstreamInterconnectSettingId;
typedef vtr::StrongId<overwrite_bitstream_id_tag> OverwriteBitstreamId;

/* Short declaration of class */
class BitstreamSetting;
Expand Down
36 changes: 32 additions & 4 deletions libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,30 @@ static void read_xml_non_fabric_bitstream_setting(
}
}

/********************************************************************
* Parse XML description for a bit setting under a <bit> XML node
*******************************************************************/
static void read_xml_overwrite_bitstream_setting(
pugi::xml_node& xml_overwrite_bitstream, const pugiutil::loc_data& loc_data,
openfpga::BitstreamSetting& bitstream_setting) {
// Loopthrough bit
for (pugi::xml_node xml_bit : xml_overwrite_bitstream.children()) {
if (xml_bit.name() != std::string("bit")) {
bad_tag(xml_bit, loc_data, xml_overwrite_bitstream, {"bit"});
}
const std::string& path_attr =
get_attribute(xml_bit, "path", loc_data).as_string();
const std::string& value_attr =
get_attribute(xml_bit, "value", loc_data).as_string();
if (value_attr != "0" && value_attr != "1") {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bit),
"Invalid value of overwrite_bitstream bit. Expect [0|1]");
}
/* Add to bit */
bitstream_setting.add_overwrite_bitstream(path_attr, value_attr == "1");
}
}

/********************************************************************
* Parse XML codes about <openfpga_bitstream_setting> to an object
*******************************************************************/
Expand All @@ -116,9 +140,10 @@ openfpga::BitstreamSetting read_xml_bitstream_setting(
/* Error out if the XML child has an invalid name! */
if ((xml_child.name() != std::string("pb_type")) &&
(xml_child.name() != std::string("interconnect")) &&
(xml_child.name() != std::string("non_fabric"))) {
(xml_child.name() != std::string("non_fabric")) &&
(xml_child.name() != std::string("overwrite_bitstream"))) {
bad_tag(xml_child, loc_data, Node,
{"pb_type | interconnect | non_fabric"});
{"pb_type | interconnect | non_fabric | overwrite_bitstream"});
}

if (xml_child.name() == std::string("pb_type")) {
Expand All @@ -127,10 +152,13 @@ openfpga::BitstreamSetting read_xml_bitstream_setting(
} else if (xml_child.name() == std::string("interconnect")) {
read_xml_bitstream_interconnect_setting(xml_child, loc_data,
bitstream_setting);
} else {
VTR_ASSERT_SAFE(xml_child.name() == std::string("non_fabric"));
} else if (xml_child.name() == std::string("non_fabric")) {
read_xml_non_fabric_bitstream_setting(xml_child, loc_data,
bitstream_setting);
} else {
VTR_ASSERT_SAFE(xml_child.name() == std::string("overwrite_bitstream"));
read_xml_overwrite_bitstream_setting(xml_child, loc_data,
bitstream_setting);
}
}

Expand Down
67 changes: 67 additions & 0 deletions libs/libfpgabitstream/src/bitstream_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

#include <algorithm>

#include "arch_error.h"
#include "bitstream_manager_utils.h"
#include "openfpga_port_parser.h"
#include "openfpga_tokenizer.h"
#include "vtr_assert.h"
#include "vtr_log.h"

Expand Down Expand Up @@ -296,6 +300,69 @@ void BitstreamManager::add_output_net_id_to_block(
block_output_net_ids_[block] = output_net_id;
}

void BitstreamManager::overwrite_bitstream(const std::string& path,
const bool& value) {
PortParser port_parser(path, PORT_PARSER_SUPPORT_SINGLE_INDEX_FORMAT);
if (!port_parser.valid()) {
archfpga_throw(__FILE__, __LINE__,
"overwrite_bitstream bit path '%s' does not match format "
"<full path in the hierarchy of FPGA fabric>[bit index]",
path.c_str());
} else {
BasicPort port = port_parser.port();
size_t bit = port.get_lsb();
StringToken tokenizer(port.get_name());
std::vector<std::string> blocks = tokenizer.split(".");
std::vector<ConfigBlockId> block_ids;
ConfigBlockId block_id = ConfigBlockId::INVALID();
size_t found = 0;
for (size_t i = 0; i < blocks.size(); i++) {
if (i == 0) {
block_ids = find_bitstream_manager_top_blocks(*this);
} else {
block_ids = block_children(block_id);
}
// Reset
block_id = ConfigBlockId::INVALID();
// Find the one from the list that match the name
for (auto id : block_ids) {
if (block_name(id) == blocks[i]) {
block_id = id;
break;
}
}
if (block_id != ConfigBlockId::INVALID()) {
// Found one that match the name
found++;
if (found == blocks.size()) {
// Last one, no more child must end here
if (block_children(block_id).size() == 0) {
std::vector<ConfigBitId> ids = block_bits(block_id);
if (bit < ids.size()) {
VTR_ASSERT(valid_bit_id(ids[bit]));
bit_values_[ids[bit]] = value ? '1' : '0';
} else {
// No configuration bits at all or out of range, invalidate
found = 0;
}
} else {
// There are more child, hence the path still no end, invalidate
found = 0;
}
}
} else {
// Cannot match the name, just stop
break;
}
}
if (found != blocks.size()) {
archfpga_throw(__FILE__, __LINE__,
"Failed to find path '%s' to overwrite bitstream",
path.c_str());
}
}
}

/******************************************************************************
* Public Validators
******************************************************************************/
Expand Down
3 changes: 3 additions & 0 deletions libs/libfpgabitstream/src/bitstream_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ class BitstreamManager {
void add_output_net_id_to_block(const ConfigBlockId& block,
const std::string& output_net_id);

/* Set bit to the bitstream at the given path */
void overwrite_bitstream(const std::string& path, const bool& value);

public: /* Public Validators */
bool valid_bit_id(const ConfigBitId& bit_id) const;

Expand Down
Loading

0 comments on commit 6ea1feb

Please sign in to comment.