Skip to content

Commit

Permalink
Merge pull request #1906 from lnis-uofu/xt_bitset
Browse files Browse the repository at this point in the history
Support overwriting mode_bits for pb_type through bitstream setting file
  • Loading branch information
tangxifan authored Nov 26, 2024
2 parents 5c8a59f + 6e89943 commit 0bc1659
Show file tree
Hide file tree
Showing 21 changed files with 491 additions and 37 deletions.
27 changes: 27 additions & 0 deletions docs/source/manual/file_formats/bitstream_setting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab
<openfpga_bitstream_setting>
<pb_type name="<string>" source="eblif" content=".param LUT" is_mode_select_bistream="true" bitstream_offset="1"/>
<default_mode_bits name="<string>" mode_bits="<string>"/>
<interconnect name="<string>" default_path="<string>"/>
<non_fabric name="<string>" file="<string>">
<pb name="<string>" type="<string>" content="<string>"/>
Expand Down Expand Up @@ -54,6 +55,32 @@ The following syntax are applicable to the XML definition tagged by ``pb_type``

Specify the offset to be applied when overloading the bitstream to a target. For example, a LUT may have a 16-bit bitstream. When ``offset=1``, bitstream overloading will skip the first bit and start from the second bit of the 16-bit bitstream.

Default Mode Bits-related Settings
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The following syntax are applicable to the XML definition tagged by ``default_mode_bits`` in bitstream setting files.

.. option:: name="<string>"

The ``pb_type`` name to be constrained, which should be the full path of a ``pb_type`` consistent with VPR's architecture description. For example,

.. note:: This must be a valid primitive pb_type (one has zero leaf nodes)!

.. code-block:: xml
pb_type="clb.fle[arithmetic].soft_adder.adder_lut4"
.. option:: mode_bits="<string>"

The default mode bits when the ``pb_type`` is not mapped. Note that the size of mode bits must comply with the definition in the OpenFPGA architecture description (See details in :ref:`annotate_vpr_arch_pb_type_annotation`). For example,

.. note:: Bitstream setting has a higher priority than the ``mode_bits`` definition in the OpenFPGA architecture description!

.. code-block:: xml
mode_bits="0100"
Interconnection-related Settings
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
70 changes: 70 additions & 0 deletions libs/libarchopenfpga/src/bitstream_setting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ BitstreamSetting::pb_type_settings() const {
pb_type_setting_ids_.end());
}

BitstreamSetting::bitstream_default_mode_setting_range
BitstreamSetting::default_mode_settings() const {
return vtr::make_range(default_mode_setting_ids_.begin(),
default_mode_setting_ids_.end());
}

