From d909d5ac51fec1856a4d87e18f292af3d84a7b13 Mon Sep 17 00:00:00 2001 From: chungshien Date: Tue, 13 Feb 2024 10:36:17 -0800 Subject: [PATCH 01/19] BRAM preload data - generic way to extract data from design --- .../libarchopenfpga/src/bitstream_setting.cpp | 20 ++ libs/libarchopenfpga/src/bitstream_setting.h | 30 +++ .../src/read_xml_bitstream_setting.cpp | 40 ++- .../src/base/openfpga_bitstream_template.h | 4 + .../extract_device_none_fabric_bitstream.cpp | 255 ++++++++++++++++++ .../extract_device_none_fabric_bitstream.h | 25 ++ 6 files changed, 370 insertions(+), 4 deletions(-) create mode 100644 openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp create mode 100644 openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.h diff --git a/libs/libarchopenfpga/src/bitstream_setting.cpp b/libs/libarchopenfpga/src/bitstream_setting.cpp index c04eeba879..7186864b2b 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/bitstream_setting.cpp @@ -102,6 +102,10 @@ std::string BitstreamSetting::default_path( return interconnect_default_paths_[interconnect_setting_id]; } +std::vector BitstreamSetting::none_fabric() const { + return none_fabric_; +} + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -154,6 +158,22 @@ BitstreamSetting::add_bitstream_interconnect_setting( return interc_setting_id; } +void BitstreamSetting::add_none_fabric(const std::string& name, + const std::string& file) { + VTR_ASSERT(name.size()); + VTR_ASSERT(file.size()); + none_fabric_.push_back(NoneFabricBitstreamSetting(name, file)); +} + +void BitstreamSetting::add_none_fabric_pb(const std::string& pb, + const std::string& type, + const std::string& content) { + VTR_ASSERT(none_fabric_.size()); + VTR_ASSERT(type == "param" || type == "attr"); + VTR_ASSERT(content.size()); + none_fabric_.back().add_pb(pb, type, content); +} + /************************************************************************ * Public Validators ***********************************************************************/ diff --git a/libs/libarchopenfpga/src/bitstream_setting.h b/libs/libarchopenfpga/src/bitstream_setting.h index 7963942a08..1bd6ec525e 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.h +++ b/libs/libarchopenfpga/src/bitstream_setting.h @@ -6,6 +6,7 @@ * which are used by OpenFPGA *******************************************************************/ #include +#include #include "bitstream_setting_fwd.h" #include "vtr_vector.h" @@ -13,6 +14,29 @@ /* namespace openfpga begins */ namespace openfpga { +struct NoneFabricBitstreamPBSetting { + NoneFabricBitstreamPBSetting(const std::string& p = "", + const std::string& t = "", + const std::string& c = "") + : pb(p), type(t), content(c) {} + const std::string pb = ""; + const std::string type = ""; + const std::string content = ""; +}; + +struct NoneFabricBitstreamSetting { + NoneFabricBitstreamSetting(const std::string& n = "", + const std::string& f = "") + : name(n), file(f) {} + void add_pb(const std::string& p, const std::string& t, + const std::string& c) { + pbs.push_back(NoneFabricBitstreamPBSetting(p, t, c)); + } + const std::string name = ""; + const std::string file = ""; + std::vector pbs; +}; + /******************************************************************** * A data structure to describe bitstream settings * @@ -73,6 +97,7 @@ class BitstreamSetting { const BitstreamInterconnectSettingId& interconnect_setting_id) const; std::string default_path( const BitstreamInterconnectSettingId& interconnect_setting_id) const; + std::vector none_fabric() const; public: /* Public Mutators */ BitstreamPbTypeSettingId add_bitstream_pb_type_setting( @@ -92,6 +117,10 @@ class BitstreamSetting { const std::vector& parent_mode_names, const std::string& default_path); + void add_none_fabric(const std::string& name, const std::string& file); + void add_none_fabric_pb(const std::string& pb, const std::string& type, + const std::string& content); + public: /* Public Validators */ bool valid_bitstream_pb_type_setting_id( const BitstreamPbTypeSettingId& pb_type_setting_id) const; @@ -133,6 +162,7 @@ class BitstreamSetting { interconnect_parent_mode_names_; vtr::vector interconnect_default_paths_; + std::vector none_fabric_; }; } // namespace openfpga diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 7447bec2a7..876ae05629 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -76,6 +76,33 @@ static void read_xml_bitstream_interconnect_setting( operating_pb_parser.modes(), default_path_attr); } +/******************************************************************** + * Parse XML description for a none_fabric annotation under a XML node + *******************************************************************/ +static void read_xml_none_fabric_bitstream_setting( + pugi::xml_node& xml_none_fabric, const pugiutil::loc_data& loc_data, + openfpga::BitstreamSetting& bitstream_setting) { + const std::string& name_attr = + get_attribute(xml_none_fabric, "name", loc_data).as_string(); + const std::string& file_attr = + get_attribute(xml_none_fabric, "file", loc_data).as_string(); + /* Add to none fabric */ + bitstream_setting.add_none_fabric(name_attr, file_attr); + for (pugi::xml_node xml_child : xml_none_fabric.children()) { + if (xml_child.name() != std::string("pb")) { + bad_tag(xml_child, loc_data, xml_none_fabric, {"pb"}); + } + const std::string& pb_name_attr = + get_attribute(xml_child, "name", loc_data).as_string(); + const std::string& type_attr = + get_attribute(xml_child, "type", loc_data).as_string(); + const std::string& content_attr = + get_attribute(xml_child, "content", loc_data).as_string(); + /* Add PB to none fabric */ + bitstream_setting.add_none_fabric_pb(pb_name_attr, type_attr, content_attr); + } +} + /******************************************************************** * Parse XML codes about to an object *******************************************************************/ @@ -89,17 +116,22 @@ openfpga::BitstreamSetting read_xml_bitstream_setting( for (pugi::xml_node xml_child : Node.children()) { /* Error out if the XML child has an invalid name! */ if ((xml_child.name() != std::string("pb_type")) && - (xml_child.name() != std::string("interconnect"))) { - bad_tag(xml_child, loc_data, Node, {"pb_type | interconnect"}); + (xml_child.name() != std::string("interconnect")) && + (xml_child.name() != std::string("none_fabric"))) { + bad_tag(xml_child, loc_data, Node, + {"pb_type | interconnect | none_fabric"}); } if (xml_child.name() == std::string("pb_type")) { read_xml_bitstream_pb_type_setting(xml_child, loc_data, bitstream_setting); - } else { - VTR_ASSERT_SAFE(xml_child.name() == std::string("interconnect")); + } 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("none_fabric")); + read_xml_none_fabric_bitstream_setting(xml_child, loc_data, + bitstream_setting); } } diff --git a/openfpga/src/base/openfpga_bitstream_template.h b/openfpga/src/base/openfpga_bitstream_template.h index 8821c8392b..c3d0ea3d64 100644 --- a/openfpga/src/base/openfpga_bitstream_template.h +++ b/openfpga/src/base/openfpga_bitstream_template.h @@ -11,6 +11,7 @@ #include "command.h" #include "command_context.h" #include "command_exit_codes.h" +#include "extract_device_none_fabric_bitstream.h" #include "globals.h" #include "openfpga_digest.h" #include "openfpga_naming.h" @@ -59,6 +60,9 @@ int fpga_bitstream_template(T& openfpga_ctx, const Command& cmd, !cmd_context.option_enable(cmd, opt_no_time_stamp)); } + extract_device_none_fabric_bitstream( + g_vpr_ctx, openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); + /* TODO: should identify the error code from internal function execution */ return CMD_EXEC_SUCCESS; } diff --git a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp new file mode 100644 index 0000000000..385f58b337 --- /dev/null +++ b/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp @@ -0,0 +1,255 @@ +/******************************************************************** + * This file includes functions to build bitstream from a mapped + * FPGA fabric. + * We decode the bitstream from configuration of routing multiplexers + * and Look-Up Tables (LUTs) which locate in CLBs and global routing + *architecture + *******************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "extract_device_none_fabric_bitstream.h" +#include "openfpga_pb_parser.h" +#include "pb_type_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Extract data from the targetted PB + * 1. If it is primitive + * a. If it match the targetted PB, try to get data from + * param of attr depends on what being defined in XML + * b. If it is does not match, do nothing + * 2. If it is not primitive, then we loop for the child + *******************************************************************/ +static bool extract_pb_data(std::fstream& fp, const AtomContext& atom_ctx, + const t_pb* op_pb, const t_pb_type* target_pb_type, + const NoneFabricBitstreamPBSetting& setting) { + t_pb_graph_node* pb_graph_node = op_pb->pb_graph_node; + t_pb_type* pb_type = pb_graph_node->pb_type; + bool found_pb = false; + if (true == is_primitive_pb_type(pb_type)) { + if (target_pb_type == pb_type) { + AtomBlockId atom_blk = atom_ctx.nlist.find_block(op_pb->name); + VTR_ASSERT(atom_blk); + if (setting.type == "param") { + for (const auto& param_search : atom_ctx.nlist.block_params(atom_blk)) { + std::string param = param_search.first; + std::string content = param_search.second; + if (setting.content == param) { + fp << ",\n \"data\" : \"" << content.c_str() << "\""; + break; + } + } + } else { + VTR_ASSERT(setting.type == "attr"); + for (const auto& attr_search : atom_ctx.nlist.block_attrs(atom_blk)) { + std::string attr = attr_search.first; + std::string content = attr_search.second; + if (setting.content == attr) { + fp << ",\n \"data\" : \"" << content.c_str() << "\""; + break; + } + } + } + found_pb = true; + } + } else { + t_mode* mapped_mode = &(pb_graph_node->pb_type->modes[op_pb->mode]); + for (int ipb = 0; ipb < mapped_mode->num_pb_type_children && !found_pb; + ++ipb) { + /* Each child may exist multiple times in the hierarchy*/ + for (int jpb = 0; + jpb < mapped_mode->pb_type_children[ipb].num_pb && !found_pb; + ++jpb) { + if ((nullptr != op_pb->child_pbs[ipb]) && + (nullptr != op_pb->child_pbs[ipb][jpb].name)) { + found_pb = + extract_pb_data(fp, atom_ctx, &(op_pb->child_pbs[ipb][jpb]), + target_pb_type, setting); + } + } + } + } + return found_pb; +} + +/******************************************************************** + * Extract data from the targetted PB (from that particular grid) + *******************************************************************/ +static void extract_grid_none_fabric_bitstream( + std::fstream& fp, const VprContext& vpr_ctx, + const OpenfpgaContext& openfpga_ctx, const ClusterBlockId& cluster_block_id, + const t_pb_type* target_pb_type, const NoneFabricBitstreamPBSetting setting) { + const ClusteringContext& clustering_ctx = vpr_ctx.clustering(); + const AtomContext& atom_ctx = vpr_ctx.atom(); + + if (ClusterBlockId::INVALID() != cluster_block_id) { + const t_pb* op_pb = clustering_ctx.clb_nlist.block_pb(cluster_block_id); + extract_pb_data(fp, atom_ctx, op_pb, target_pb_type, setting); + } else { + // Grid is valid, but this resource is not being used + } +} + +/******************************************************************** + * Extract data from the targetted PB (from the device) + *******************************************************************/ +static void extract_device_none_fabric_pb_bitstream( + std::fstream& fp, const NoneFabricBitstreamPBSetting setting, + const std::string& target_parent_pb_name, const t_pb_type* target_pb_type, + const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx) { + const DeviceContext& device_ctx = vpr_ctx.device(); + const PlacementContext& placement_ctx = vpr_ctx.placement(); + const DeviceGrid& grids = device_ctx.grid; + const size_t& layer = 0; + + // Loop logic block one by one + fp << ",\n \"grid\" : ["; + size_t grid_count = 0; + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + t_physical_tile_loc phy_tile_loc(ix, iy, layer); + t_physical_tile_type_ptr grid_type = + grids.get_physical_type(phy_tile_loc); + // Bypass EMPTY grid + if (true == is_empty_type(grid_type)) { + continue; + } + + // Skip width > 1 or height > 1 tiles (mostly heterogeneous blocks) + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { + continue; + } + + // Skip if this grid is not what we are looking for + if (target_parent_pb_name != std::string(grid_type->name)) { + continue; + } + + // Get the mapped blocks to this grid + for (int isubtile = 0; isubtile < grid_type->capacity; ++isubtile) { + ClusterBlockId cluster_blk_id = + placement_ctx.grid_blocks.block_at_location( + {(int)ix, (int)iy, (int)isubtile, (int)layer}); + if (grid_count) { + fp << ","; + } + fp << "\n"; + fp << " {\n"; + fp << " \"x\" : " << (uint32_t)(ix) << ",\n"; + fp << " \"y\" : " << (uint32_t)(iy); + extract_grid_none_fabric_bitstream( + fp, vpr_ctx, openfpga_ctx, cluster_blk_id, target_pb_type, setting); + fp << "\n }"; + grid_count++; + } + } + } + fp << "\n ]"; +} + +/******************************************************************** + * Search the PB type based on the given name defined in XML + *******************************************************************/ +static t_pb_type* find_pb_type(const DeviceContext& device_ctx, + const std::string& parent_pb, + const std::string& pb) { + t_pb_type* pb_type = nullptr; + openfpga::PbParser pb_parser(pb); + std::vector names = pb_parser.parents(); + names.push_back(pb_parser.leaf()); + for (const t_logical_block_type& lb_type : device_ctx.logical_block_types) { + /* Bypass nullptr for pb_type head */ + if (nullptr == lb_type.pb_type) { + continue; + } + + /* Check the name of the top-level pb_type, if it does not match, we can + * bypass */ + if (parent_pb != std::string(lb_type.pb_type->name)) { + continue; + } + + /* Match the name in the top-level, we go further to search the pb_type in + * the graph */ + pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, names, + pb_parser.modes()); + if (nullptr == pb_type) { + continue; + } + break; + } + return pb_type; +} + +/******************************************************************** + * A top-level function to extract data based on none-fabric bitstream setting + *******************************************************************/ +void extract_device_none_fabric_bitstream(const VprContext& vpr_ctx, + const OpenfpgaContext& openfpga_ctx, + const bool& verbose) { + std::string timer_message = + std::string("\nBuild none-fabric bitstream for implementation '") + + vpr_ctx.atom().nlist.netlist_name() + std::string("'\n"); + vtr::ScopedStartFinishTimer timer(timer_message); + const openfpga::BitstreamSetting& bitstream_setting = + openfpga_ctx.bitstream_setting(); + std::vector none_fabric_setting = + bitstream_setting.none_fabric(); + + // Only proceed if it is defined in bitstream_setting.xml + if (none_fabric_setting.size()) { + // Go through each none_fabric settting + for (auto setting : none_fabric_setting) { + std::fstream fp; + fp.open(setting.file.c_str(), std::fstream::out); + fp << "{\n"; + fp << " \"" << setting.name.c_str() << "\" : [\n"; + int pb_count = 0; + // Extract each needed PB data + for (auto pb_setting : setting.pbs) { + std::string pb_type = setting.name + pb_setting.pb; + t_pb_type* target_pb_type = + find_pb_type(vpr_ctx.device(), setting.name, pb_type); + if (pb_count) { + fp << ",\n"; + } + fp << " {\n"; + fp << " \"pb\" : \"" << pb_type.c_str() << "\",\n"; + if (target_pb_type == nullptr) { + fp << " \"is_primitive_pb_type\" : \"invalid\"\n"; + } else { + if (is_primitive_pb_type(target_pb_type)) { + fp << " \"is_primitive_pb_type\" : \"true\",\n"; + } else { + fp << " \"is_primitive_pb_type\" : \"false\",\n"; + } + } + fp << " \"type\" : \"" << pb_setting.type.c_str() << "\",\n"; + fp << " \"content\" : \"" << pb_setting.content.c_str() << "\""; + if (target_pb_type != nullptr && is_primitive_pb_type(target_pb_type)) { + extract_device_none_fabric_pb_bitstream(fp, pb_setting, setting.name, + target_pb_type, vpr_ctx, + openfpga_ctx); + } + fp << "\n }"; + pb_count++; + } + if (pb_count) { + fp << "\n"; + } + fp << " ]\n"; + fp << "}\n"; + } + } + VTR_LOGV(verbose, "Done\n"); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.h b/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.h new file mode 100644 index 0000000000..2a83bc63ff --- /dev/null +++ b/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.h @@ -0,0 +1,25 @@ +#ifndef EXTRACT_DEVICE_NONE_FABRIC_BITSTREAM_H +#define EXTRACT_DEVICE_NONE_FABRIC_BITSTREAM_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "openfpga_context.h" +#include "vpr_context.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void extract_device_none_fabric_bitstream(const VprContext& vpr_ctx, + const OpenfpgaContext& openfpga_ctx, + const bool& verbose); + +} /* end namespace openfpga */ + +#endif From 1e5e15e2813fa07ae358b5a712a269b8d7be912e Mon Sep 17 00:00:00 2001 From: chungshien Date: Tue, 13 Feb 2024 22:30:21 -0800 Subject: [PATCH 02/19] Add docs and support special __layout__ case --- .../manual/file_formats/bitstream_setting.rst | 46 +++++++++- .../libarchopenfpga/src/bitstream_setting.cpp | 12 ++- libs/libarchopenfpga/src/bitstream_setting.h | 3 +- .../src/read_xml_bitstream_setting.cpp | 7 +- .../extract_device_none_fabric_bitstream.cpp | 90 ++++++++++++------- 5 files changed, 117 insertions(+), 41 deletions(-) diff --git a/docs/source/manual/file_formats/bitstream_setting.rst b/docs/source/manual/file_formats/bitstream_setting.rst index 764bf0c87d..894f5b93db 100644 --- a/docs/source/manual/file_formats/bitstream_setting.rst +++ b/docs/source/manual/file_formats/bitstream_setting.rst @@ -13,6 +13,9 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab + + + pb_type-related Settings @@ -39,7 +42,6 @@ The following syntax are applicable to the XML definition tagged by ``pb_type`` .. option:: content="" The content of the ``pb_type`` bitstream, which could be a keyword in a ``.eblif`` file. For example, ``content=".attr LUT"`` means that the bitstream will be extracted from the ``.attr LUT`` line which is defined under the ``.blif model`` (that is defined under the ``pb_type`` in VPR architecture file). - .. option:: is_mode_select_bitstream="" @@ -71,3 +73,45 @@ 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. + +none_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 + +The following syntax are applicable to the XML definition tagged by ``none-fabric`` in bitstream setting files. + +.. option:: name="" + + The ``pb_type`` top level name that the data to be extracted. For example, + + .. code-block:: xml + + name="bram" + +.. option:: file="" + + The filepath the data is saved to. For example, + + .. code-block:: xml + + file="bram.json" + +.. option:: ``pb`` child element name="" + + Together with ``pb_type`` top level name, that is the source of the ``pb_type`` bitstream + + The final ``pb_type`` name is "" + "" + + For example, + + .. code-block:: xml + + + + + The final ``pb_type`` name is "bram.bram_lr[mem_36K_tdp].mem_36K" + +.. option:: ``pb`` child element content="" + + 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``. diff --git a/libs/libarchopenfpga/src/bitstream_setting.cpp b/libs/libarchopenfpga/src/bitstream_setting.cpp index 7186864b2b..29dd029fac 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/bitstream_setting.cpp @@ -166,12 +166,16 @@ void BitstreamSetting::add_none_fabric(const std::string& name, } void BitstreamSetting::add_none_fabric_pb(const std::string& pb, - const std::string& type, const std::string& content) { VTR_ASSERT(none_fabric_.size()); - VTR_ASSERT(type == "param" || type == "attr"); - VTR_ASSERT(content.size()); - none_fabric_.back().add_pb(pb, type, content); + VTR_ASSERT(content.find(".param ") == 0 || content.find(".attr ") == 0); + if (content.find(".param ") == 0) { + VTR_ASSERT(content.size() > 7); + none_fabric_.back().add_pb(pb, "param", content.substr(7)); + } else { + VTR_ASSERT(content.size() > 6); + none_fabric_.back().add_pb(pb, "attr", content.substr(6)); + } } /************************************************************************ diff --git a/libs/libarchopenfpga/src/bitstream_setting.h b/libs/libarchopenfpga/src/bitstream_setting.h index 1bd6ec525e..cc6969aad2 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.h +++ b/libs/libarchopenfpga/src/bitstream_setting.h @@ -118,8 +118,7 @@ class BitstreamSetting { const std::string& default_path); void add_none_fabric(const std::string& name, const std::string& file); - void add_none_fabric_pb(const std::string& pb, const std::string& type, - const std::string& content); + void add_none_fabric_pb(const std::string& pb, const std::string& content); public: /* Public Validators */ bool valid_bitstream_pb_type_setting_id( diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 876ae05629..a18baee12c 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -77,7 +77,8 @@ static void read_xml_bitstream_interconnect_setting( } /******************************************************************** - * Parse XML description for a none_fabric annotation under a XML node + * Parse XML description for a none_fabric annotation under a XML + *node *******************************************************************/ static void read_xml_none_fabric_bitstream_setting( pugi::xml_node& xml_none_fabric, const pugiutil::loc_data& loc_data, @@ -94,12 +95,10 @@ static void read_xml_none_fabric_bitstream_setting( } const std::string& pb_name_attr = get_attribute(xml_child, "name", loc_data).as_string(); - const std::string& type_attr = - get_attribute(xml_child, "type", loc_data).as_string(); const std::string& content_attr = get_attribute(xml_child, "content", loc_data).as_string(); /* Add PB to none fabric */ - bitstream_setting.add_none_fabric_pb(pb_name_attr, type_attr, content_attr); + bitstream_setting.add_none_fabric_pb(pb_name_attr, content_attr); } } diff --git a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp index 385f58b337..73e1910ba8 100644 --- a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp @@ -19,6 +19,8 @@ /* begin namespace openfpga */ namespace openfpga { +#define PRINT_LAYOUT_NAME "__layout__" + /******************************************************************** * Extract data from the targetted PB * 1. If it is primitive @@ -110,7 +112,9 @@ static void extract_device_none_fabric_pb_bitstream( const size_t& layer = 0; // Loop logic block one by one - fp << ",\n \"grid\" : ["; + if (target_parent_pb_name != PRINT_LAYOUT_NAME) { + fp << ",\n \"grid\" : ["; + } size_t grid_count = 0; for (size_t ix = 1; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { @@ -128,6 +132,20 @@ static void extract_device_none_fabric_pb_bitstream( continue; } + // Skip if this grid is not what we are looking for + if (target_parent_pb_name == PRINT_LAYOUT_NAME) { + if (grid_count) { + fp << ",\n"; + } + fp << " {\n"; + fp << " \"x\" : " << (uint32_t)(ix) << ",\n"; + fp << " \"y\" : " << (uint32_t)(iy) << ",\n"; + fp << " \"name\" : \"" << grid_type->name << "\"\n"; + fp << " }"; + grid_count++; + continue; + } + // Skip if this grid is not what we are looking for if (target_parent_pb_name != std::string(grid_type->name)) { continue; @@ -152,7 +170,11 @@ static void extract_device_none_fabric_pb_bitstream( } } } - fp << "\n ]"; + if (target_parent_pb_name == PRINT_LAYOUT_NAME) { + fp << "\n"; + } else { + fp << "\n ]"; + } } /******************************************************************** @@ -212,41 +234,49 @@ void extract_device_none_fabric_bitstream(const VprContext& vpr_ctx, fp.open(setting.file.c_str(), std::fstream::out); fp << "{\n"; fp << " \"" << setting.name.c_str() << "\" : [\n"; - int pb_count = 0; - // Extract each needed PB data - for (auto pb_setting : setting.pbs) { - std::string pb_type = setting.name + pb_setting.pb; - t_pb_type* target_pb_type = - find_pb_type(vpr_ctx.device(), setting.name, pb_type); - if (pb_count) { - fp << ",\n"; - } - fp << " {\n"; - fp << " \"pb\" : \"" << pb_type.c_str() << "\",\n"; - if (target_pb_type == nullptr) { - fp << " \"is_primitive_pb_type\" : \"invalid\"\n"; - } else { - if (is_primitive_pb_type(target_pb_type)) { - fp << " \"is_primitive_pb_type\" : \"true\",\n"; + if (setting.name == PRINT_LAYOUT_NAME) { + extract_device_none_fabric_pb_bitstream( + fp, NoneFabricBitstreamPBSetting{}, setting.name, nullptr, vpr_ctx, + openfpga_ctx); + } else { + int pb_count = 0; + // Extract each needed PB data + for (auto pb_setting : setting.pbs) { + std::string pb_type = setting.name + pb_setting.pb; + t_pb_type* target_pb_type = + find_pb_type(vpr_ctx.device(), setting.name, pb_type); + if (pb_count) { + fp << ",\n"; + } + fp << " {\n"; + fp << " \"pb\" : \"" << pb_type.c_str() << "\",\n"; + if (target_pb_type == nullptr) { + fp << " \"is_primitive_pb_type\" : \"invalid\",\n"; } else { - fp << " \"is_primitive_pb_type\" : \"false\",\n"; + if (is_primitive_pb_type(target_pb_type)) { + fp << " \"is_primitive_pb_type\" : \"true\",\n"; + } else { + fp << " \"is_primitive_pb_type\" : \"false\",\n"; + } + } + fp << " \"type\" : \"" << pb_setting.type.c_str() << "\",\n"; + fp << " \"content\" : \"" << pb_setting.content.c_str() << "\""; + if (target_pb_type != nullptr && + is_primitive_pb_type(target_pb_type)) { + extract_device_none_fabric_pb_bitstream( + fp, pb_setting, setting.name, target_pb_type, vpr_ctx, + openfpga_ctx); } + fp << "\n }"; + pb_count++; } - fp << " \"type\" : \"" << pb_setting.type.c_str() << "\",\n"; - fp << " \"content\" : \"" << pb_setting.content.c_str() << "\""; - if (target_pb_type != nullptr && is_primitive_pb_type(target_pb_type)) { - extract_device_none_fabric_pb_bitstream(fp, pb_setting, setting.name, - target_pb_type, vpr_ctx, - openfpga_ctx); + if (pb_count) { + fp << "\n"; } - fp << "\n }"; - pb_count++; - } - if (pb_count) { - fp << "\n"; } fp << " ]\n"; fp << "}\n"; + fp.close(); } } VTR_LOGV(verbose, "Done\n"); From efe75c21d674c42f9072c7ad96d6451f4859593d Mon Sep 17 00:00:00 2001 From: chungshien Date: Wed, 14 Feb 2024 00:56:50 -0800 Subject: [PATCH 03/19] Add test --- .../fpga_bitstream_reg_test.sh | 3 ++ .../config/bitstream_annotation.xml | 7 +++ .../extract_dsp_mode_bit/config/task.conf | 44 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/bitstream_annotation.xml create mode 100644 openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/task.conf diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index 184eceee92..8d46be27f1 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -52,3 +52,6 @@ run-task fpga_bitstream/filter_value0 $@ run-task fpga_bitstream/filter_value1 $@ run-task fpga_bitstream/path_only $@ run-task fpga_bitstream/value_only $@ + +echo -e "Testing extracting mode bits for DSP blocks when generating bitstream"; +run-task fpga_bitstream/extract_dsp_mode_bit $@ diff --git a/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/bitstream_annotation.xml b/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/bitstream_annotation.xml new file mode 100644 index 0000000000..33807b0433 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/bitstream_annotation.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/task.conf new file mode 100644 index 0000000000..9086785718 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/bitstream_setting_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_frac_dsp16_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_bitstream_setting_file=${PATH:TASK_DIR}/config/bitstream_annotation.xml +# VPR parameter +openfpga_vpr_circuit_format=eblif + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_frac_dsp16_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mult/mult8/mult8.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_N4_tileable_frac_dsp16_40nm_cell_sim.v +bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_N4_tileable_frac_dsp16_40nm_dsp_map.v +bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=8 -D DSP_B_MAXWIDTH=8 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_8x8 +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dsp_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dsp_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys +bench0_top = mult8 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= From 4f6cde54e5b40efa9126128d935ce2745d4dfc92 Mon Sep 17 00:00:00 2001 From: chungshien Date: Wed, 14 Feb 2024 01:46:04 -0800 Subject: [PATCH 04/19] Fix warning --- .../extract_device_none_fabric_bitstream.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp index 73e1910ba8..d208a0b2b9 100644 --- a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp @@ -86,8 +86,8 @@ static bool extract_pb_data(std::fstream& fp, const AtomContext& atom_ctx, *******************************************************************/ static void extract_grid_none_fabric_bitstream( std::fstream& fp, const VprContext& vpr_ctx, - const OpenfpgaContext& openfpga_ctx, const ClusterBlockId& cluster_block_id, - const t_pb_type* target_pb_type, const NoneFabricBitstreamPBSetting setting) { + const ClusterBlockId& cluster_block_id, const t_pb_type* target_pb_type, + const NoneFabricBitstreamPBSetting setting) { const ClusteringContext& clustering_ctx = vpr_ctx.clustering(); const AtomContext& atom_ctx = vpr_ctx.atom(); @@ -105,7 +105,7 @@ static void extract_grid_none_fabric_bitstream( static void extract_device_none_fabric_pb_bitstream( std::fstream& fp, const NoneFabricBitstreamPBSetting setting, const std::string& target_parent_pb_name, const t_pb_type* target_pb_type, - const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx) { + const VprContext& vpr_ctx) { const DeviceContext& device_ctx = vpr_ctx.device(); const PlacementContext& placement_ctx = vpr_ctx.placement(); const DeviceGrid& grids = device_ctx.grid; @@ -163,8 +163,8 @@ static void extract_device_none_fabric_pb_bitstream( fp << " {\n"; fp << " \"x\" : " << (uint32_t)(ix) << ",\n"; fp << " \"y\" : " << (uint32_t)(iy); - extract_grid_none_fabric_bitstream( - fp, vpr_ctx, openfpga_ctx, cluster_blk_id, target_pb_type, setting); + extract_grid_none_fabric_bitstream(fp, vpr_ctx, cluster_blk_id, + target_pb_type, setting); fp << "\n }"; grid_count++; } @@ -236,8 +236,7 @@ void extract_device_none_fabric_bitstream(const VprContext& vpr_ctx, fp << " \"" << setting.name.c_str() << "\" : [\n"; if (setting.name == PRINT_LAYOUT_NAME) { extract_device_none_fabric_pb_bitstream( - fp, NoneFabricBitstreamPBSetting{}, setting.name, nullptr, vpr_ctx, - openfpga_ctx); + fp, NoneFabricBitstreamPBSetting{}, setting.name, nullptr, vpr_ctx); } else { int pb_count = 0; // Extract each needed PB data @@ -264,8 +263,7 @@ void extract_device_none_fabric_bitstream(const VprContext& vpr_ctx, if (target_pb_type != nullptr && is_primitive_pb_type(target_pb_type)) { extract_device_none_fabric_pb_bitstream( - fp, pb_setting, setting.name, target_pb_type, vpr_ctx, - openfpga_ctx); + fp, pb_setting, setting.name, target_pb_type, vpr_ctx); } fp << "\n }"; pb_count++; From 49cdb4e9c80d08de144269ad9aaae0d9c5660aea Mon Sep 17 00:00:00 2001 From: chungshien Date: Tue, 20 Feb 2024 21:05:13 -0800 Subject: [PATCH 05/19] Change none-fabric to non-fabric --- .../manual/file_formats/bitstream_setting.rst | 12 ++--- .../libarchopenfpga/src/bitstream_setting.cpp | 20 ++++----- libs/libarchopenfpga/src/bitstream_setting.h | 26 +++++------ .../src/read_xml_bitstream_setting.cpp | 32 +++++++------- .../src/base/openfpga_bitstream_template.h | 4 +- ...> extract_device_non_fabric_bitstream.cpp} | 44 +++++++++---------- ... => extract_device_non_fabric_bitstream.h} | 10 ++--- .../config/bitstream_annotation.xml | 4 +- 8 files changed, 76 insertions(+), 76 deletions(-) rename openfpga/src/fpga_bitstream/{extract_device_none_fabric_bitstream.cpp => extract_device_non_fabric_bitstream.cpp} (87%) rename openfpga/src/fpga_bitstream/{extract_device_none_fabric_bitstream.h => extract_device_non_fabric_bitstream.h} (63%) diff --git a/docs/source/manual/file_formats/bitstream_setting.rst b/docs/source/manual/file_formats/bitstream_setting.rst index 894f5b93db..eb2af5ddfa 100644 --- a/docs/source/manual/file_formats/bitstream_setting.rst +++ b/docs/source/manual/file_formats/bitstream_setting.rst @@ -13,9 +13,9 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab - + - + pb_type-related Settings @@ -74,12 +74,12 @@ 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. -none_fabric-related Settings +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 -The following syntax are applicable to the XML definition tagged by ``none-fabric`` in bitstream setting files. +The following syntax are applicable to the XML definition tagged by ``non_fabric`` in bitstream setting files. .. option:: name="" @@ -106,9 +106,9 @@ The following syntax are applicable to the XML definition tagged by ``none-fabri For example, .. code-block:: xml - + - + The final ``pb_type`` name is "bram.bram_lr[mem_36K_tdp].mem_36K" diff --git a/libs/libarchopenfpga/src/bitstream_setting.cpp b/libs/libarchopenfpga/src/bitstream_setting.cpp index 29dd029fac..7d763f9d2b 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/bitstream_setting.cpp @@ -102,8 +102,8 @@ std::string BitstreamSetting::default_path( return interconnect_default_paths_[interconnect_setting_id]; } -std::vector BitstreamSetting::none_fabric() const { - return none_fabric_; +std::vector BitstreamSetting::non_fabric() const { + return non_fabric_; } /************************************************************************ @@ -158,23 +158,23 @@ BitstreamSetting::add_bitstream_interconnect_setting( return interc_setting_id; } -void BitstreamSetting::add_none_fabric(const std::string& name, - const std::string& file) { +void BitstreamSetting::add_non_fabric(const std::string& name, + const std::string& file) { VTR_ASSERT(name.size()); VTR_ASSERT(file.size()); - none_fabric_.push_back(NoneFabricBitstreamSetting(name, file)); + non_fabric_.push_back(NonFabricBitstreamSetting(name, file)); } -void BitstreamSetting::add_none_fabric_pb(const std::string& pb, - const std::string& content) { - VTR_ASSERT(none_fabric_.size()); +void BitstreamSetting::add_non_fabric_pb(const std::string& pb, + const std::string& content) { + VTR_ASSERT(non_fabric_.size()); VTR_ASSERT(content.find(".param ") == 0 || content.find(".attr ") == 0); if (content.find(".param ") == 0) { VTR_ASSERT(content.size() > 7); - none_fabric_.back().add_pb(pb, "param", content.substr(7)); + non_fabric_.back().add_pb(pb, "param", content.substr(7)); } else { VTR_ASSERT(content.size() > 6); - none_fabric_.back().add_pb(pb, "attr", content.substr(6)); + non_fabric_.back().add_pb(pb, "attr", content.substr(6)); } } diff --git a/libs/libarchopenfpga/src/bitstream_setting.h b/libs/libarchopenfpga/src/bitstream_setting.h index cc6969aad2..1b12c8de32 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.h +++ b/libs/libarchopenfpga/src/bitstream_setting.h @@ -14,27 +14,27 @@ /* namespace openfpga begins */ namespace openfpga { -struct NoneFabricBitstreamPBSetting { - NoneFabricBitstreamPBSetting(const std::string& p = "", - const std::string& t = "", - const std::string& c = "") +struct NonFabricBitstreamPBSetting { + NonFabricBitstreamPBSetting(const std::string& p = "", + const std::string& t = "", + const std::string& c = "") : pb(p), type(t), content(c) {} const std::string pb = ""; const std::string type = ""; const std::string content = ""; }; -struct NoneFabricBitstreamSetting { - NoneFabricBitstreamSetting(const std::string& n = "", - const std::string& f = "") +struct NonFabricBitstreamSetting { + NonFabricBitstreamSetting(const std::string& n = "", + const std::string& f = "") : name(n), file(f) {} void add_pb(const std::string& p, const std::string& t, const std::string& c) { - pbs.push_back(NoneFabricBitstreamPBSetting(p, t, c)); + pbs.push_back(NonFabricBitstreamPBSetting(p, t, c)); } const std::string name = ""; const std::string file = ""; - std::vector pbs; + std::vector pbs; }; /******************************************************************** @@ -97,7 +97,7 @@ class BitstreamSetting { const BitstreamInterconnectSettingId& interconnect_setting_id) const; std::string default_path( const BitstreamInterconnectSettingId& interconnect_setting_id) const; - std::vector none_fabric() const; + std::vector non_fabric() const; public: /* Public Mutators */ BitstreamPbTypeSettingId add_bitstream_pb_type_setting( @@ -117,8 +117,8 @@ class BitstreamSetting { const std::vector& parent_mode_names, const std::string& default_path); - void add_none_fabric(const std::string& name, const std::string& file); - void add_none_fabric_pb(const std::string& pb, const std::string& content); + 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); public: /* Public Validators */ bool valid_bitstream_pb_type_setting_id( @@ -161,7 +161,7 @@ class BitstreamSetting { interconnect_parent_mode_names_; vtr::vector interconnect_default_paths_; - std::vector none_fabric_; + std::vector non_fabric_; }; } // namespace openfpga diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index a18baee12c..7f6bd12372 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -77,28 +77,28 @@ static void read_xml_bitstream_interconnect_setting( } /******************************************************************** - * Parse XML description for a none_fabric annotation under a XML + * Parse XML description for a non_fabric annotation under a XML *node *******************************************************************/ -static void read_xml_none_fabric_bitstream_setting( - pugi::xml_node& xml_none_fabric, const pugiutil::loc_data& loc_data, +static void read_xml_non_fabric_bitstream_setting( + pugi::xml_node& xml_non_fabric, const pugiutil::loc_data& loc_data, openfpga::BitstreamSetting& bitstream_setting) { const std::string& name_attr = - get_attribute(xml_none_fabric, "name", loc_data).as_string(); + get_attribute(xml_non_fabric, "name", loc_data).as_string(); const std::string& file_attr = - get_attribute(xml_none_fabric, "file", loc_data).as_string(); - /* Add to none fabric */ - bitstream_setting.add_none_fabric(name_attr, file_attr); - for (pugi::xml_node xml_child : xml_none_fabric.children()) { + get_attribute(xml_non_fabric, "file", loc_data).as_string(); + /* Add to non-fabric */ + bitstream_setting.add_non_fabric(name_attr, file_attr); + for (pugi::xml_node xml_child : xml_non_fabric.children()) { if (xml_child.name() != std::string("pb")) { - bad_tag(xml_child, loc_data, xml_none_fabric, {"pb"}); + bad_tag(xml_child, loc_data, xml_non_fabric, {"pb"}); } const std::string& pb_name_attr = get_attribute(xml_child, "name", loc_data).as_string(); const std::string& content_attr = get_attribute(xml_child, "content", loc_data).as_string(); - /* Add PB to none fabric */ - bitstream_setting.add_none_fabric_pb(pb_name_attr, content_attr); + /* Add PB to non-fabric */ + bitstream_setting.add_non_fabric_pb(pb_name_attr, content_attr); } } @@ -116,9 +116,9 @@ 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("none_fabric"))) { + (xml_child.name() != std::string("non_fabric"))) { bad_tag(xml_child, loc_data, Node, - {"pb_type | interconnect | none_fabric"}); + {"pb_type | interconnect | non_fabric"}); } if (xml_child.name() == std::string("pb_type")) { @@ -128,9 +128,9 @@ openfpga::BitstreamSetting read_xml_bitstream_setting( read_xml_bitstream_interconnect_setting(xml_child, loc_data, bitstream_setting); } else { - VTR_ASSERT_SAFE(xml_child.name() == std::string("none_fabric")); - read_xml_none_fabric_bitstream_setting(xml_child, loc_data, - bitstream_setting); + VTR_ASSERT_SAFE(xml_child.name() == std::string("non_fabric")); + read_xml_non_fabric_bitstream_setting(xml_child, loc_data, + bitstream_setting); } } diff --git a/openfpga/src/base/openfpga_bitstream_template.h b/openfpga/src/base/openfpga_bitstream_template.h index c3d0ea3d64..c132e907f7 100644 --- a/openfpga/src/base/openfpga_bitstream_template.h +++ b/openfpga/src/base/openfpga_bitstream_template.h @@ -11,7 +11,7 @@ #include "command.h" #include "command_context.h" #include "command_exit_codes.h" -#include "extract_device_none_fabric_bitstream.h" +#include "extract_device_non_fabric_bitstream.h" #include "globals.h" #include "openfpga_digest.h" #include "openfpga_naming.h" @@ -60,7 +60,7 @@ int fpga_bitstream_template(T& openfpga_ctx, const Command& cmd, !cmd_context.option_enable(cmd, opt_no_time_stamp)); } - extract_device_none_fabric_bitstream( + extract_device_non_fabric_bitstream( g_vpr_ctx, openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); /* TODO: should identify the error code from internal function execution */ diff --git a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/extract_device_non_fabric_bitstream.cpp similarity index 87% rename from openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp rename to openfpga/src/fpga_bitstream/extract_device_non_fabric_bitstream.cpp index d208a0b2b9..3793c1b3d8 100644 --- a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/extract_device_non_fabric_bitstream.cpp @@ -9,7 +9,7 @@ #include /* Headers from vtrutil library */ -#include "extract_device_none_fabric_bitstream.h" +#include "extract_device_non_fabric_bitstream.h" #include "openfpga_pb_parser.h" #include "pb_type_utils.h" #include "vtr_assert.h" @@ -31,7 +31,7 @@ namespace openfpga { *******************************************************************/ static bool extract_pb_data(std::fstream& fp, const AtomContext& atom_ctx, const t_pb* op_pb, const t_pb_type* target_pb_type, - const NoneFabricBitstreamPBSetting& setting) { + const NonFabricBitstreamPBSetting& setting) { t_pb_graph_node* pb_graph_node = op_pb->pb_graph_node; t_pb_type* pb_type = pb_graph_node->pb_type; bool found_pb = false; @@ -84,10 +84,10 @@ static bool extract_pb_data(std::fstream& fp, const AtomContext& atom_ctx, /******************************************************************** * Extract data from the targetted PB (from that particular grid) *******************************************************************/ -static void extract_grid_none_fabric_bitstream( +static void extract_grid_non_fabric_bitstream( std::fstream& fp, const VprContext& vpr_ctx, const ClusterBlockId& cluster_block_id, const t_pb_type* target_pb_type, - const NoneFabricBitstreamPBSetting setting) { + const NonFabricBitstreamPBSetting setting) { const ClusteringContext& clustering_ctx = vpr_ctx.clustering(); const AtomContext& atom_ctx = vpr_ctx.atom(); @@ -102,8 +102,8 @@ static void extract_grid_none_fabric_bitstream( /******************************************************************** * Extract data from the targetted PB (from the device) *******************************************************************/ -static void extract_device_none_fabric_pb_bitstream( - std::fstream& fp, const NoneFabricBitstreamPBSetting setting, +static void extract_device_non_fabric_pb_bitstream( + std::fstream& fp, const NonFabricBitstreamPBSetting setting, const std::string& target_parent_pb_name, const t_pb_type* target_pb_type, const VprContext& vpr_ctx) { const DeviceContext& device_ctx = vpr_ctx.device(); @@ -163,8 +163,8 @@ static void extract_device_none_fabric_pb_bitstream( fp << " {\n"; fp << " \"x\" : " << (uint32_t)(ix) << ",\n"; fp << " \"y\" : " << (uint32_t)(iy); - extract_grid_none_fabric_bitstream(fp, vpr_ctx, cluster_blk_id, - target_pb_type, setting); + extract_grid_non_fabric_bitstream(fp, vpr_ctx, cluster_blk_id, + target_pb_type, setting); fp << "\n }"; grid_count++; } @@ -212,31 +212,31 @@ static t_pb_type* find_pb_type(const DeviceContext& device_ctx, } /******************************************************************** - * A top-level function to extract data based on none-fabric bitstream setting + * A top-level function to extract data based on non-fabric bitstream setting *******************************************************************/ -void extract_device_none_fabric_bitstream(const VprContext& vpr_ctx, - const OpenfpgaContext& openfpga_ctx, - const bool& verbose) { +void extract_device_non_fabric_bitstream(const VprContext& vpr_ctx, + const OpenfpgaContext& openfpga_ctx, + const bool& verbose) { std::string timer_message = - std::string("\nBuild none-fabric bitstream for implementation '") + + std::string("\nBuild non-fabric bitstream for implementation '") + vpr_ctx.atom().nlist.netlist_name() + std::string("'\n"); vtr::ScopedStartFinishTimer timer(timer_message); const openfpga::BitstreamSetting& bitstream_setting = openfpga_ctx.bitstream_setting(); - std::vector none_fabric_setting = - bitstream_setting.none_fabric(); + std::vector non_fabric_setting = + bitstream_setting.non_fabric(); // Only proceed if it is defined in bitstream_setting.xml - if (none_fabric_setting.size()) { - // Go through each none_fabric settting - for (auto setting : none_fabric_setting) { + if (non_fabric_setting.size()) { + // Go through each non_fabric settting + for (auto setting : non_fabric_setting) { std::fstream fp; fp.open(setting.file.c_str(), std::fstream::out); fp << "{\n"; fp << " \"" << setting.name.c_str() << "\" : [\n"; if (setting.name == PRINT_LAYOUT_NAME) { - extract_device_none_fabric_pb_bitstream( - fp, NoneFabricBitstreamPBSetting{}, setting.name, nullptr, vpr_ctx); + extract_device_non_fabric_pb_bitstream( + fp, NonFabricBitstreamPBSetting{}, setting.name, nullptr, vpr_ctx); } else { int pb_count = 0; // Extract each needed PB data @@ -262,8 +262,8 @@ void extract_device_none_fabric_bitstream(const VprContext& vpr_ctx, fp << " \"content\" : \"" << pb_setting.content.c_str() << "\""; if (target_pb_type != nullptr && is_primitive_pb_type(target_pb_type)) { - extract_device_none_fabric_pb_bitstream( - fp, pb_setting, setting.name, target_pb_type, vpr_ctx); + extract_device_non_fabric_pb_bitstream(fp, pb_setting, setting.name, + target_pb_type, vpr_ctx); } fp << "\n }"; pb_count++; diff --git a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.h b/openfpga/src/fpga_bitstream/extract_device_non_fabric_bitstream.h similarity index 63% rename from openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.h rename to openfpga/src/fpga_bitstream/extract_device_non_fabric_bitstream.h index 2a83bc63ff..658c40b96a 100644 --- a/openfpga/src/fpga_bitstream/extract_device_none_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/extract_device_non_fabric_bitstream.h @@ -1,5 +1,5 @@ -#ifndef EXTRACT_DEVICE_NONE_FABRIC_BITSTREAM_H -#define EXTRACT_DEVICE_NONE_FABRIC_BITSTREAM_H +#ifndef EXTRACT_DEVICE_NON_FABRIC_BITSTREAM_H +#define EXTRACT_DEVICE_NON_FABRIC_BITSTREAM_H /******************************************************************** * Include header files that are required by function declaration @@ -16,9 +16,9 @@ /* begin namespace openfpga */ namespace openfpga { -void extract_device_none_fabric_bitstream(const VprContext& vpr_ctx, - const OpenfpgaContext& openfpga_ctx, - const bool& verbose); +void extract_device_non_fabric_bitstream(const VprContext& vpr_ctx, + const OpenfpgaContext& openfpga_ctx, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/bitstream_annotation.xml b/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/bitstream_annotation.xml index 33807b0433..7c835ad7e3 100644 --- a/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/bitstream_annotation.xml +++ b/openfpga_flow/tasks/fpga_bitstream/extract_dsp_mode_bit/config/bitstream_annotation.xml @@ -1,7 +1,7 @@ - + - + From 2ef362d53dec67ce8ee195c3dc7fca5c85fd7470 Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Thu, 25 Jul 2024 17:40:46 -0700 Subject: [PATCH 06/19] Init support overwriting bitstream --- .../openfpga_bitstream_command_template.h | 6 + .../src/base/openfpga_bitstream_template.h | 6 +- .../fpga_bitstream/build_device_bitstream.cpp | 8 +- .../fpga_bitstream/build_device_bitstream.h | 6 +- .../fpga_bitstream/build_grid_bitstream.cpp | 312 ++++++++++++++++-- .../src/fpga_bitstream/build_grid_bitstream.h | 3 +- ...x_device_example_script_overwrite.openfpga | 74 +++++ .../fpga_bitstream_reg_test.sh | 3 + .../config/overwrite_bitstream.txt | 2 + .../device_4x4_overwrite/config/task.conf | 35 ++ 10 files changed, 421 insertions(+), 34 deletions(-) create mode 100644 openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga create mode 100644 openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/overwrite_bitstream.txt create mode 100644 openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/task.conf diff --git a/openfpga/src/base/openfpga_bitstream_command_template.h b/openfpga/src/base/openfpga_bitstream_command_template.h index f80176514d..a3d40f9f91 100644 --- a/openfpga/src/base/openfpga_bitstream_command_template.h +++ b/openfpga/src/base/openfpga_bitstream_command_template.h @@ -78,6 +78,12 @@ ShellCommandId add_build_arch_bitstream_command_template( shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); + /* Add an option '--overwrite_bitstream_file' */ + CommandOptionId opt_overwrite_file = + shell_cmd.add_option("overwrite_bitstream_file", false, + "file path to read to overwrite bitstream bits"); + shell_cmd.set_option_require_value(opt_overwrite_file, openfpga::OPT_STRING); + /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); diff --git a/openfpga/src/base/openfpga_bitstream_template.h b/openfpga/src/base/openfpga_bitstream_template.h index c132e907f7..19c9a4bc69 100644 --- a/openfpga/src/base/openfpga_bitstream_template.h +++ b/openfpga/src/base/openfpga_bitstream_template.h @@ -38,13 +38,17 @@ int fpga_bitstream_template(T& openfpga_ctx, const Command& cmd, CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_write_file = cmd.option("write_file"); CommandOptionId opt_read_file = cmd.option("read_file"); + CommandOptionId opt_overwrite_bitstream_file = + cmd.option("overwrite_bitstream_file"); if (true == cmd_context.option_enable(cmd, opt_read_file)) { openfpga_ctx.mutable_bitstream_manager() = read_xml_architecture_bitstream( cmd_context.option_value(cmd, opt_read_file).c_str()); } else { openfpga_ctx.mutable_bitstream_manager() = build_device_bitstream( - g_vpr_ctx, openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); + g_vpr_ctx, openfpga_ctx, + cmd_context.option_value(cmd, opt_overwrite_bitstream_file), + cmd_context.option_enable(cmd, opt_verbose)); } if (true == cmd_context.option_enable(cmd, opt_write_file)) { diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 9d7b89789b..7f27cea52f 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -147,9 +147,9 @@ static size_t rec_estimate_device_bitstream_num_bits( * of the FPGA fabric that FPGA-X2P generates! * But it can be used to output a generic bitstream for VPR mapping FPGA *******************************************************************/ -BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, - const OpenfpgaContext& openfpga_ctx, - const bool& verbose) { +BitstreamManager build_device_bitstream( + const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, + const std::string& overwrite_bitstream_file, const bool& verbose) { std::string timer_message = std::string("\nBuild fabric-independent bitstream for implementation '") + vpr_ctx.atom().nlist.netlist_name() + std::string("'\n"); @@ -218,7 +218,7 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_clustering_annotation(), openfpga_ctx.vpr_placement_annotation(), - openfpga_ctx.vpr_bitstream_annotation(), verbose); + openfpga_ctx.vpr_bitstream_annotation(), overwrite_bitstream_file, verbose); VTR_LOGV(verbose, "Done\n"); /* Create bitstream from routing architectures */ diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.h b/openfpga/src/fpga_bitstream/build_device_bitstream.h index 3bddf92115..044b932310 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.h @@ -16,9 +16,9 @@ /* begin namespace openfpga */ namespace openfpga { -BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, - const OpenfpgaContext& openfpga_ctx, - const bool& verbose); +BitstreamManager build_device_bitstream( + const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, + const std::string& overwrite_bitstream_file, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index d8e4f17fbf..44e33e8598 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -3,6 +3,7 @@ * for grids (CLBs, heterogenerous blocks, I/Os, etc.) *******************************************************************/ #include +#include #include /* Headers from vtrutil library */ @@ -29,6 +30,242 @@ /* begin namespace openfpga */ namespace openfpga { +struct OVERWRITE_BITS { + OVERWRITE_BITS(bool i, int s, int e, uint64_t b) + : incr(i), start(s), end(e), bits(b) {} + bool incr = true; + int start = -1; + int end = -1; + uint64_t bits = 0; +}; + +std::string M_TOP_NAME = ""; +std::string M_BLOCK_GRID_NAME = ""; +std::map>*> + M_OVERWRITE_GRID_BITS; +std::map>* M_OVERWRITE_BITS = nullptr; + +/******************************************************************** + * Track the fabric top name + *******************************************************************/ +static void track_fabric_top_name(const std::string& top) { + VTR_ASSERT(top.size()); + M_TOP_NAME = top; +} + +/******************************************************************** + * Track the fabric grid name + *******************************************************************/ +static void track_physical_block_grid(const std::string& block) { + VTR_ASSERT(M_TOP_NAME.size()); + VTR_ASSERT(block.size()); + M_BLOCK_GRID_NAME = M_TOP_NAME + std::string(".") + block; + if (M_OVERWRITE_GRID_BITS.find(M_BLOCK_GRID_NAME) != + M_OVERWRITE_GRID_BITS.end()) { + M_OVERWRITE_BITS = M_OVERWRITE_GRID_BITS[M_BLOCK_GRID_NAME]; + } else { + M_OVERWRITE_BITS = nullptr; + } +} + +/******************************************************************** + * Trim whitespace + *******************************************************************/ +static void trim_white_space(std::string& line) { + const auto begin = line.find_first_not_of(" \t\r\n"); + if (begin != std::string::npos) { + const auto end = line.find_last_not_of(" \t\r\n"); + const auto count = end - begin + 1; + line = line.substr(begin, count); + } +} + +/******************************************************************** + * Split the line by delimiter + *******************************************************************/ +static std::vector split_line_by( + std::string line, const std::string& delimiter = " \t") { + std::vector results; + size_t index = line.find_first_of(delimiter); + trim_white_space(line); + while (index != std::string::npos) { + std::string result = line.substr(0, index); + trim_white_space(result); + results.push_back(result); + line = line.substr(index + 1); + trim_white_space(line); + index = line.find_first_of(delimiter); + } + if (line.size()) { + results.push_back(line); + } + return results; +} + +/******************************************************************** + * Check if the string is all number + *******************************************************************/ +static bool is_number(const std::string& s) { + std::string::const_iterator it = s.begin(); + while (it != s.end() && std::isdigit(*it)) ++it; + return !s.empty() && it == s.end(); +} + +/******************************************************************** + * Convert string to uint64_t + *******************************************************************/ +static uint64_t get_number(const std::string& s) { + uint64_t value = 0; + std::istringstream iss(s); + iss >> value; + return value; +} + +/******************************************************************** + * Cleanup + *******************************************************************/ +static void cleanup_overwrite() { + for (auto& iter : M_OVERWRITE_GRID_BITS) { + delete iter.second; + } + M_OVERWRITE_GRID_BITS.clear(); + M_OVERWRITE_BITS = nullptr; +} + +/******************************************************************** + * Read the overwrite file + *******************************************************************/ +static void read_overwrite_file(const std::string& filepath) { + cleanup_overwrite(); + if (filepath.size()) { + std::ifstream file(filepath.c_str()); + if (file.is_open()) { + if (file.good()) { + std::string line = ""; + while (std::getline(file, line)) { + trim_white_space(line); + if (line.size() && line[0] != '#') { + std::vector words = split_line_by(line); + if (words.size() >= 3 && words[0].size() > 0 && + words[1].size() > 0) { + // Prepare the pointer to fillup path and bits (speedup stuff) + M_OVERWRITE_BITS = nullptr; + if (M_OVERWRITE_GRID_BITS.find(words[0]) != + M_OVERWRITE_GRID_BITS.end()) { + M_OVERWRITE_BITS = M_OVERWRITE_GRID_BITS.at(words[0]); + } + std::string path = std::string(".") + words[1]; + for (size_t i = 2; i < words.size(); i++) { + std::vector values = split_line_by(words[i], "="); + bool incr = true; + int start = -1; + int end = -1; + uint64_t value = 0; + if (values.size() == 1) { + if (is_number(values[0])) { + value = get_number(values[0]); + } else { + // Bad + continue; + } + } else if (values.size() == 2) { + if (values[0].size() >= 3 && values[0][0] == '[' && + values[0][values[0].size() - 1] == ']') { + line = values[0].substr(1, values[0].size() - 2); + trim_white_space(line); + std::vector range = split_line_by(line, ":"); + if (range.size() == 1 && is_number(range[0])) { + start = get_number(range[0]); + end = start; + } else if (range.size() == 2 && is_number(range[0]) && + is_number(range[1])) { + end = (int)(get_number(range[0])); + start = (int)(get_number(range[1])); + incr = end >= start; + } else { + // Bad + continue; + } + if (is_number(values[1])) { + value = get_number(values[1]); + } else { + // Bad + continue; + } + } else { + // Bad + continue; + } + } else { + // Bad + continue; + } + if ((start == -1 && end == -1) || (start >= 0 && end >= 0)) { + if (M_OVERWRITE_BITS == nullptr) { + M_OVERWRITE_BITS = + new std::map>; + M_OVERWRITE_GRID_BITS[words[0]] = M_OVERWRITE_BITS; + } + if (M_OVERWRITE_BITS->find(path) == M_OVERWRITE_BITS->end()) { + (*M_OVERWRITE_BITS)[path] = {}; + } + M_OVERWRITE_BITS->at(path).push_back( + OVERWRITE_BITS(incr, start, end, value)); + } + } + } + } + } + } + file.close(); + } + } + M_OVERWRITE_BITS = nullptr; +} + +/******************************************************************** + * Overwrite the bits + *******************************************************************/ +static void overwrite_bits(const std::string& path, std::vector& bits) { + VTR_ASSERT(M_OVERWRITE_BITS != nullptr); + if (M_OVERWRITE_BITS->find(path) != M_OVERWRITE_BITS->end()) { + for (OVERWRITE_BITS& obits : M_OVERWRITE_BITS->at(path)) { + if (obits.start == -1 && obits.end == -1) { + for (int i = 0; i < int(bits.size()); i++) { + if (obits.bits & (1 << i)) { + bits[i] = true; + } else { + bits[i] = false; + } + } + } else { + int i = 0; + int start = obits.start; + while (true) { + if (start >= 0 && start < int(bits.size())) { + if (obits.bits & (1 << i)) { + bits[start] = true; + } else { + bits[start] = false; + } + } else { + break; + } + if (start == obits.end) { + break; + } + i++; + if (obits.incr) { + start++; + } else { + start--; + } + } + } + } + } +} + /******************************************************************** * Decode mode bits "01..." to a bitstream vector *******************************************************************/ @@ -55,7 +292,7 @@ static void build_primitive_bitstream( const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& device_annotation, const PhysicalPb& physical_pb, const PhysicalPbId& primitive_pb_id, t_pb_type* primitive_pb_type, - const bool& verbose) { + std::string config_instance_path, const bool& verbose) { /* Ensure a valid physical pritimive pb */ if (nullptr == primitive_pb_type) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_type!\n"); @@ -162,6 +399,11 @@ static void build_primitive_bitstream( bitstream_manager.block_name(parent_configurable_block).c_str()); /* Add the bitstream to the bitstream manager */ + if (M_OVERWRITE_BITS != nullptr) { + std::string path = config_instance_path + std::string(".") + + bitstream_manager.block_name(mem_block); + overwrite_bits(path, mode_select_bitstream); + } bitstream_manager.add_block_bits(mem_block, mode_select_bitstream); } @@ -185,7 +427,8 @@ static void build_physical_block_pin_interc_bitstream( const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, const PhysicalPb& physical_pb, t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode, const bool& verbose) { + t_mode* physical_mode, std::string config_instance_path, + const bool& verbose) { /* Identify the number of fan-in (Consider interconnection edges of only * selected mode) */ t_interconnect* cur_interc = @@ -329,6 +572,11 @@ static void build_physical_block_pin_interc_bitstream( bitstream_manager.block_name(parent_configurable_block).c_str()); /* Add the bistream to the bitstream manager */ + if (M_OVERWRITE_BITS != nullptr) { + std::string path = config_instance_path + std::string(".") + + bitstream_manager.block_name(mux_mem_block); + overwrite_bits(path, mux_bitstream); + } 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); @@ -385,7 +633,7 @@ static void build_physical_block_interc_port_bitstream( const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode, - const bool& verbose) { + std::string config_instance_path, const bool& verbose) { switch (pb_port_type) { case CIRCUIT_PB_PORT_INPUT: for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; @@ -398,7 +646,7 @@ static void build_physical_block_interc_port_bitstream( circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode, - verbose); + config_instance_path, verbose); } } break; @@ -413,7 +661,7 @@ static void build_physical_block_interc_port_bitstream( circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode, - verbose); + config_instance_path, verbose); } } break; @@ -428,7 +676,7 @@ static void build_physical_block_interc_port_bitstream( circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode, - verbose); + config_instance_path, verbose); } } break; @@ -451,7 +699,8 @@ static void build_physical_block_interc_bitstream( const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, - t_mode* physical_mode, const bool& verbose) { + t_mode* physical_mode, std::string config_instance_path, + const bool& verbose) { /* Check if the pb_graph node is valid or not */ if (nullptr == physical_pb_graph_node) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid physical_pb_graph_node.\n"); @@ -472,7 +721,8 @@ static void build_physical_block_interc_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, parent_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb_graph_node, - physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode, verbose); + physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode, config_instance_path, + verbose); /* We check input_pins of child_pb_graph_node and its the input_edges * Iterate over the interconnections between inputs of physical_pb_graph_node @@ -496,14 +746,14 @@ static void build_physical_block_interc_bitstream( parent_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode, - verbose); + config_instance_path, verbose); /* For clock pins, we should do the same work */ build_physical_block_interc_port_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, parent_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode, - verbose); + config_instance_path, verbose); } } } @@ -519,7 +769,8 @@ static void build_lut_bitstream( const VprDeviceAnnotation& device_annotation, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const PhysicalPb& physical_pb, - const PhysicalPbId& lut_pb_id, t_pb_type* lut_pb_type, const bool& verbose) { + const PhysicalPbId& lut_pb_id, t_pb_type* lut_pb_type, + std::string config_instance_path, const bool& verbose) { /* Ensure a valid physical pritimive pb */ if (nullptr == lut_pb_type) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid lut_pb_type!\n"); @@ -688,6 +939,11 @@ static void build_lut_bitstream( bitstream_manager.block_name(parent_configurable_block).c_str()); /* Add the bitstream to the bitstream manager */ + if (M_OVERWRITE_BITS != nullptr) { + std::string path = config_instance_path + std::string(".") + + bitstream_manager.block_name(mem_block); + overwrite_bits(path, lut_bitstream); + } bitstream_manager.add_block_bits(mem_block, lut_bitstream); } @@ -712,7 +968,7 @@ static void rec_build_physical_block_bitstream( const VprBitstreamAnnotation& bitstream_annotation, const e_side& border_side, const PhysicalPb& physical_pb, const PhysicalPbId& pb_id, t_pb_graph_node* physical_pb_graph_node, const size_t& pb_graph_node_index, - const bool& verbose) { + std::string config_instance_path, const bool& verbose) { /* Get the physical pb_type that is linked to the pb_graph node */ t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; @@ -736,6 +992,7 @@ static void rec_build_physical_block_bitstream( * manager */ std::string pb_block_name = generate_physical_block_instance_name( physical_pb_type, pb_graph_node_index); + config_instance_path += (std::string(".") + pb_block_name); /* If there are no physical memory blocks under the current module, use the * previous module, which is the physical memory block */ ConfigBlockId pb_configurable_block = parent_configurable_block; @@ -773,7 +1030,7 @@ static void rec_build_physical_block_bitstream( child_pb, &(physical_pb_graph_node ->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - jpb, verbose); + jpb, config_instance_path, verbose); } } } @@ -788,10 +1045,10 @@ static void rec_build_physical_block_bitstream( /* Special case for LUT !!! * Mapped logical block information is stored in child_pbs of this pb!!! */ - build_lut_bitstream(bitstream_manager, grouped_mem_inst_scoreboard, - pb_configurable_block, device_annotation, - module_manager, circuit_lib, mux_lib, physical_pb, - pb_id, physical_pb_type, verbose); + build_lut_bitstream( + bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, + device_annotation, module_manager, circuit_lib, mux_lib, physical_pb, + pb_id, physical_pb_type, config_instance_path, verbose); break; case CIRCUIT_MODEL_FF: case CIRCUIT_MODEL_HARDLOGIC: @@ -800,7 +1057,7 @@ static void rec_build_physical_block_bitstream( build_primitive_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, module_manager, circuit_lib, device_annotation, physical_pb, pb_id, - physical_pb_type, verbose); + physical_pb_type, config_instance_path, verbose); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -817,7 +1074,7 @@ static void rec_build_physical_block_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb_graph_node, - physical_pb, physical_mode, verbose); + physical_pb, physical_mode, config_instance_path, verbose); } /******************************************************************** @@ -866,7 +1123,7 @@ static void build_physical_block_bitstream( std::string grid_block_name = generate_grid_block_instance_name( grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), border_side, grid_coord_in_unique_tile); - + track_physical_block_grid(grid_block_name); ConfigBlockId grid_configurable_block = bitstream_manager.add_block(grid_block_name); bitstream_manager.add_child_block(top_block, grid_configurable_block); @@ -931,7 +1188,7 @@ static void build_physical_block_bitstream( grid_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, border_side, PhysicalPb(), PhysicalPbId::INVALID(), - lb_type->pb_graph_head, z, verbose); + lb_type->pb_graph_head, z, "", verbose); } else { const PhysicalPb& phy_pb = cluster_annotation.physical_pb( place_annotation.grid_blocks(grid_coord)[z]); @@ -946,7 +1203,7 @@ static void build_physical_block_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, grid_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, - border_side, phy_pb, top_pb_id, pb_graph_head, z, verbose); + border_side, phy_pb, top_pb_id, pb_graph_head, z, "", verbose); } } } @@ -966,9 +1223,13 @@ void build_grid_bitstream( const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, - const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose) { + const VprBitstreamAnnotation& bitstream_annotation, + const std::string& overwrite_bitstream_file, const bool& verbose) { VTR_LOGV(verbose, "Generating bitstream for core grids..."); + /* Read file that might want to overwrite the bitstream */ + read_overwrite_file(overwrite_bitstream_file); + /* Generate bitstream for the core logic block one by one */ for (size_t ix = 1; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { @@ -1002,7 +1263,7 @@ void build_grid_bitstream( tile_inst_name.c_str(), bitstream_manager.block_name(top_block).c_str()); } - + track_fabric_top_name(bitstream_manager.block_name(top_block)); build_physical_block_bitstream( bitstream_manager, parent_block, module_manager, module_name_map, fabric_tile, curr_tile, circuit_lib, mux_lib, atom_ctx, @@ -1050,7 +1311,7 @@ void build_grid_bitstream( tile_inst_name.c_str(), bitstream_manager.block_name(parent_block).c_str()); } - + track_fabric_top_name(bitstream_manager.block_name(top_block)); build_physical_block_bitstream( bitstream_manager, parent_block, module_manager, module_name_map, fabric_tile, curr_tile, circuit_lib, mux_lib, atom_ctx, @@ -1058,6 +1319,7 @@ void build_grid_bitstream( bitstream_annotation, grids, layer, io_coordinate, io_side, verbose); } } + cleanup_overwrite(); VTR_LOGV(verbose, "Done\n"); } diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.h b/openfpga/src/fpga_bitstream/build_grid_bitstream.h index 36b297c987..4fe200427e 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.h @@ -34,7 +34,8 @@ void build_grid_bitstream( const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, - const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose); + const VprBitstreamAnnotation& bitstream_annotation, + const std::string& overwrite_bitstream_file, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga b/openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga new file mode 100644 index 0000000000..0903f0f899 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga @@ -0,0 +1,74 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --device ${OPENFPGA_VPR_DEVICE_LAYOUT} + +# 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 Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# 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_independent_bitstream.xml --overwrite_bitstream_file ../../../../config/overwrite_bitstream.txt + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text +write_fabric_bitstream --file fabric_bitstream.xml --format xml + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit +write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index 174b4cabe7..db23208183 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -15,6 +15,9 @@ echo -e "Testing bitstream generation for an 48x48 FPGA device"; run-task fpga_bitstream/generate_bitstream/configuration_chain/device_48x48 $@ run-task fpga_bitstream/generate_bitstream/ql_memory_bank_shift_register/device_48x48 $@ +echo -e "Testing bitstream generation for an 4x4 FPGA device (overwrite IO tile bits)"; +run-task fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite $@ + echo -e "Testing bitstream generation for an 96x96 FPGA device"; run-task fpga_bitstream/generate_bitstream/configuration_chain/device_96x96 $@ run-task fpga_bitstream/generate_bitstream/ql_memory_bank_shift_register/device_72x72 $@ diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/overwrite_bitstream.txt b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/overwrite_bitstream.txt new file mode 100644 index 0000000000..ec1dc059b3 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/overwrite_bitstream.txt @@ -0,0 +1,2 @@ +fpga_top.grid_io_left_0__1_ logical_tile_io_mode_io__7.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem 0 +fpga_top.grid_io_bottom_3__0_ logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem [0]=0 \ No newline at end of file diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/task.conf new file mode 100644 index 0000000000..c54b4bf3f5 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/task.conf @@ -0,0 +1,35 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=4x4 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_wide_mem16K_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 e60777d23eb10b7a80ab17a4afc4b9289769918d Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Fri, 26 Jul 2024 01:36:49 -0700 Subject: [PATCH 07/19] Use Bitstream Setting XML --- .../libarchopenfpga/src/bitstream_setting.cpp | 10 + libs/libarchopenfpga/src/bitstream_setting.h | 10 + .../src/read_xml_bitstream_setting.cpp | 26 +- .../src/bitstream_manager.cpp | 39 +++ libs/libfpgabitstream/src/bitstream_manager.h | 3 + .../src/bitstream_manager_utils.cpp | 17 + .../src/bitstream_manager_utils.h | 2 + .../openfpga_bitstream_command_template.h | 6 - .../src/base/openfpga_bitstream_template.h | 6 +- .../fpga_bitstream/build_device_bitstream.cpp | 14 +- .../fpga_bitstream/build_device_bitstream.h | 6 +- .../fpga_bitstream/build_grid_bitstream.cpp | 312 ++---------------- .../src/fpga_bitstream/build_grid_bitstream.h | 3 +- 13 files changed, 143 insertions(+), 311 deletions(-) diff --git a/libs/libarchopenfpga/src/bitstream_setting.cpp b/libs/libarchopenfpga/src/bitstream_setting.cpp index 7d763f9d2b..e3cc3f697b 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/bitstream_setting.cpp @@ -106,6 +106,10 @@ std::vector BitstreamSetting::non_fabric() const { return non_fabric_; } +std::vector BitstreamSetting::path_bit_settings() const { + return path_bit_settings_; +} + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -178,6 +182,12 @@ void BitstreamSetting::add_non_fabric_pb(const std::string& pb, } } +void BitstreamSetting::add_path_bit_setting(const std::string& path, + const bool value) { + VTR_ASSERT(path.size()); + path_bit_settings_.push_back(PathBitSetting(path, value)); +} + /************************************************************************ * Public Validators ***********************************************************************/ diff --git a/libs/libarchopenfpga/src/bitstream_setting.h b/libs/libarchopenfpga/src/bitstream_setting.h index 1b12c8de32..dc70c7b14c 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.h +++ b/libs/libarchopenfpga/src/bitstream_setting.h @@ -37,6 +37,12 @@ struct NonFabricBitstreamSetting { std::vector pbs; }; +struct PathBitSetting { + PathBitSetting(const std::string& p, bool v) : path(p), value(v) {} + const std::string path = ""; + const bool value = false; +}; + /******************************************************************** * A data structure to describe bitstream settings * @@ -98,6 +104,7 @@ class BitstreamSetting { std::string default_path( const BitstreamInterconnectSettingId& interconnect_setting_id) const; std::vector non_fabric() const; + std::vector path_bit_settings() const; public: /* Public Mutators */ BitstreamPbTypeSettingId add_bitstream_pb_type_setting( @@ -120,6 +127,8 @@ 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); + void add_path_bit_setting(const std::string& path, const bool value); + public: /* Public Validators */ bool valid_bitstream_pb_type_setting_id( const BitstreamPbTypeSettingId& pb_type_setting_id) const; @@ -162,6 +171,7 @@ class BitstreamSetting { vtr::vector interconnect_default_paths_; std::vector non_fabric_; + std::vector path_bit_settings_; }; } // namespace openfpga diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 7f6bd12372..23bbed0ae4 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -102,6 +102,21 @@ static void read_xml_non_fabric_bitstream_setting( } } +/******************************************************************** + * Parse XML description for a bit setting under a XML node + *******************************************************************/ +static void read_xml_bit_setting( + pugi::xml_node& xml_bit, const pugiutil::loc_data& loc_data, + openfpga::BitstreamSetting& bitstream_setting) { + 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(); + VTR_ASSERT_SAFE(value_attr == "0" || value_attr == "1"); + /* Add to bit */ + bitstream_setting.add_path_bit_setting(path_attr, value_attr == "1"); +} + /******************************************************************** * Parse XML codes about to an object *******************************************************************/ @@ -116,9 +131,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("bit"))) { bad_tag(xml_child, loc_data, Node, - {"pb_type | interconnect | non_fabric"}); + {"pb_type | interconnect | non_fabric | bit"}); } if (xml_child.name() == std::string("pb_type")) { @@ -127,10 +143,12 @@ 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("bit")); + read_xml_bit_setting(xml_child, loc_data, bitstream_setting); } } diff --git a/libs/libfpgabitstream/src/bitstream_manager.cpp b/libs/libfpgabitstream/src/bitstream_manager.cpp index cf18a6e861..673e28c9d0 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager.cpp @@ -5,6 +5,7 @@ #include +#include "bitstream_manager_utils.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -296,6 +297,44 @@ void BitstreamManager::add_output_net_id_to_block( block_output_net_ids_[block] = output_net_id; } +void BitstreamManager::set_path_bit(const std::string& path, const bool value) { + ConfigBlockId block; + std::vector blocks = + reverse_split_bit_path_to_blocks((std::string)(path)); + std::string block_name = ""; + bool match = false; + for (size_t i = 0; i < bit_values_.size() && !match; i++) { + block = bit_parent_blocks_[ConfigBitId(i)]; + if (size_t(block) < num_blocks_) { + size_t index = find_bitstream_manager_config_bit_index_in_parent_block( + *this, ConfigBitId(i)); + block_name = block_names_[block] + ("[" + std::to_string(index) + "]"); + if (block_name == blocks[0]) { + match = true; + for (size_t b = 1; b < blocks.size() && match; b++) { + valid_block_id(block); + block = parent_block_ids_[block]; + if (size_t(block) < num_blocks_) { + if (block_names_[block] != blocks[b]) { + match = false; + } + } else { + match = false; + } + } + if (match) { + valid_block_id(block); + if (parent_block_ids_[block] == ConfigBlockId::INVALID()) { + bit_values_[ConfigBitId(i)] = value ? '1' : '0'; + } else { + match = false; + } + } + } + } + } +} + /****************************************************************************** * Public Validators ******************************************************************************/ diff --git a/libs/libfpgabitstream/src/bitstream_manager.h b/libs/libfpgabitstream/src/bitstream_manager.h index 4af15084d1..daaccbd7f2 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.h +++ b/libs/libfpgabitstream/src/bitstream_manager.h @@ -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 set_path_bit(const std::string& path, const bool value); + public: /* Public Validators */ bool valid_bit_id(const ConfigBitId& bit_id) const; diff --git a/libs/libfpgabitstream/src/bitstream_manager_utils.cpp b/libs/libfpgabitstream/src/bitstream_manager_utils.cpp index 13ef85bbdc..c9bff9b396 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_utils.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager_utils.cpp @@ -130,4 +130,21 @@ size_t rec_find_bitstream_manager_block_sum_of_bits( return sum_of_bits; } +/******************************************************************** + * Split the bit path with delimiter ".". The blocks is reversed + *******************************************************************/ +std::vector reverse_split_bit_path_to_blocks(std::string path) { + std::vector blocks; + size_t index = path.find_first_of("."); + while (index != std::string::npos) { + blocks.insert(blocks.begin(), path.substr(0, index)); + path = path.substr(index + 1); + index = path.find_first_of("."); + } + if (path.size()) { + blocks.insert(blocks.begin(), path); + } + return blocks; +} + } /* end namespace openfpga */ diff --git a/libs/libfpgabitstream/src/bitstream_manager_utils.h b/libs/libfpgabitstream/src/bitstream_manager_utils.h index 26d6f35b89..ff24b961d8 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_utils.h +++ b/libs/libfpgabitstream/src/bitstream_manager_utils.h @@ -31,6 +31,8 @@ size_t find_bitstream_manager_config_bit_index_in_grandparent_block( size_t rec_find_bitstream_manager_block_sum_of_bits( const BitstreamManager& bitstream_manager, const ConfigBlockId& block); +std::vector reverse_split_bit_path_to_blocks(std::string path); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_bitstream_command_template.h b/openfpga/src/base/openfpga_bitstream_command_template.h index a3d40f9f91..f80176514d 100644 --- a/openfpga/src/base/openfpga_bitstream_command_template.h +++ b/openfpga/src/base/openfpga_bitstream_command_template.h @@ -78,12 +78,6 @@ ShellCommandId add_build_arch_bitstream_command_template( shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); - /* Add an option '--overwrite_bitstream_file' */ - CommandOptionId opt_overwrite_file = - shell_cmd.add_option("overwrite_bitstream_file", false, - "file path to read to overwrite bitstream bits"); - shell_cmd.set_option_require_value(opt_overwrite_file, openfpga::OPT_STRING); - /* Add an option '--verbose' */ shell_cmd.add_option("verbose", false, "Enable verbose output"); diff --git a/openfpga/src/base/openfpga_bitstream_template.h b/openfpga/src/base/openfpga_bitstream_template.h index 19c9a4bc69..c132e907f7 100644 --- a/openfpga/src/base/openfpga_bitstream_template.h +++ b/openfpga/src/base/openfpga_bitstream_template.h @@ -38,17 +38,13 @@ int fpga_bitstream_template(T& openfpga_ctx, const Command& cmd, CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); CommandOptionId opt_write_file = cmd.option("write_file"); CommandOptionId opt_read_file = cmd.option("read_file"); - CommandOptionId opt_overwrite_bitstream_file = - cmd.option("overwrite_bitstream_file"); if (true == cmd_context.option_enable(cmd, opt_read_file)) { openfpga_ctx.mutable_bitstream_manager() = read_xml_architecture_bitstream( cmd_context.option_value(cmd, opt_read_file).c_str()); } else { openfpga_ctx.mutable_bitstream_manager() = build_device_bitstream( - g_vpr_ctx, openfpga_ctx, - cmd_context.option_value(cmd, opt_overwrite_bitstream_file), - cmd_context.option_enable(cmd, opt_verbose)); + g_vpr_ctx, openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); } if (true == cmd_context.option_enable(cmd, opt_write_file)) { diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 7f27cea52f..b832d927bc 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -147,9 +147,9 @@ static size_t rec_estimate_device_bitstream_num_bits( * of the FPGA fabric that FPGA-X2P generates! * But it can be used to output a generic bitstream for VPR mapping FPGA *******************************************************************/ -BitstreamManager build_device_bitstream( - const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, - const std::string& overwrite_bitstream_file, const bool& verbose) { +BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, + const OpenfpgaContext& openfpga_ctx, + const bool& verbose) { std::string timer_message = std::string("\nBuild fabric-independent bitstream for implementation '") + vpr_ctx.atom().nlist.netlist_name() + std::string("'\n"); @@ -218,7 +218,7 @@ BitstreamManager build_device_bitstream( openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_clustering_annotation(), openfpga_ctx.vpr_placement_annotation(), - openfpga_ctx.vpr_bitstream_annotation(), overwrite_bitstream_file, verbose); + openfpga_ctx.vpr_bitstream_annotation(), verbose); VTR_LOGV(verbose, "Done\n"); /* Create bitstream from routing architectures */ @@ -230,6 +230,12 @@ BitstreamManager build_device_bitstream( openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_routing_annotation(), vpr_ctx.device().rr_graph, openfpga_ctx.device_rr_gsb(), openfpga_ctx.flow_manager().compress_routing(), verbose); + + /* Apply path bit value */ + for (auto bit : openfpga_ctx.bitstream_setting().path_bit_settings()) { + bitstream_manager.set_path_bit(bit.path, bit.value); + } + VTR_LOGV(verbose, "Done\n"); VTR_LOGV(verbose, "Decoded %lu configuration bits into %lu blocks\n", diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.h b/openfpga/src/fpga_bitstream/build_device_bitstream.h index 044b932310..3bddf92115 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.h @@ -16,9 +16,9 @@ /* begin namespace openfpga */ namespace openfpga { -BitstreamManager build_device_bitstream( - const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, - const std::string& overwrite_bitstream_file, const bool& verbose); +BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, + const OpenfpgaContext& openfpga_ctx, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index 44e33e8598..d8e4f17fbf 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -3,7 +3,6 @@ * for grids (CLBs, heterogenerous blocks, I/Os, etc.) *******************************************************************/ #include -#include #include /* Headers from vtrutil library */ @@ -30,242 +29,6 @@ /* begin namespace openfpga */ namespace openfpga { -struct OVERWRITE_BITS { - OVERWRITE_BITS(bool i, int s, int e, uint64_t b) - : incr(i), start(s), end(e), bits(b) {} - bool incr = true; - int start = -1; - int end = -1; - uint64_t bits = 0; -}; - -std::string M_TOP_NAME = ""; -std::string M_BLOCK_GRID_NAME = ""; -std::map>*> - M_OVERWRITE_GRID_BITS; -std::map>* M_OVERWRITE_BITS = nullptr; - -/******************************************************************** - * Track the fabric top name - *******************************************************************/ -static void track_fabric_top_name(const std::string& top) { - VTR_ASSERT(top.size()); - M_TOP_NAME = top; -} - -/******************************************************************** - * Track the fabric grid name - *******************************************************************/ -static void track_physical_block_grid(const std::string& block) { - VTR_ASSERT(M_TOP_NAME.size()); - VTR_ASSERT(block.size()); - M_BLOCK_GRID_NAME = M_TOP_NAME + std::string(".") + block; - if (M_OVERWRITE_GRID_BITS.find(M_BLOCK_GRID_NAME) != - M_OVERWRITE_GRID_BITS.end()) { - M_OVERWRITE_BITS = M_OVERWRITE_GRID_BITS[M_BLOCK_GRID_NAME]; - } else { - M_OVERWRITE_BITS = nullptr; - } -} - -/******************************************************************** - * Trim whitespace - *******************************************************************/ -static void trim_white_space(std::string& line) { - const auto begin = line.find_first_not_of(" \t\r\n"); - if (begin != std::string::npos) { - const auto end = line.find_last_not_of(" \t\r\n"); - const auto count = end - begin + 1; - line = line.substr(begin, count); - } -} - -/******************************************************************** - * Split the line by delimiter - *******************************************************************/ -static std::vector split_line_by( - std::string line, const std::string& delimiter = " \t") { - std::vector results; - size_t index = line.find_first_of(delimiter); - trim_white_space(line); - while (index != std::string::npos) { - std::string result = line.substr(0, index); - trim_white_space(result); - results.push_back(result); - line = line.substr(index + 1); - trim_white_space(line); - index = line.find_first_of(delimiter); - } - if (line.size()) { - results.push_back(line); - } - return results; -} - -/******************************************************************** - * Check if the string is all number - *******************************************************************/ -static bool is_number(const std::string& s) { - std::string::const_iterator it = s.begin(); - while (it != s.end() && std::isdigit(*it)) ++it; - return !s.empty() && it == s.end(); -} - -/******************************************************************** - * Convert string to uint64_t - *******************************************************************/ -static uint64_t get_number(const std::string& s) { - uint64_t value = 0; - std::istringstream iss(s); - iss >> value; - return value; -} - -/******************************************************************** - * Cleanup - *******************************************************************/ -static void cleanup_overwrite() { - for (auto& iter : M_OVERWRITE_GRID_BITS) { - delete iter.second; - } - M_OVERWRITE_GRID_BITS.clear(); - M_OVERWRITE_BITS = nullptr; -} - -/******************************************************************** - * Read the overwrite file - *******************************************************************/ -static void read_overwrite_file(const std::string& filepath) { - cleanup_overwrite(); - if (filepath.size()) { - std::ifstream file(filepath.c_str()); - if (file.is_open()) { - if (file.good()) { - std::string line = ""; - while (std::getline(file, line)) { - trim_white_space(line); - if (line.size() && line[0] != '#') { - std::vector words = split_line_by(line); - if (words.size() >= 3 && words[0].size() > 0 && - words[1].size() > 0) { - // Prepare the pointer to fillup path and bits (speedup stuff) - M_OVERWRITE_BITS = nullptr; - if (M_OVERWRITE_GRID_BITS.find(words[0]) != - M_OVERWRITE_GRID_BITS.end()) { - M_OVERWRITE_BITS = M_OVERWRITE_GRID_BITS.at(words[0]); - } - std::string path = std::string(".") + words[1]; - for (size_t i = 2; i < words.size(); i++) { - std::vector values = split_line_by(words[i], "="); - bool incr = true; - int start = -1; - int end = -1; - uint64_t value = 0; - if (values.size() == 1) { - if (is_number(values[0])) { - value = get_number(values[0]); - } else { - // Bad - continue; - } - } else if (values.size() == 2) { - if (values[0].size() >= 3 && values[0][0] == '[' && - values[0][values[0].size() - 1] == ']') { - line = values[0].substr(1, values[0].size() - 2); - trim_white_space(line); - std::vector range = split_line_by(line, ":"); - if (range.size() == 1 && is_number(range[0])) { - start = get_number(range[0]); - end = start; - } else if (range.size() == 2 && is_number(range[0]) && - is_number(range[1])) { - end = (int)(get_number(range[0])); - start = (int)(get_number(range[1])); - incr = end >= start; - } else { - // Bad - continue; - } - if (is_number(values[1])) { - value = get_number(values[1]); - } else { - // Bad - continue; - } - } else { - // Bad - continue; - } - } else { - // Bad - continue; - } - if ((start == -1 && end == -1) || (start >= 0 && end >= 0)) { - if (M_OVERWRITE_BITS == nullptr) { - M_OVERWRITE_BITS = - new std::map>; - M_OVERWRITE_GRID_BITS[words[0]] = M_OVERWRITE_BITS; - } - if (M_OVERWRITE_BITS->find(path) == M_OVERWRITE_BITS->end()) { - (*M_OVERWRITE_BITS)[path] = {}; - } - M_OVERWRITE_BITS->at(path).push_back( - OVERWRITE_BITS(incr, start, end, value)); - } - } - } - } - } - } - file.close(); - } - } - M_OVERWRITE_BITS = nullptr; -} - -/******************************************************************** - * Overwrite the bits - *******************************************************************/ -static void overwrite_bits(const std::string& path, std::vector& bits) { - VTR_ASSERT(M_OVERWRITE_BITS != nullptr); - if (M_OVERWRITE_BITS->find(path) != M_OVERWRITE_BITS->end()) { - for (OVERWRITE_BITS& obits : M_OVERWRITE_BITS->at(path)) { - if (obits.start == -1 && obits.end == -1) { - for (int i = 0; i < int(bits.size()); i++) { - if (obits.bits & (1 << i)) { - bits[i] = true; - } else { - bits[i] = false; - } - } - } else { - int i = 0; - int start = obits.start; - while (true) { - if (start >= 0 && start < int(bits.size())) { - if (obits.bits & (1 << i)) { - bits[start] = true; - } else { - bits[start] = false; - } - } else { - break; - } - if (start == obits.end) { - break; - } - i++; - if (obits.incr) { - start++; - } else { - start--; - } - } - } - } - } -} - /******************************************************************** * Decode mode bits "01..." to a bitstream vector *******************************************************************/ @@ -292,7 +55,7 @@ static void build_primitive_bitstream( const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& device_annotation, const PhysicalPb& physical_pb, const PhysicalPbId& primitive_pb_id, t_pb_type* primitive_pb_type, - std::string config_instance_path, const bool& verbose) { + const bool& verbose) { /* Ensure a valid physical pritimive pb */ if (nullptr == primitive_pb_type) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_type!\n"); @@ -399,11 +162,6 @@ static void build_primitive_bitstream( bitstream_manager.block_name(parent_configurable_block).c_str()); /* Add the bitstream to the bitstream manager */ - if (M_OVERWRITE_BITS != nullptr) { - std::string path = config_instance_path + std::string(".") + - bitstream_manager.block_name(mem_block); - overwrite_bits(path, mode_select_bitstream); - } bitstream_manager.add_block_bits(mem_block, mode_select_bitstream); } @@ -427,8 +185,7 @@ static void build_physical_block_pin_interc_bitstream( const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, const PhysicalPb& physical_pb, t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode, std::string config_instance_path, - const bool& verbose) { + t_mode* physical_mode, const bool& verbose) { /* Identify the number of fan-in (Consider interconnection edges of only * selected mode) */ t_interconnect* cur_interc = @@ -572,11 +329,6 @@ static void build_physical_block_pin_interc_bitstream( bitstream_manager.block_name(parent_configurable_block).c_str()); /* Add the bistream to the bitstream manager */ - if (M_OVERWRITE_BITS != nullptr) { - std::string path = config_instance_path + std::string(".") + - bitstream_manager.block_name(mux_mem_block); - overwrite_bits(path, mux_bitstream); - } 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); @@ -633,7 +385,7 @@ static void build_physical_block_interc_port_bitstream( const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode, - std::string config_instance_path, const bool& verbose) { + const bool& verbose) { switch (pb_port_type) { case CIRCUIT_PB_PORT_INPUT: for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; @@ -646,7 +398,7 @@ static void build_physical_block_interc_port_bitstream( circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode, - config_instance_path, verbose); + verbose); } } break; @@ -661,7 +413,7 @@ static void build_physical_block_interc_port_bitstream( circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode, - config_instance_path, verbose); + verbose); } } break; @@ -676,7 +428,7 @@ static void build_physical_block_interc_port_bitstream( circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode, - config_instance_path, verbose); + verbose); } } break; @@ -699,8 +451,7 @@ static void build_physical_block_interc_bitstream( const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, - t_mode* physical_mode, std::string config_instance_path, - const bool& verbose) { + t_mode* physical_mode, const bool& verbose) { /* Check if the pb_graph node is valid or not */ if (nullptr == physical_pb_graph_node) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid physical_pb_graph_node.\n"); @@ -721,8 +472,7 @@ static void build_physical_block_interc_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, parent_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb_graph_node, - physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode, config_instance_path, - verbose); + physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode, verbose); /* We check input_pins of child_pb_graph_node and its the input_edges * Iterate over the interconnections between inputs of physical_pb_graph_node @@ -746,14 +496,14 @@ static void build_physical_block_interc_bitstream( parent_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode, - config_instance_path, verbose); + verbose); /* For clock pins, we should do the same work */ build_physical_block_interc_port_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, parent_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode, - config_instance_path, verbose); + verbose); } } } @@ -769,8 +519,7 @@ static void build_lut_bitstream( const VprDeviceAnnotation& device_annotation, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const PhysicalPb& physical_pb, - const PhysicalPbId& lut_pb_id, t_pb_type* lut_pb_type, - std::string config_instance_path, const bool& verbose) { + const PhysicalPbId& lut_pb_id, t_pb_type* lut_pb_type, const bool& verbose) { /* Ensure a valid physical pritimive pb */ if (nullptr == lut_pb_type) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid lut_pb_type!\n"); @@ -939,11 +688,6 @@ static void build_lut_bitstream( bitstream_manager.block_name(parent_configurable_block).c_str()); /* Add the bitstream to the bitstream manager */ - if (M_OVERWRITE_BITS != nullptr) { - std::string path = config_instance_path + std::string(".") + - bitstream_manager.block_name(mem_block); - overwrite_bits(path, lut_bitstream); - } bitstream_manager.add_block_bits(mem_block, lut_bitstream); } @@ -968,7 +712,7 @@ static void rec_build_physical_block_bitstream( const VprBitstreamAnnotation& bitstream_annotation, const e_side& border_side, const PhysicalPb& physical_pb, const PhysicalPbId& pb_id, t_pb_graph_node* physical_pb_graph_node, const size_t& pb_graph_node_index, - std::string config_instance_path, const bool& verbose) { + const bool& verbose) { /* Get the physical pb_type that is linked to the pb_graph node */ t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; @@ -992,7 +736,6 @@ static void rec_build_physical_block_bitstream( * manager */ std::string pb_block_name = generate_physical_block_instance_name( physical_pb_type, pb_graph_node_index); - config_instance_path += (std::string(".") + pb_block_name); /* If there are no physical memory blocks under the current module, use the * previous module, which is the physical memory block */ ConfigBlockId pb_configurable_block = parent_configurable_block; @@ -1030,7 +773,7 @@ static void rec_build_physical_block_bitstream( child_pb, &(physical_pb_graph_node ->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - jpb, config_instance_path, verbose); + jpb, verbose); } } } @@ -1045,10 +788,10 @@ static void rec_build_physical_block_bitstream( /* Special case for LUT !!! * Mapped logical block information is stored in child_pbs of this pb!!! */ - build_lut_bitstream( - bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, - device_annotation, module_manager, circuit_lib, mux_lib, physical_pb, - pb_id, physical_pb_type, config_instance_path, verbose); + build_lut_bitstream(bitstream_manager, grouped_mem_inst_scoreboard, + pb_configurable_block, device_annotation, + module_manager, circuit_lib, mux_lib, physical_pb, + pb_id, physical_pb_type, verbose); break; case CIRCUIT_MODEL_FF: case CIRCUIT_MODEL_HARDLOGIC: @@ -1057,7 +800,7 @@ static void rec_build_physical_block_bitstream( build_primitive_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, module_manager, circuit_lib, device_annotation, physical_pb, pb_id, - physical_pb_type, config_instance_path, verbose); + physical_pb_type, verbose); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -1074,7 +817,7 @@ static void rec_build_physical_block_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, physical_pb_graph_node, - physical_pb, physical_mode, config_instance_path, verbose); + physical_pb, physical_mode, verbose); } /******************************************************************** @@ -1123,7 +866,7 @@ static void build_physical_block_bitstream( std::string grid_block_name = generate_grid_block_instance_name( grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), border_side, grid_coord_in_unique_tile); - track_physical_block_grid(grid_block_name); + ConfigBlockId grid_configurable_block = bitstream_manager.add_block(grid_block_name); bitstream_manager.add_child_block(top_block, grid_configurable_block); @@ -1188,7 +931,7 @@ static void build_physical_block_bitstream( grid_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, border_side, PhysicalPb(), PhysicalPbId::INVALID(), - lb_type->pb_graph_head, z, "", verbose); + lb_type->pb_graph_head, z, verbose); } else { const PhysicalPb& phy_pb = cluster_annotation.physical_pb( place_annotation.grid_blocks(grid_coord)[z]); @@ -1203,7 +946,7 @@ static void build_physical_block_bitstream( bitstream_manager, grouped_mem_inst_scoreboard, grid_configurable_block, module_manager, module_name_map, circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, - border_side, phy_pb, top_pb_id, pb_graph_head, z, "", verbose); + border_side, phy_pb, top_pb_id, pb_graph_head, z, verbose); } } } @@ -1223,13 +966,9 @@ void build_grid_bitstream( const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const std::string& overwrite_bitstream_file, const bool& verbose) { + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose) { VTR_LOGV(verbose, "Generating bitstream for core grids..."); - /* Read file that might want to overwrite the bitstream */ - read_overwrite_file(overwrite_bitstream_file); - /* Generate bitstream for the core logic block one by one */ for (size_t ix = 1; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { @@ -1263,7 +1002,7 @@ void build_grid_bitstream( tile_inst_name.c_str(), bitstream_manager.block_name(top_block).c_str()); } - track_fabric_top_name(bitstream_manager.block_name(top_block)); + build_physical_block_bitstream( bitstream_manager, parent_block, module_manager, module_name_map, fabric_tile, curr_tile, circuit_lib, mux_lib, atom_ctx, @@ -1311,7 +1050,7 @@ void build_grid_bitstream( tile_inst_name.c_str(), bitstream_manager.block_name(parent_block).c_str()); } - track_fabric_top_name(bitstream_manager.block_name(top_block)); + build_physical_block_bitstream( bitstream_manager, parent_block, module_manager, module_name_map, fabric_tile, curr_tile, circuit_lib, mux_lib, atom_ctx, @@ -1319,7 +1058,6 @@ void build_grid_bitstream( bitstream_annotation, grids, layer, io_coordinate, io_side, verbose); } } - cleanup_overwrite(); VTR_LOGV(verbose, "Done\n"); } diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.h b/openfpga/src/fpga_bitstream/build_grid_bitstream.h index 4fe200427e..36b297c987 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.h @@ -34,8 +34,7 @@ void build_grid_bitstream( const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, - const VprBitstreamAnnotation& bitstream_annotation, - const std::string& overwrite_bitstream_file, const bool& verbose); + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose); } /* end namespace openfpga */ From 9641aaf6c48f77ae23215795f7f7722be4113c30 Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Fri, 26 Jul 2024 02:17:25 -0700 Subject: [PATCH 08/19] Update test --- .../regression_test_scripts/fpga_bitstream_reg_test.sh | 2 +- .../config/bitstream_annotation.xml | 9 +++++++++ .../config/task.conf | 3 ++- .../device_4x4_PathBitSetting/config/write_xml.openfpga} | 9 +++++++-- .../device_4x4_overwrite/config/overwrite_bitstream.txt | 2 -- 5 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml rename openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/{device_4x4_overwrite => device_4x4_PathBitSetting}/config/task.conf (80%) rename openfpga_flow/{openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga => tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga} (92%) delete mode 100644 openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/overwrite_bitstream.txt diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index db23208183..d6ba24549a 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -16,7 +16,7 @@ run-task fpga_bitstream/generate_bitstream/configuration_chain/device_48x48 $@ run-task fpga_bitstream/generate_bitstream/ql_memory_bank_shift_register/device_48x48 $@ echo -e "Testing bitstream generation for an 4x4 FPGA device (overwrite IO tile bits)"; -run-task fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite $@ +run-task fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting $@ echo -e "Testing bitstream generation for an 96x96 FPGA device"; run-task fpga_bitstream/generate_bitstream/configuration_chain/device_96x96 $@ diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml new file mode 100644 index 0000000000..19ed76fe42 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/task.conf similarity index 80% rename from openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/task.conf rename to openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/task.conf index c54b4bf3f5..eb36a69e6d 100644 --- a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/task.conf +++ b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/task.conf @@ -16,9 +16,10 @@ timeout_each_job = 20*60 fpga_flow=vpr_blif [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_bitstream_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml openfpga_vpr_device_layout=4x4 [ARCHITECTURES] diff --git a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga similarity index 92% rename from openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga rename to openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga index 0903f0f899..81abe263fb 100644 --- a/openfpga_flow/openfpga_shell_scripts/fix_device_example_script_overwrite.openfpga +++ b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga @@ -1,3 +1,5 @@ +# This file is copied from fix_device_example_script.openfpga + # Run VPR for the 'and' design #--write_rr_graph example_rr_graph.xml vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --device ${OPENFPGA_VPR_DEVICE_LAYOUT} @@ -8,6 +10,9 @@ read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} # Read OpenFPGA simulation settings read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} +# Read OpenFPGA bitstream settings +read_openfpga_bitstream_setting -f ${OPENFPGA_BITSTREAM_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 @@ -34,14 +39,14 @@ repack #--verbose # Build the bitstream # - Output the fabric-independent bitstream to a file -build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml --overwrite_bitstream_file ../../../../config/overwrite_bitstream.txt +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml # Build fabric-dependent bitstream build_fabric_bitstream --verbose # Write fabric-dependent bitstream write_fabric_bitstream --file fabric_bitstream.bit --format plain_text -write_fabric_bitstream --file fabric_bitstream.xml --format xml +write_fabric_bitstream --file fabric_bitstream.xml --format xml # Write the Verilog netlist for FPGA fabric # - Enable the use of explicit port mapping in Verilog netlist diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/overwrite_bitstream.txt b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/overwrite_bitstream.txt deleted file mode 100644 index ec1dc059b3..0000000000 --- a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_overwrite/config/overwrite_bitstream.txt +++ /dev/null @@ -1,2 +0,0 @@ -fpga_top.grid_io_left_0__1_ logical_tile_io_mode_io__7.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem 0 -fpga_top.grid_io_bottom_3__0_ logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem [0]=0 \ No newline at end of file From fbe5ae6bd359b4c2cf12bb14c784cbaad32f1cfe Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Fri, 26 Jul 2024 02:18:08 -0700 Subject: [PATCH 09/19] Update test --- .../device_4x4_PathBitSetting/config/bitstream_annotation.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml index 19ed76fe42..24b5fa8f65 100644 --- a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml +++ b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml @@ -5,5 +5,5 @@ --> - + From 0ff0c3445ec6944b9d3e8313c92a275ab987c32f Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Fri, 26 Jul 2024 13:43:31 -0700 Subject: [PATCH 10/19] Update doc --- .../manual/file_formats/bitstream_setting.rst | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/source/manual/file_formats/bitstream_setting.rst b/docs/source/manual/file_formats/bitstream_setting.rst index eb2af5ddfa..d18614b7e7 100644 --- a/docs/source/manual/file_formats/bitstream_setting.rst +++ b/docs/source/manual/file_formats/bitstream_setting.rst @@ -16,6 +16,7 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab + pb_type-related Settings @@ -75,7 +76,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 @@ -97,7 +98,7 @@ The following syntax are applicable to the XML definition tagged by ``non_fabric file="bram.json" -.. option:: ``pb`` child element name="" +.. option:: pb child element name="" Together with ``pb_type`` top level name, that is the source of the ``pb_type`` bitstream @@ -112,6 +113,29 @@ 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="" +.. option:: pb child element content="" 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``. + +bit-related Settings +^^^^^^^^^^^^^^^^^^^^ + +This is to allow user to set particular bit using full path in the hierarchy of FPGA fabric + +The following syntax are applicable to the XML definition tagged by ``bit`` in bitstream setting files. + +.. option:: value="<0 or 1>" + + The boolean ``0`` or ``1`` that will be set. For example, + + .. code-block:: xml + + value="0" + +.. option:: path="" + + ``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]" From 933155b08fe9e6b3d2d5bb3133ffbbfb0b5822dd Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Sat, 27 Jul 2024 23:52:54 -0700 Subject: [PATCH 11/19] Update test flow --- .../src/read_xml_bitstream_setting.cpp | 28 ++-- openfpga/src/base/openfpga_basic.cpp | 10 +- .../fpga_bitstream_reg_test.sh | 4 +- .../config/bitstream_annotation.xml | 9 -- .../config/write_xml.openfpga | 79 ------------ .../device_4x4}/config/task.conf | 4 +- .../device_4x4/config/test.openfpga | 53 ++++++++ .../device_4x4/config/test.py | 120 ++++++++++++++++++ 8 files changed, 200 insertions(+), 107 deletions(-) delete mode 100644 openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml delete mode 100644 openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga rename openfpga_flow/tasks/fpga_bitstream/{generate_bitstream/configuration_chain/device_4x4_PathBitSetting => overwrite_bitstream/device_4x4}/config/task.conf (83%) create mode 100644 openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga create mode 100644 openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 23bbed0ae4..543a81af6e 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -105,16 +105,18 @@ static void read_xml_non_fabric_bitstream_setting( /******************************************************************** * Parse XML description for a bit setting under a XML node *******************************************************************/ -static void read_xml_bit_setting( - pugi::xml_node& xml_bit, const pugiutil::loc_data& loc_data, +static void read_xml_overwrite_bit_setting( + pugi::xml_node& xml_overwrite_bitstream, const pugiutil::loc_data& loc_data, openfpga::BitstreamSetting& bitstream_setting) { - 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(); - VTR_ASSERT_SAFE(value_attr == "0" || value_attr == "1"); - /* Add to bit */ - bitstream_setting.add_path_bit_setting(path_attr, value_attr == "1"); + for (pugi::xml_node xml_bit : xml_overwrite_bitstream.children()) { + 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(); + VTR_ASSERT(value_attr == "0" || value_attr == "1"); + /* Add to bit */ + bitstream_setting.add_path_bit_setting(path_attr, value_attr == "1"); + } } /******************************************************************** @@ -132,9 +134,9 @@ openfpga::BitstreamSetting read_xml_bitstream_setting( 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("bit"))) { + (xml_child.name() != std::string("overwrite_bitstream"))) { bad_tag(xml_child, loc_data, Node, - {"pb_type | interconnect | non_fabric | bit"}); + {"pb_type | interconnect | non_fabric | overwrite_bitstream"}); } if (xml_child.name() == std::string("pb_type")) { @@ -147,8 +149,8 @@ openfpga::BitstreamSetting read_xml_bitstream_setting( read_xml_non_fabric_bitstream_setting(xml_child, loc_data, bitstream_setting); } else { - VTR_ASSERT_SAFE(xml_child.name() == std::string("bit")); - read_xml_bit_setting(xml_child, loc_data, bitstream_setting); + VTR_ASSERT_SAFE(xml_child.name() == std::string("overwrite_bitstream")); + read_xml_overwrite_bit_setting(xml_child, loc_data, bitstream_setting); } } diff --git a/openfpga/src/base/openfpga_basic.cpp b/openfpga/src/base/openfpga_basic.cpp index 240caaa6f8..b3a705c895 100644 --- a/openfpga/src/base/openfpga_basic.cpp +++ b/openfpga/src/base/openfpga_basic.cpp @@ -68,8 +68,14 @@ int call_external_command(const Command& cmd, VTR_LOG("Processer is not available"); return CMD_EXEC_FATAL_ERROR; } - - return system(cmd_ss.c_str()); + + int status = system(cmd_ss.c_str()); + if (status & 0xFF) { + // First 8 bits are system signals + return 1; + } + // real return was actually shifted 8 bits + return status >> 8; } } /* end namespace openfpga */ diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index d6ba24549a..8fc5e022c3 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -15,8 +15,8 @@ echo -e "Testing bitstream generation for an 48x48 FPGA device"; run-task fpga_bitstream/generate_bitstream/configuration_chain/device_48x48 $@ run-task fpga_bitstream/generate_bitstream/ql_memory_bank_shift_register/device_48x48 $@ -echo -e "Testing bitstream generation for an 4x4 FPGA device (overwrite IO tile bits)"; -run-task fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting $@ +echo -e "Testing bitstream generation for an 4x4 FPGA device (randomly overwrite fabric bits)"; +run-task fpga_bitstream/overwrite_bitstream/device_4x4 $@ echo -e "Testing bitstream generation for an 96x96 FPGA device"; run-task fpga_bitstream/generate_bitstream/configuration_chain/device_96x96 $@ diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml deleted file mode 100644 index 24b5fa8f65..0000000000 --- a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga deleted file mode 100644 index 81abe263fb..0000000000 --- a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga +++ /dev/null @@ -1,79 +0,0 @@ -# This file is copied from fix_device_example_script.openfpga - -# Run VPR for the 'and' design -#--write_rr_graph example_rr_graph.xml -vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --device ${OPENFPGA_VPR_DEVICE_LAYOUT} - -# Read OpenFPGA architecture definition -read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} - -# Read OpenFPGA simulation settings -read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} - -# Read OpenFPGA bitstream settings -read_openfpga_bitstream_setting -f ${OPENFPGA_BITSTREAM_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 Look-Up Table truth tables based on packing results -lut_truth_table_fixup - -# Build the module graph -# - Enabled compression on routing architecture modules -# - Enable pin duplication on grid modules -build_fabric --compress_routing #--verbose - -# Write the fabric hierarchy of module graph to a file -# This is used by hierarchical PnR flows -write_fabric_hierarchy --file ./fabric_hierarchy.txt - -# 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_independent_bitstream.xml - -# Build fabric-dependent bitstream -build_fabric_bitstream --verbose - -# Write fabric-dependent bitstream -write_fabric_bitstream --file fabric_bitstream.bit --format plain_text -write_fabric_bitstream --file fabric_bitstream.xml --format xml - -# Write the Verilog netlist for FPGA fabric -# - Enable the use of explicit port mapping in Verilog netlist -write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose - -# Write the Verilog testbench for FPGA fabric -# - We suggest the use of same output directory as fabric Verilog netlists -# - Must specify the reference benchmark file if you want to output any testbenches -# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA -# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase -# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts -write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit -write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping -write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping - -# Write the SDC files for PnR backend -# - Turn on every options here -write_pnr_sdc --file ./SDC - -# Write SDC to disable timing for configure ports -write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc - -# Write the SDC to run timing analysis for a mapped FPGA fabric -write_analysis_sdc --file ./SDC_analysis - -# Finish and exit OpenFPGA -exit - -# Note : -# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/task.conf similarity index 83% rename from openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/task.conf rename to openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/task.conf index eb36a69e6d..76ff7c2511 100644 --- a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/task.conf +++ b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/task.conf @@ -16,10 +16,10 @@ timeout_each_job = 20*60 fpga_flow=vpr_blif [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/write_xml.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml -openfpga_bitstream_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/configuration_chain/device_4x4_PathBitSetting/config/bitstream_annotation.xml +openfpga_bitstream_setting_file=bitstream_annotation.xml openfpga_vpr_device_layout=4x4 [ARCHITECTURES] diff --git a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga new file mode 100644 index 0000000000..5ae9f514e3 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga @@ -0,0 +1,53 @@ +# This file is copied from fix_device_example_script.openfpga + +ext_exec --command "python3 ../../../../config/test.py run_golden" + +ext_exec --command "python3 ../../../../config/test.py generate_testcase" + +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --device ${OPENFPGA_VPR_DEVICE_LAYOUT} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Read OpenFPGA bitstream settings +read_openfpga_bitstream_setting -f ${OPENFPGA_BITSTREAM_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 Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--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 + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.xml --format xml + +ext_exec --command "python3 ../../../../config/test.py validate" + +# Finish and exit OpenFPGA +exit diff --git a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py new file mode 100644 index 0000000000..5a5a002856 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py @@ -0,0 +1,120 @@ +import xml.etree.ElementTree as ET +import sys +import shutil +import os +import random + +random.seed() +assert len(sys.argv) >= 2 +assert sys.argv[1] in ["run_golden", "generate_testcase", "validate"] +TEST_BIT_COUNT = 200 + +def read_fabric_bitstream_xml(file) : + + bit_count = 0 + tree = ET.parse(file) + root = tree.getroot() + assert root.tag == "fabric_bitstream", "Root tag is not 'fabric_bitstream', but '%s'" % root.tag + for region in root : + assert region.tag == "region", "fabric_bitstream child node tag is not 'region', but '%s'" % region.tag + for bit in region : + assert bit.tag == "bit", "region child node tag is not 'bit', but '%s'" % bit.tag + assert "path" in bit.attrib, "Attribute 'path' does not exist in bit node" + assert "value" in bit.attrib, "Attribute 'value' does not exist in bit node" + assert bit.attrib["value"] in ["0", "1"] + bit_count += 1 + return [tree, bit_count] + +def read_bitstream_annotation_xml(file) : + + xml = {} + tree = ET.parse(file) + root = tree.getroot() + assert root.tag == "openfpga_bitstream_setting", "Root tag is not 'openfpga_bitstream_setting', but '%s'" % root.tag + for overwrite_bitstream in root : + assert overwrite_bitstream.tag == "overwrite_bitstream", "openfpga_bitstream_setting child node tag is not 'overwrite_bitstream', but '%s'" % overwrite_bitstream.tag + for bit in overwrite_bitstream : + assert bit.tag == "bit", "overwrite_bitstream child node tag is not 'bit', but '%s'" % bit.tag + assert "path" in bit.attrib, "Attribute 'path' does not exist in bit node" + assert "value" in bit.attrib, "Attribute 'value' does not exist in bit node" + path = bit.attrib["path"] + assert path not in xml + index = path.rfind("[") + assert index != -1 + path = "%s.mem_out%s" % (path[:index], path[index:]) + assert path not in xml + assert bit.attrib["value"] in ["0", "1"] + xml[path] = bit.attrib["value"] + return xml + +if sys.argv[1] == "run_golden" : + + openfpga_exe = os.path.abspath("../../../../../../../../../build/openfpga/openfpga") + assert os.path.exists(openfpga_exe) + shutil.rmtree("golden", ignore_errors=True) + os.mkdir("golden") + original_openfpga = open("and2_run.openfpga") + golden_openfpga = open("golden/and2_run.openfpga", "w") + for line in original_openfpga : + if line.find("ext_exec") == 0 : + pass + else : + golden_openfpga.write(line) + golden_openfpga.close() + original_openfpga.close() + bitstream_annotation = open("golden/bitstream_annotation.xml", "w") + bitstream_annotation.write("\n") + bitstream_annotation.close() + shutil.copyfile("and2.blif", "golden/and2.blif") + shutil.copyfile("and2_ace_out.act", "golden/and2_ace_out.act") + cmd = "cd golden && %s -batch -f and2_run.openfpga > golden.log" % (openfpga_exe) + assert os.system(cmd) == 0 + +elif sys.argv[1] == "generate_testcase" : + + (tree, bit_count) = read_fabric_bitstream_xml("golden/fabric_bitstream.xml") + random_bits = [] + while len(random_bits) != TEST_BIT_COUNT : + bit = random.randint(0, bit_count - 1) + if bit not in random_bits : + random_bits.append(bit) + bitstream_annotation = open("bitstream_annotation.xml", "w") + bitstream_annotation.write("\n") + bitstream_annotation.write(" \n") + index = 0 + for region in tree.getroot() : + for bit in region : + if index in random_bits : + path = bit.attrib["path"] + value = bit.attrib["value"] + assert value in ["0", "1"] + path = path.replace(".mem_out[", "[") + bitstream_annotation.write(" \n" % ("1" if value == "0" else "0", path)) + index += 1 + bitstream_annotation.write(" \n") + bitstream_annotation.write("\n") + bitstream_annotation.close() + +else : + + gtree = ET.parse("golden/fabric_bitstream.xml") + tree = ET.parse("fabric_bitstream.xml") + bitstream_annotation = read_bitstream_annotation_xml("bitstream_annotation.xml") + status = 0 + checked_count = 0 + for gregion, region in zip(gtree.getroot(), tree.getroot()) : + for gbit, bit in zip(gregion, region) : + assert bit.attrib["path"] == gbit.attrib["path"] + path = bit.attrib["path"] + if path in bitstream_annotation : + # This is something we want to overwrite, hence the value should + # Same in the annotation file + # Not same in golden fabric + assert bit.attrib["value"] != gbit.attrib["value"] + assert bit.attrib["value"] == bitstream_annotation[path] + else : + # This is not what we want to overwrite + # Hence the value should same in golden fabric + assert bit.attrib["value"] == gbit.attrib["value"] + +exit(0) From cbe9a46f95094dd3f0b6842685f9a83c8d4e08a6 Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Sun, 28 Jul 2024 00:02:20 -0700 Subject: [PATCH 12/19] Format and update doc --- .../manual/file_formats/bitstream_setting.rst | 14 ++++++++++---- openfpga/src/base/openfpga_basic.cpp | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/source/manual/file_formats/bitstream_setting.rst b/docs/source/manual/file_formats/bitstream_setting.rst index d18614b7e7..e5dfbf40c7 100644 --- a/docs/source/manual/file_formats/bitstream_setting.rst +++ b/docs/source/manual/file_formats/bitstream_setting.rst @@ -16,7 +16,9 @@ This can define a hard-coded bitstream for a reconfigurable resource in FPGA fab - + + + pb_type-related Settings @@ -117,12 +119,16 @@ The following syntax are applicable to the XML definition tagged by ``non_fabric 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``. -bit-related Settings +overwrite_bitstream-related Settings ^^^^^^^^^^^^^^^^^^^^ -This is to allow user to set particular bit using full path in the hierarchy of FPGA fabric +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 -The following syntax are applicable to the XML definition tagged by ``bit`` in bitstream setting files. +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>" diff --git a/openfpga/src/base/openfpga_basic.cpp b/openfpga/src/base/openfpga_basic.cpp index b3a705c895..ac10f007c5 100644 --- a/openfpga/src/base/openfpga_basic.cpp +++ b/openfpga/src/base/openfpga_basic.cpp @@ -68,7 +68,7 @@ int call_external_command(const Command& cmd, VTR_LOG("Processer is not available"); return CMD_EXEC_FATAL_ERROR; } - + int status = system(cmd_ss.c_str()); if (status & 0xFF) { // First 8 bits are system signals From 2a3d69aded840c54212dd9652670ab54e9ab1222 Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Sun, 28 Jul 2024 02:37:15 -0700 Subject: [PATCH 13/19] Update code based on feedback --- .../libarchopenfpga/src/bitstream_setting.cpp | 43 ++++++++++++++++--- libs/libarchopenfpga/src/bitstream_setting.h | 23 ++++++---- .../src/bitstream_setting_fwd.h | 2 + .../src/read_xml_bitstream_setting.cpp | 11 +++-- .../src/bitstream_manager.cpp | 28 ++++++------ libs/libfpgabitstream/src/bitstream_manager.h | 2 +- .../src/bitstream_manager_utils.cpp | 17 -------- .../src/bitstream_manager_utils.h | 2 - .../src/base/openfpga_bitstream_template.h | 5 +++ .../fpga_bitstream/build_device_bitstream.cpp | 5 --- .../fpga_bitstream/overwrite_bitstream.cpp | 38 ++++++++++++++++ .../src/fpga_bitstream/overwrite_bitstream.h | 23 ++++++++++ 12 files changed, 144 insertions(+), 55 deletions(-) create mode 100644 openfpga/src/fpga_bitstream/overwrite_bitstream.cpp create mode 100644 openfpga/src/fpga_bitstream/overwrite_bitstream.h diff --git a/libs/libarchopenfpga/src/bitstream_setting.cpp b/libs/libarchopenfpga/src/bitstream_setting.cpp index e3cc3f697b..6092bd91e1 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/bitstream_setting.cpp @@ -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 ***********************************************************************/ @@ -106,8 +112,16 @@ std::vector BitstreamSetting::non_fabric() const { return non_fabric_; } -std::vector BitstreamSetting::path_bit_settings() const { - return path_bit_settings_; +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]; } /************************************************************************ @@ -182,10 +196,19 @@ void BitstreamSetting::add_non_fabric_pb(const std::string& pb, } } -void BitstreamSetting::add_path_bit_setting(const std::string& path, - const bool value) { +OverwriteBitstreamId BitstreamSetting::add_overwrite_bitstream( + const std::string& path, const bool& value) { VTR_ASSERT(path.size()); - path_bit_settings_.push_back(PathBitSetting(path, value)); + 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; } /************************************************************************ @@ -204,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 diff --git a/libs/libarchopenfpga/src/bitstream_setting.h b/libs/libarchopenfpga/src/bitstream_setting.h index dc70c7b14c..042e850e01 100644 --- a/libs/libarchopenfpga/src/bitstream_setting.h +++ b/libs/libarchopenfpga/src/bitstream_setting.h @@ -37,12 +37,6 @@ struct NonFabricBitstreamSetting { std::vector pbs; }; -struct PathBitSetting { - PathBitSetting(const std::string& p, bool v) : path(p), value(v) {} - const std::string path = ""; - const bool value = false; -}; - /******************************************************************** * A data structure to describe bitstream settings * @@ -67,11 +61,15 @@ class BitstreamSetting { typedef vtr::vector::const_iterator bitstream_interconnect_setting_iterator; + typedef vtr::vector::const_iterator + overwrite_bitstream_iterator; /* Create range */ typedef vtr::Range bitstream_pb_type_setting_range; typedef vtr::Range bitstream_interconnect_setting_range; + typedef vtr::Range overwrite_bitstream_range; public: /* Constructors */ BitstreamSetting(); @@ -79,6 +77,7 @@ class 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( @@ -104,7 +103,8 @@ class BitstreamSetting { std::string default_path( const BitstreamInterconnectSettingId& interconnect_setting_id) const; std::vector non_fabric() const; - std::vector path_bit_settings() 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( @@ -127,13 +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); - void add_path_bit_setting(const std::string& path, const bool value); + 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 @@ -171,7 +173,10 @@ class BitstreamSetting { vtr::vector interconnect_default_paths_; std::vector non_fabric_; - std::vector path_bit_settings_; + vtr::vector + overwrite_bitstream_ids_; + vtr::vector overwrite_bitstream_paths_; + vtr::vector overwrite_bitstream_values_; }; } // namespace openfpga diff --git a/libs/libarchopenfpga/src/bitstream_setting_fwd.h b/libs/libarchopenfpga/src/bitstream_setting_fwd.h index bc5c2ab880..dbcc705531 100644 --- a/libs/libarchopenfpga/src/bitstream_setting_fwd.h +++ b/libs/libarchopenfpga/src/bitstream_setting_fwd.h @@ -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 BitstreamPbTypeSettingId; typedef vtr::StrongId BitstreamInterconnectSettingId; +typedef vtr::StrongId OverwriteBitstreamId; /* Short declaration of class */ class BitstreamSetting; diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 543a81af6e..9552127d65 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -105,17 +105,21 @@ static void read_xml_non_fabric_bitstream_setting( /******************************************************************** * Parse XML description for a bit setting under a XML node *******************************************************************/ -static void read_xml_overwrite_bit_setting( +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(); VTR_ASSERT(value_attr == "0" || value_attr == "1"); /* Add to bit */ - bitstream_setting.add_path_bit_setting(path_attr, value_attr == "1"); + bitstream_setting.add_overwrite_bitstream(path_attr, value_attr == "1"); } } @@ -150,7 +154,8 @@ openfpga::BitstreamSetting read_xml_bitstream_setting( bitstream_setting); } else { VTR_ASSERT_SAFE(xml_child.name() == std::string("overwrite_bitstream")); - read_xml_overwrite_bit_setting(xml_child, loc_data, bitstream_setting); + read_xml_overwrite_bitstream_setting(xml_child, loc_data, + bitstream_setting); } } diff --git a/libs/libfpgabitstream/src/bitstream_manager.cpp b/libs/libfpgabitstream/src/bitstream_manager.cpp index 673e28c9d0..71aa36ffbc 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager.cpp @@ -6,6 +6,7 @@ #include #include "bitstream_manager_utils.h" +#include "openfpga_tokenizer.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -297,25 +298,27 @@ void BitstreamManager::add_output_net_id_to_block( block_output_net_ids_[block] = output_net_id; } -void BitstreamManager::set_path_bit(const std::string& path, const bool value) { +void BitstreamManager::overwrite_bitstream(const std::string& path, + const bool& value) { ConfigBlockId block; - std::vector blocks = - reverse_split_bit_path_to_blocks((std::string)(path)); - std::string block_name = ""; + StringToken tokenizer(path); + std::vector blocks = tokenizer.split("."); + std::reverse(blocks.begin(), blocks.end()); + std::string current_block_name = ""; bool match = false; for (size_t i = 0; i < bit_values_.size() && !match; i++) { block = bit_parent_blocks_[ConfigBitId(i)]; - if (size_t(block) < num_blocks_) { + if (valid_block_id(block)) { size_t index = find_bitstream_manager_config_bit_index_in_parent_block( *this, ConfigBitId(i)); - block_name = block_names_[block] + ("[" + std::to_string(index) + "]"); - if (block_name == blocks[0]) { + current_block_name = + block_name(block) + ("[" + std::to_string(index) + "]"); + if (current_block_name == blocks[0]) { match = true; for (size_t b = 1; b < blocks.size() && match; b++) { - valid_block_id(block); - block = parent_block_ids_[block]; - if (size_t(block) < num_blocks_) { - if (block_names_[block] != blocks[b]) { + block = block_parent(block); + if (valid_block_id(block)) { + if (block_name(block) != blocks[b]) { match = false; } } else { @@ -323,8 +326,7 @@ void BitstreamManager::set_path_bit(const std::string& path, const bool value) { } } if (match) { - valid_block_id(block); - if (parent_block_ids_[block] == ConfigBlockId::INVALID()) { + if (!valid_block_id(block_parent(block))) { bit_values_[ConfigBitId(i)] = value ? '1' : '0'; } else { match = false; diff --git a/libs/libfpgabitstream/src/bitstream_manager.h b/libs/libfpgabitstream/src/bitstream_manager.h index daaccbd7f2..3cba54fc45 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.h +++ b/libs/libfpgabitstream/src/bitstream_manager.h @@ -214,7 +214,7 @@ class BitstreamManager { const std::string& output_net_id); /* Set bit to the bitstream at the given path */ - void set_path_bit(const std::string& path, const bool value); + void overwrite_bitstream(const std::string& path, const bool& value); public: /* Public Validators */ bool valid_bit_id(const ConfigBitId& bit_id) const; diff --git a/libs/libfpgabitstream/src/bitstream_manager_utils.cpp b/libs/libfpgabitstream/src/bitstream_manager_utils.cpp index c9bff9b396..13ef85bbdc 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_utils.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager_utils.cpp @@ -130,21 +130,4 @@ size_t rec_find_bitstream_manager_block_sum_of_bits( return sum_of_bits; } -/******************************************************************** - * Split the bit path with delimiter ".". The blocks is reversed - *******************************************************************/ -std::vector reverse_split_bit_path_to_blocks(std::string path) { - std::vector blocks; - size_t index = path.find_first_of("."); - while (index != std::string::npos) { - blocks.insert(blocks.begin(), path.substr(0, index)); - path = path.substr(index + 1); - index = path.find_first_of("."); - } - if (path.size()) { - blocks.insert(blocks.begin(), path); - } - return blocks; -} - } /* end namespace openfpga */ diff --git a/libs/libfpgabitstream/src/bitstream_manager_utils.h b/libs/libfpgabitstream/src/bitstream_manager_utils.h index ff24b961d8..26d6f35b89 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_utils.h +++ b/libs/libfpgabitstream/src/bitstream_manager_utils.h @@ -31,8 +31,6 @@ size_t find_bitstream_manager_config_bit_index_in_grandparent_block( size_t rec_find_bitstream_manager_block_sum_of_bits( const BitstreamManager& bitstream_manager, const ConfigBlockId& block); -std::vector reverse_split_bit_path_to_blocks(std::string path); - } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_bitstream_template.h b/openfpga/src/base/openfpga_bitstream_template.h index c132e907f7..af5bf1ae7c 100644 --- a/openfpga/src/base/openfpga_bitstream_template.h +++ b/openfpga/src/base/openfpga_bitstream_template.h @@ -16,6 +16,7 @@ #include "openfpga_digest.h" #include "openfpga_naming.h" #include "openfpga_reserved_words.h" +#include "overwrite_bitstream.h" #include "read_xml_arch_bitstream.h" #include "report_bitstream_distribution.h" #include "vtr_log.h" @@ -47,6 +48,10 @@ int fpga_bitstream_template(T& openfpga_ctx, const Command& cmd, g_vpr_ctx, openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); } + overwrite_bitstream(openfpga_ctx.mutable_bitstream_manager(), + openfpga_ctx.bitstream_setting(), + cmd_context.option_enable(cmd, opt_verbose)); + if (true == cmd_context.option_enable(cmd, opt_write_file)) { std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_write_file)); diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index b832d927bc..a3fb264321 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -231,11 +231,6 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, vpr_ctx.device().rr_graph, openfpga_ctx.device_rr_gsb(), openfpga_ctx.flow_manager().compress_routing(), verbose); - /* Apply path bit value */ - for (auto bit : openfpga_ctx.bitstream_setting().path_bit_settings()) { - bitstream_manager.set_path_bit(bit.path, bit.value); - } - VTR_LOGV(verbose, "Done\n"); VTR_LOGV(verbose, "Decoded %lu configuration bits into %lu blocks\n", diff --git a/openfpga/src/fpga_bitstream/overwrite_bitstream.cpp b/openfpga/src/fpga_bitstream/overwrite_bitstream.cpp new file mode 100644 index 0000000000..e25d63e94f --- /dev/null +++ b/openfpga/src/fpga_bitstream/overwrite_bitstream.cpp @@ -0,0 +1,38 @@ +/******************************************************************** + * This file includes functions to build bitstream from a mapped + * FPGA fabric. + * We decode the bitstream from configuration of routing multiplexers + * and Look-Up Tables (LUTs) which locate in CLBs and global routing + *architecture + *******************************************************************/ + +/* Headers from vtrutil library */ +#include "overwrite_bitstream.h" + +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Overwrite bitstream retrieve from bitstream annotation XML which stored in + *BitstreamSetting + *******************************************************************/ +void overwrite_bitstream(openfpga::BitstreamManager& bitstream_manager, + const openfpga::BitstreamSetting& bitstream_setting, + const bool& verbose) { + vtr::ScopedStartFinishTimer timer("\nOverwrite Bitstream\n"); + + /* Apply overwrite_bitstream bit's path and value */ + for (auto& id : bitstream_setting.overwrite_bitstreams()) { + std::string path = bitstream_setting.overwrite_bitstream_path(id); + bool value = bitstream_setting.overwrite_bitstream_value(id); + VTR_LOGV(verbose, "Overwrite bitstream path='%s' to value='%d'\n", + path.c_str(), value); + bitstream_manager.overwrite_bitstream(path, value); + } +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/overwrite_bitstream.h b/openfpga/src/fpga_bitstream/overwrite_bitstream.h new file mode 100644 index 0000000000..de142232b1 --- /dev/null +++ b/openfpga/src/fpga_bitstream/overwrite_bitstream.h @@ -0,0 +1,23 @@ +#ifndef OVERWRITE_BITSTREAM_H +#define OVERWRITE_BITSTREAM_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include "openfpga_context.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void overwrite_bitstream(openfpga::BitstreamManager& bitstream_manager, + const openfpga::BitstreamSetting& bitstream_setting, + const bool& verbose); + +} /* end namespace openfpga */ + +#endif From 22d7df5ffb981de3fb7b4e8ff8ac8ce0f5f2152d Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Sun, 28 Jul 2024 02:40:24 -0700 Subject: [PATCH 14/19] Update doc --- docs/source/manual/file_formats/bitstream_setting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/manual/file_formats/bitstream_setting.rst b/docs/source/manual/file_formats/bitstream_setting.rst index e5dfbf40c7..d46751a146 100644 --- a/docs/source/manual/file_formats/bitstream_setting.rst +++ b/docs/source/manual/file_formats/bitstream_setting.rst @@ -120,7 +120,7 @@ The following syntax are applicable to the XML definition tagged by ``non_fabric 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 From 9882394c8bb2b7a05f168de9a8b080c22e665183 Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Sun, 28 Jul 2024 02:53:18 -0700 Subject: [PATCH 15/19] Use archfpga_throw --- libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 9552127d65..49b76e0b16 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -117,7 +117,10 @@ static void read_xml_overwrite_bitstream_setting( get_attribute(xml_bit, "path", loc_data).as_string(); const std::string& value_attr = get_attribute(xml_bit, "value", loc_data).as_string(); - VTR_ASSERT(value_attr == "0" || value_attr == "1"); + 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"); + } /* Add to bit */ bitstream_setting.add_overwrite_bitstream(path_attr, value_attr == "1"); } From 0d9f1a3c6bd849c62d19b132949106f8ce8d9fd2 Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Sun, 28 Jul 2024 19:12:34 -0700 Subject: [PATCH 16/19] Forward searching the config bit + some minor refactor --- .../src/read_xml_bitstream_setting.cpp | 2 +- .../src/bitstream_manager.cpp | 91 +++++++++++++------ openfpga/src/base/openfpga_basic.cpp | 16 +++- .../device_4x4/config/test.py | 1 - 4 files changed, 75 insertions(+), 35 deletions(-) diff --git a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp index 49b76e0b16..244703fc14 100644 --- a/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp +++ b/libs/libarchopenfpga/src/read_xml_bitstream_setting.cpp @@ -119,7 +119,7 @@ static void read_xml_overwrite_bitstream_setting( 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"); + "Invalid value of overwrite_bitstream bit. Expect [0|1]"); } /* Add to bit */ bitstream_setting.add_overwrite_bitstream(path_attr, value_attr == "1"); diff --git a/libs/libfpgabitstream/src/bitstream_manager.cpp b/libs/libfpgabitstream/src/bitstream_manager.cpp index 71aa36ffbc..39c3515b35 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager.cpp @@ -5,6 +5,7 @@ #include +#include "arch_error.h" #include "bitstream_manager_utils.h" #include "openfpga_tokenizer.h" #include "vtr_assert.h" @@ -300,40 +301,74 @@ void BitstreamManager::add_output_net_id_to_block( void BitstreamManager::overwrite_bitstream(const std::string& path, const bool& value) { - ConfigBlockId block; - StringToken tokenizer(path); - std::vector blocks = tokenizer.split("."); - std::reverse(blocks.begin(), blocks.end()); - std::string current_block_name = ""; - bool match = false; - for (size_t i = 0; i < bit_values_.size() && !match; i++) { - block = bit_parent_blocks_[ConfigBitId(i)]; - if (valid_block_id(block)) { - size_t index = find_bitstream_manager_config_bit_index_in_parent_block( - *this, ConfigBitId(i)); - current_block_name = - block_name(block) + ("[" + std::to_string(index) + "]"); - if (current_block_name == blocks[0]) { - match = true; - for (size_t b = 1; b < blocks.size() && match; b++) { - block = block_parent(block); - if (valid_block_id(block)) { - if (block_name(block) != blocks[b]) { - match = false; - } - } else { - match = false; - } + bool bad_format = true; + size_t index = path.rfind("["); + std::string bit_string = ""; + if (index != std::string::npos && path[path.size() - 1] == ']') { + bit_string = path.substr(index + 1, path.size() - index - 2); + bad_format = bit_string.size() == 0; + auto iter = bit_string.begin(); + while (!bad_format && iter != bit_string.end()) { + bad_format = !std::isdigit(*iter); + iter++; + } + } + if (bad_format) { + archfpga_throw(__FILE__, __LINE__, + "overwrite_bitstream bit path '%s' does not match format " + "[bit index]", + path.c_str()); + } else { + size_t bit = (size_t)(std::stoi(bit_string)); + StringToken tokenizer(path.substr(0, index)); + std::vector blocks = tokenizer.split("."); + std::vector 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 (match) { - if (!valid_block_id(block_parent(block))) { - bit_values_[ConfigBitId(i)] = value ? '1' : '0'; + } + 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 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 { - match = false; + // 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()); + } } } diff --git a/openfpga/src/base/openfpga_basic.cpp b/openfpga/src/base/openfpga_basic.cpp index ac10f007c5..6546ff9098 100644 --- a/openfpga/src/base/openfpga_basic.cpp +++ b/openfpga/src/base/openfpga_basic.cpp @@ -69,13 +69,19 @@ int call_external_command(const Command& cmd, return CMD_EXEC_FATAL_ERROR; } + // Refer https://pubs.opengroup.org/onlinepubs/009695399/functions/system.html + // Refer + // https://pubs.opengroup.org/onlinepubs/009695399/functions/waitpid.html int status = system(cmd_ss.c_str()); - if (status & 0xFF) { - // First 8 bits are system signals - return 1; + if (WIFEXITED(status)) { + // This is normal program exit, WEXITSTATUS() will help you shift the status + // accordingly (status >> 8) + // Becareful if the final status is 2 or beyond, program will not error + // as it is treated as CMD_EXEC_MINOR_ERROR + return WEXITSTATUS(status); } - // real return was actually shifted 8 bits - return status >> 8; + // Program maybe terminated because of various killed or stopped signal + return CMD_EXEC_FATAL_ERROR; } } /* end namespace openfpga */ diff --git a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py index 5a5a002856..07d96a7da5 100644 --- a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py +++ b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py @@ -100,7 +100,6 @@ def read_bitstream_annotation_xml(file) : gtree = ET.parse("golden/fabric_bitstream.xml") tree = ET.parse("fabric_bitstream.xml") bitstream_annotation = read_bitstream_annotation_xml("bitstream_annotation.xml") - status = 0 checked_count = 0 for gregion, region in zip(gtree.getroot(), tree.getroot()) : for gbit, bit in zip(gregion, region) : From 3e3f089823b0ca12b97b67e0e77379ffaf404a1e Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Sun, 28 Jul 2024 19:24:48 -0700 Subject: [PATCH 17/19] Get the filepath using definition under [OpenFPGA_SHELL] --- .../overwrite_bitstream/device_4x4/config/task.conf | 1 + .../overwrite_bitstream/device_4x4/config/test.openfpga | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/task.conf index 76ff7c2511..67a1e028c1 100644 --- a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/task.conf +++ b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/task.conf @@ -21,6 +21,7 @@ openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10 openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_bitstream_setting_file=bitstream_annotation.xml openfpga_vpr_device_layout=4x4 +openfpga_ext_exec_python_script=${PATH:TASK_DIR}/config/test.py [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_thru_channel_adder_chain_wide_mem16K_40nm.xml diff --git a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga index 5ae9f514e3..ea3aa90b8a 100644 --- a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga +++ b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga @@ -1,8 +1,8 @@ -# This file is copied from fix_device_example_script.openfpga +# Majority of the content refer to fix_device_example_script.openfpga -ext_exec --command "python3 ../../../../config/test.py run_golden" +ext_exec --command "python3 ${OPENFPGA_EXT_EXEC_PYTHON_SCRIPT} run_golden" -ext_exec --command "python3 ../../../../config/test.py generate_testcase" +ext_exec --command "python3 ${OPENFPGA_EXT_EXEC_PYTHON_SCRIPT} generate_testcase" # Run VPR for the 'and' design #--write_rr_graph example_rr_graph.xml @@ -47,7 +47,7 @@ build_fabric_bitstream --verbose # Write fabric-dependent bitstream write_fabric_bitstream --file fabric_bitstream.xml --format xml -ext_exec --command "python3 ../../../../config/test.py validate" +ext_exec --command "python3 ${OPENFPGA_EXT_EXEC_PYTHON_SCRIPT} validate" # Finish and exit OpenFPGA exit From ca48841ae354eb561f909e49b980bfc54a7a26c4 Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Mon, 29 Jul 2024 11:04:03 -0700 Subject: [PATCH 18/19] Pass in the OpenFPGA root dir --- .../overwrite_bitstream/device_4x4/config/test.openfpga | 2 +- .../overwrite_bitstream/device_4x4/config/test.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga index ea3aa90b8a..1e9e3f79c5 100644 --- a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga +++ b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.openfpga @@ -1,6 +1,6 @@ # Majority of the content refer to fix_device_example_script.openfpga -ext_exec --command "python3 ${OPENFPGA_EXT_EXEC_PYTHON_SCRIPT} run_golden" +ext_exec --command "python3 ${OPENFPGA_EXT_EXEC_PYTHON_SCRIPT} run_golden ${OPENFPGA_PATH}" ext_exec --command "python3 ${OPENFPGA_EXT_EXEC_PYTHON_SCRIPT} generate_testcase" diff --git a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py index 07d96a7da5..2997bb5d6d 100644 --- a/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py +++ b/openfpga_flow/tasks/fpga_bitstream/overwrite_bitstream/device_4x4/config/test.py @@ -49,7 +49,8 @@ def read_bitstream_annotation_xml(file) : if sys.argv[1] == "run_golden" : - openfpga_exe = os.path.abspath("../../../../../../../../../build/openfpga/openfpga") + assert len(sys.argv) >= 3 + openfpga_exe = os.path.abspath("%s/build/openfpga/openfpga" % sys.argv[2]) assert os.path.exists(openfpga_exe) shutil.rmtree("golden", ignore_errors=True) os.mkdir("golden") From 766df0a1b5bae0af7342c55850be9b62fe7d051a Mon Sep 17 00:00:00 2001 From: chungshien-chai Date: Wed, 31 Jul 2024 12:19:30 -0700 Subject: [PATCH 19/19] Improve Port Parser --- .../src/bitstream_manager.cpp | 21 +++----- .../src/openfpga_port_parser.cpp | 50 +++++++++++++++++-- .../src/openfpga_port_parser.h | 26 +++++++--- 3 files changed, 71 insertions(+), 26 deletions(-) diff --git a/libs/libfpgabitstream/src/bitstream_manager.cpp b/libs/libfpgabitstream/src/bitstream_manager.cpp index 39c3515b35..291befb60c 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager.cpp @@ -7,6 +7,7 @@ #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" @@ -301,26 +302,16 @@ void BitstreamManager::add_output_net_id_to_block( void BitstreamManager::overwrite_bitstream(const std::string& path, const bool& value) { - bool bad_format = true; - size_t index = path.rfind("["); - std::string bit_string = ""; - if (index != std::string::npos && path[path.size() - 1] == ']') { - bit_string = path.substr(index + 1, path.size() - index - 2); - bad_format = bit_string.size() == 0; - auto iter = bit_string.begin(); - while (!bad_format && iter != bit_string.end()) { - bad_format = !std::isdigit(*iter); - iter++; - } - } - if (bad_format) { + 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 " "[bit index]", path.c_str()); } else { - size_t bit = (size_t)(std::stoi(bit_string)); - StringToken tokenizer(path.substr(0, index)); + BasicPort port = port_parser.port(); + size_t bit = port.get_lsb(); + StringToken tokenizer(port.get_name()); std::vector blocks = tokenizer.split("."); std::vector block_ids; ConfigBlockId block_id = ConfigBlockId::INVALID(); diff --git a/libs/libopenfpgautil/src/openfpga_port_parser.cpp b/libs/libopenfpgautil/src/openfpga_port_parser.cpp index 93b7e08990..da0a273683 100644 --- a/libs/libopenfpgautil/src/openfpga_port_parser.cpp +++ b/libs/libopenfpgautil/src/openfpga_port_parser.cpp @@ -5,6 +5,7 @@ #include +#include "arch_error.h" #include "openfpga_tokenizer.h" #include "vtr_assert.h" #include "vtr_geometry.h" @@ -19,9 +20,10 @@ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -PortParser::PortParser(const std::string& data) { +PortParser::PortParser(const std::string& data, const int support_format) { set_default_bracket(); set_default_delim(); + set_support_format(support_format); set_data(data); } @@ -33,9 +35,18 @@ std::string PortParser::data() const { return data_; } BasicPort PortParser::port() const { return port_; } +bool PortParser::valid() const { return valid_; } + /************************************************************************ * Public Mutators ***********************************************************************/ +void PortParser::set_support_format(const int support_format) { + VTR_ASSERT((support_format & PORT_PARSER_SUPPORT_ALL_FORMAT) != 0); + VTR_ASSERT((support_format & ~PORT_PARSER_SUPPORT_ALL_FORMAT) == 0); + support_format_ = support_format; + return; +} + void PortParser::set_data(const std::string& data) { data_ = data; parse(); @@ -47,6 +58,8 @@ void PortParser::set_data(const std::string& data) { ***********************************************************************/ /* Parse the data */ void PortParser::parse() { + valid_ = true; + /* Create a tokenizer */ StringToken tokenizer(data_); @@ -54,11 +67,14 @@ void PortParser::parse() { std::vector port_tokens = tokenizer.split(bracket_.x()); /* Make sure we have a port name! */ VTR_ASSERT_SAFE((1 == port_tokens.size()) || (2 == port_tokens.size())); + /* Store the port name! */ port_.set_name(port_tokens[0]); /* If we only have one token */ if (1 == port_tokens.size()) { + // there is no [ + valid_ = (support_format_ & PORT_PARSER_SUPPORT_NO_PORT_FORMAT) != 0; port_.set_width(1); return; /* We can finish here */ } @@ -72,19 +88,25 @@ void PortParser::parse() { /* Split the pin string now */ tokenizer.set_data(pin_tokens[0]); pin_tokens = tokenizer.split(delim_); + VTR_ASSERT_SAFE((1 == pin_tokens.size()) || (2 == pin_tokens.size())); /* Check if we have LSB and MSB or just one */ if (1 == pin_tokens.size()) { /* Single pin */ - port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[0])); + valid_ = (support_format_ & PORT_PARSER_SUPPORT_SINGLE_INDEX_FORMAT) != 0; + size_t temp = string_to_number(pin_tokens[0]); + port_.set_width(temp, temp); } else if (2 == pin_tokens.size()) { /* A number of pins. * Note that we always use the LSB for token[0] and MSB for token[1] */ - if (std::stoi(pin_tokens[1]) < std::stoi(pin_tokens[0])) { - port_.set_width(std::stoi(pin_tokens[1]), std::stoi(pin_tokens[0])); + valid_ = (support_format_ & PORT_PARSER_SUPPORT_RANGE_FORMAT) != 0; + size_t temp0 = string_to_number(pin_tokens[0]); + size_t temp1 = string_to_number(pin_tokens[1]); + if (temp1 < temp0) { + port_.set_width(temp1, temp0); } else { - port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[1])); + port_.set_width(temp0, temp1); } } @@ -102,6 +124,24 @@ void PortParser::set_default_delim() { return; } +/* + Make sure string is not empty and is all digit before stoi +*/ +size_t PortParser::string_to_number(const std::string& str) { + bool bad_format = str.empty(); + for (auto& chr : str) { + if (!std::isdigit(chr)) { + bad_format = true; + break; + } + } + if (bad_format) { + archfpga_throw(__FILE__, __LINE__, + "Invalid string '%s' to call std::stoi()", str.c_str()); + } + return (size_t)(std::stoi(str)); +} + /************************************************************************ * Member functions for MultiPortParser class ***********************************************************************/ diff --git a/libs/libopenfpgautil/src/openfpga_port_parser.h b/libs/libopenfpgautil/src/openfpga_port_parser.h index f596fd309b..ab61603e0e 100644 --- a/libs/libopenfpgautil/src/openfpga_port_parser.h +++ b/libs/libopenfpgautil/src/openfpga_port_parser.h @@ -21,37 +21,51 @@ /* namespace openfpga begins */ namespace openfpga { +constexpr int PORT_PARSER_SUPPORT_NO_PORT_FORMAT = (1 << 0); // (5) below +constexpr int PORT_PARSER_SUPPORT_SINGLE_INDEX_FORMAT = (1 << 1); // (3) below +constexpr int PORT_PARSER_SUPPORT_RANGE_FORMAT = (1 << 2); // (1) and (2) below +constexpr int PORT_PARSER_SUPPORT_ALL_FORMAT = ((1 << 3) - 1); + /************************************************************************ * Class PortParser: single port parser * Supported port definition: - * 1. [:] - * 2. [:] - * 3. [] - * 4. [] - * 5. + * (1) [:] + * (2) [:] + * (3) [] + * (4) [] -- this is not currently supported. Two problems: + * * tokenizer will error out and + * * stoi cannot support empty string, and give + * std::invalid_argument error + * (5) * In case 4 and 5, we will assign (-1,-1) for LSB and MSB ***********************************************************************/ class PortParser { public: /* Constructors*/ - PortParser(const std::string& data); + PortParser(const std::string& data, + const int support_format = PORT_PARSER_SUPPORT_ALL_FORMAT); public: /* Public Accessors */ std::string data() const; BasicPort port() const; + bool valid() const; public: /* Public Mutators */ + void set_support_format(const int support_format); void set_data(const std::string& data); private: /* Private Mutators */ void parse(); void set_default_bracket(); void set_default_delim(); + size_t string_to_number(const std::string& str); private: /* Internal data */ std::string data_; /* Lines to be splited */ + int support_format_; vtr::Point bracket_; char delim_; BasicPort port_; + bool valid_; }; /************************************************************************