BitstreamSetting::bitstream_interconnect_setting_range
BitstreamSetting::interconnect_settings() const {
return vtr::make_range(interconnect_setting_ids_.begin(),
Expand Down Expand Up @@ -80,6 +86,46 @@ size_t BitstreamSetting::bitstream_offset(
return bitstream_offsets_[pb_type_setting_id];
}

std::string BitstreamSetting::default_mode_pb_type_name(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const {
VTR_ASSERT(true ==
valid_bitstream_default_mode_setting_id(default_mode_setting_id));
return default_mode_pb_type_names_[default_mode_setting_id];
}

std::vector<std::string> BitstreamSetting::default_mode_parent_pb_type_names(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const {
VTR_ASSERT(true ==
valid_bitstream_default_mode_setting_id(default_mode_setting_id));
return default_mode_parent_pb_type_names_[default_mode_setting_id];
}

std::vector<std::string> BitstreamSetting::default_mode_parent_mode_names(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const {
VTR_ASSERT(true ==
valid_bitstream_default_mode_setting_id(default_mode_setting_id));
return default_mode_parent_mode_names_[default_mode_setting_id];
}

std::vector<size_t> BitstreamSetting::default_mode_bits(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const {
VTR_ASSERT(true ==
valid_bitstream_default_mode_setting_id(default_mode_setting_id));
return pb_type_default_mode_bits_[default_mode_setting_id];
}

std::string BitstreamSetting::default_mode_bits_to_string(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const {
VTR_ASSERT(true ==
valid_bitstream_default_mode_setting_id(default_mode_setting_id));
std::string mode_bits_str;
for (const size_t& bit :
pb_type_default_mode_bits_[default_mode_setting_id]) {
mode_bits_str += std::to_string(bit);
}
return mode_bits_str;
}

std::string BitstreamSetting::interconnect_name(
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
VTR_ASSERT(true ==
Expand Down Expand Up @@ -159,6 +205,23 @@ void BitstreamSetting::set_bitstream_offset(
bitstream_offsets_[pb_type_setting_id] = offset;
}

BitstreamDefaultModeSettingId
BitstreamSetting::add_bitstream_default_mode_setting(
const std::string& pb_type_name,
const std::vector<std::string>& parent_pb_type_names,
const std::vector<std::string>& parent_mode_names,
const std::vector<size_t>& mode_bits) {
BitstreamDefaultModeSettingId default_mode_setting_id =
BitstreamDefaultModeSettingId(default_mode_setting_ids_.size());
default_mode_setting_ids_.push_back(default_mode_setting_id);
default_mode_pb_type_names_.push_back(pb_type_name);
default_mode_parent_pb_type_names_.push_back(parent_pb_type_names);
default_mode_parent_mode_names_.push_back(parent_mode_names);
pb_type_default_mode_bits_.push_back(mode_bits);

return default_mode_setting_id;
}

BitstreamInterconnectSettingId
BitstreamSetting::add_bitstream_interconnect_setting(
const std::string& interconnect_name,
Expand Down Expand Up @@ -220,6 +283,13 @@ bool BitstreamSetting::valid_bitstream_pb_type_setting_id(
(pb_type_setting_id == pb_type_setting_ids_[pb_type_setting_id]);
}

bool BitstreamSetting::valid_bitstream_default_mode_setting_id(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const {
return (size_t(default_mode_setting_id) < default_mode_setting_ids_.size()) &&
(default_mode_setting_id ==
default_mode_setting_ids_[default_mode_setting_id]);
}

bool BitstreamSetting::valid_bitstream_interconnect_setting_id(
const BitstreamInterconnectSettingId& interconnect_setting_id) const {
return (size_t(interconnect_setting_id) < interconnect_setting_ids_.size()) &&
Expand Down
40 changes: 40 additions & 0 deletions libs/libarchopenfpga/src/bitstream_setting.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <vector>

#include "bitstream_setting_fwd.h"
#include "vtr_geometry.h"
#include "vtr_vector.h"

/* namespace openfpga begins */
Expand Down Expand Up @@ -58,6 +59,9 @@ class BitstreamSetting {
typedef vtr::vector<BitstreamPbTypeSettingId,
BitstreamPbTypeSettingId>::const_iterator
bitstream_pb_type_setting_iterator;
typedef vtr::vector<BitstreamDefaultModeSettingId,
BitstreamDefaultModeSettingId>::const_iterator
bitstream_default_mode_setting_iterator;
typedef vtr::vector<BitstreamInterconnectSettingId,
BitstreamInterconnectSettingId>::const_iterator
bitstream_interconnect_setting_iterator;
Expand All @@ -67,6 +71,8 @@ class BitstreamSetting {
/* Create range */
typedef vtr::Range<bitstream_pb_type_setting_iterator>
bitstream_pb_type_setting_range;
typedef vtr::Range<bitstream_default_mode_setting_iterator>
bitstream_default_mode_setting_range;
typedef vtr::Range<bitstream_interconnect_setting_iterator>
bitstream_interconnect_setting_range;
typedef vtr::Range<overwrite_bitstream_iterator> overwrite_bitstream_range;
Expand All @@ -76,6 +82,7 @@ class BitstreamSetting {

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

Expand All @@ -94,6 +101,19 @@ class BitstreamSetting {
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
size_t bitstream_offset(
const BitstreamPbTypeSettingId& pb_type_setting_id) const;

/* Default Mode Bit settings */
std::string default_mode_pb_type_name(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const;
std::vector<std::string> default_mode_parent_pb_type_names(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const;
std::vector<std::string> default_mode_parent_mode_names(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const;
std::vector<size_t> default_mode_bits(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const;
std::string default_mode_bits_to_string(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const;

std::string interconnect_name(
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
std::vector<std::string> parent_pb_type_names(
Expand All @@ -118,6 +138,12 @@ class BitstreamSetting {
void set_bitstream_offset(const BitstreamPbTypeSettingId& pb_type_setting_id,
const size_t& offset);

BitstreamDefaultModeSettingId add_bitstream_default_mode_setting(
const std::string& pb_type_name,
const std::vector<std::string>& parent_pb_type_names,
const std::vector<std::string>& parent_mode_names,
const std::vector<size_t>& mode_bits);

BitstreamInterconnectSettingId add_bitstream_interconnect_setting(
const std::string& interconnect_name,
const std::vector<std::string>& parent_pb_type_names,
Expand All @@ -133,6 +159,8 @@ class BitstreamSetting {
public: /* Public Validators */
bool valid_bitstream_pb_type_setting_id(
const BitstreamPbTypeSettingId& pb_type_setting_id) const;
bool valid_bitstream_default_mode_setting_id(
const BitstreamDefaultModeSettingId& default_mode_setting_id) const;
bool valid_bitstream_interconnect_setting_id(
const BitstreamInterconnectSettingId& interconnect_setting_id) const;
bool valid_overwrite_bitstream_id(const OverwriteBitstreamId& id) const;
Expand All @@ -158,6 +186,18 @@ class BitstreamSetting {
* pb_type */
vtr::vector<BitstreamPbTypeSettingId, size_t> bitstream_offsets_;

/* Pb type - default mode bits overwrite */
vtr::vector<BitstreamDefaultModeSettingId, BitstreamDefaultModeSettingId>
default_mode_setting_ids_;
vtr::vector<BitstreamDefaultModeSettingId, std::string>
default_mode_pb_type_names_;
vtr::vector<BitstreamDefaultModeSettingId, std::vector<std::string>>
default_mode_parent_pb_type_names_;
vtr::vector<BitstreamDefaultModeSettingId, std::vector<std::string>>
default_mode_parent_mode_names_;
vtr::vector<BitstreamDefaultModeSettingId, std::vector<size_t>>
pb_type_default_mode_bits_;

/* Interconnect-related settings:
* - Name of interconnect under a given pb_type
* - The default path to be considered for a given interconnect during
Expand Down
3 changes: 3 additions & 0 deletions libs/libarchopenfpga/src/bitstream_setting_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
#include "vtr_strong_id.h"

struct bitstream_pb_type_setting_id_tag;
struct bitstream_default_mode_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_default_mode_setting_id_tag>
BitstreamDefaultModeSettingId;
typedef vtr::StrongId<bitstream_interconnect_setting_id_tag>
BitstreamInterconnectSettingId;
typedef vtr::StrongId<overwrite_bitstream_id_tag> OverwriteBitstreamId;
Expand Down
35 changes: 33 additions & 2 deletions libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_bitstream_setting.h"
#include "read_xml_openfpga_arch_utils.h"
#include "read_xml_util.h"

/********************************************************************
Expand Down Expand Up @@ -56,6 +57,29 @@ static void read_xml_bitstream_pb_type_setting(
bitstream_setting.set_bitstream_offset(bitstream_pb_type_id, offset);
}

/********************************************************************
* Parse XML description for a pb_type annotation under a <default_mode_bits>
*XML node
*******************************************************************/
static void read_xml_bitstream_default_mode_setting(
pugi::xml_node& xml_pb_type, const pugiutil::loc_data& loc_data,
openfpga::BitstreamSetting& bitstream_setting) {
const std::string& name_attr =
get_attribute(xml_pb_type, "name", loc_data).as_string();
/* Parse the attributes for operating pb_type */
openfpga::PbParser operating_pb_parser(name_attr);

const std::string& mode_bits_attr =
get_attribute(xml_pb_type, "mode_bits", loc_data).as_string();
std::vector<size_t> mode_bits =
parse_mode_bits(xml_pb_type, loc_data, mode_bits_attr);

/* Add to bitstream setting */
bitstream_setting.add_bitstream_default_mode_setting(
operating_pb_parser.leaf(), operating_pb_parser.parents(),
operating_pb_parser.modes(), mode_bits);
}

/********************************************************************
* Parse XML description for a pb_type annotation under a <interconect> XML node
*******************************************************************/
Expand Down Expand Up @@ -137,18 +161,25 @@ openfpga::BitstreamSetting read_xml_bitstream_setting(
* each child should be named after <pb_type>
*/
for (pugi::xml_node xml_child : Node.children()) {
/* Error out if the XML child has an invalid name! */
/* Error out if the XML child has an invalid name!
* TODO: Use std::map or something similar to apply checks!
*/
if ((xml_child.name() != std::string("pb_type")) &&
(xml_child.name() != std::string("default_mode_bits")) &&
(xml_child.name() != std::string("interconnect")) &&
(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 | overwrite_bitstream"});
{"pb_type | interconnect | default_mode_bits | non_fabric | "
"overwrite_bitstream"});
}

if (xml_child.name() == std::string("pb_type")) {
read_xml_bitstream_pb_type_setting(xml_child, loc_data,
bitstream_setting);
} else if (xml_child.name() == std::string("default_mode_bits")) {
read_xml_bitstream_default_mode_setting(xml_child, loc_data,
bitstream_setting);
} else if (xml_child.name() == std::string("interconnect")) {
read_xml_bitstream_interconnect_setting(xml_child, loc_data,
bitstream_setting);
Expand Down
42 changes: 42 additions & 0 deletions libs/libarchopenfpga/src/read_xml_openfpga_arch_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML modeling OpenFPGA architecture to the associated
* data structures
*******************************************************************/
#include <string>

/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"

/* Headers from vtr util library */
#include "vtr_assert.h"

/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_openfpga_arch_utils.h"

/********************************************************************
* Parse mode_bits: convert from string to array of digits
* We only allow the bit to either '0' or '1'
*******************************************************************/
std::vector<size_t> parse_mode_bits(pugi::xml_node& xml_mode_bits,
const pugiutil::loc_data& loc_data,
const std::string& mode_bit_str) {
std::vector<size_t> mode_bits;

for (const char& bit_char : mode_bit_str) {
if ('0' == bit_char) {
mode_bits.push_back(0);
} else if ('1' == bit_char) {
mode_bits.push_back(1);
} else {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_mode_bits),
"Unexpected '%c' character found in the mode bit '%s'! "
"Only allow either '0' or '1'\n",
bit_char, mode_bit_str.c_str());
}
}

return mode_bits;
}
20 changes: 20 additions & 0 deletions libs/libarchopenfpga/src/read_xml_openfpga_arch_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef READ_XML_OPENFPGA_ARCH_UTILS_H
#define READ_XML_OPENFPGA_ARCH_UTILS_H

/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>

#include "bitstream_setting.h"
#include "openfpga_arch.h"
#include "simulation_setting.h"

/********************************************************************
* Function declaration
*******************************************************************/
std::vector<size_t> parse_mode_bits(pugi::xml_node& xml_mode_bits,
const pugiutil::loc_data& loc_data,
const std::string& mode_bit_str);

#endif
Loading

0 comments on commit 0bc1659

Please sign in to comment.