diff --git a/openfpga/src/annotation/annotate_bitstream_setting.cpp b/openfpga/src/annotation/annotate_bitstream_setting.cpp index 48002a08b..a51e73fde 100644 --- a/openfpga/src/annotation/annotate_bitstream_setting.cpp +++ b/openfpga/src/annotation/annotate_bitstream_setting.cpp @@ -12,6 +12,9 @@ #include "vtr_assert.h" #include "vtr_log.h" +/* Headers from openfpgautil library */ +#include "openfpga_tokenizer.h" + #include "pb_type_utils.h" #include "annotate_bitstream_setting.h" @@ -23,9 +26,10 @@ namespace openfpga { * - Find the pb_type and link to the bitstream source * - Find the pb_type and link to the bitstream content *******************************************************************/ -int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, - const DeviceContext& vpr_device_ctx, - VprBitstreamAnnotation& vpr_bitstream_annotation) { +static +int annotate_bitstream_pb_type_setting(const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + VprBitstreamAnnotation& vpr_bitstream_annotation) { for (const auto& bitstream_pb_type_setting_id : bitstream_setting.pb_type_settings()) { /* Get the full name of pb_type */ @@ -95,4 +99,135 @@ int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, return CMD_EXEC_SUCCESS; } +/******************************************************************** + * Annotate bitstream setting based on VPR device information + * - Find the interconnect and link to the default path id + *******************************************************************/ +static +int annotate_bitstream_interconnect_setting(const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, + VprBitstreamAnnotation& vpr_bitstream_annotation) { + + for (const auto& bitstream_interc_setting_id : bitstream_setting.interconnect_settings()) { + /* Get the full name of pb_type */ + std::vector target_pb_type_names; + std::vector target_pb_mode_names; + + target_pb_type_names = bitstream_setting.parent_pb_type_names(bitstream_interc_setting_id); + target_pb_mode_names = bitstream_setting.parent_mode_names(bitstream_interc_setting_id); + /* Kick out the last mode so that we can use an existing function search the pb_type in graph */ + std::string expected_physical_mode_name = target_pb_mode_names.back(); + target_pb_mode_names.pop_back(); + + std::string interconnect_name = bitstream_setting.interconnect_name(bitstream_interc_setting_id); + std::string expected_input_path = bitstream_setting.default_path(bitstream_interc_setting_id); + + /* Pb type information are located at the logic_block_types in the device context of VPR + * We iterate over the vectors and find the pb_type matches the parent_pb_type_name + */ + bool link_success = false; + + for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) { + /* By pass 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 (target_pb_type_names[0] != 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 */ + t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names, + target_pb_mode_names); + if (nullptr == target_pb_type) { + continue; + } + + /* Found one, build annotation */ + t_mode* physical_mode = vpr_device_annotation.physical_mode(target_pb_type); + + VTR_ASSERT(nullptr != physical_mode); + /* Ensure that the annotation is only applicable to physical mode */ + if (std::string(physical_mode->name) != expected_physical_mode_name) { + VTR_LOG_ERROR("The physical mode '%s' under pb_type '%s' does not match in the bitstream setting '%s'!\n", + physical_mode->name, + target_pb_type->name, + expected_physical_mode_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Find the interconnect name under the physical mode of a physical pb_type */ + t_interconnect* pb_interc = find_pb_mode_interconnect(physical_mode, interconnect_name.c_str()); + + if (nullptr == pb_interc) { + VTR_LOG_ERROR("Unable to find interconnect '%s' under physical mode '%s' of pb_type '%s'!\n", + interconnect_name.c_str(), + physical_mode->name, + target_pb_type->name); + return CMD_EXEC_FATAL_ERROR; + } + + /* Find the default path and spot the path id from the input string recorded */ + StringToken input_string_tokenizer(std::string(pb_interc->input_string)); + std::vector input_paths = input_string_tokenizer.split(' '); + size_t input_path_id = input_paths.size(); + for (size_t ipath = 0; ipath < input_paths.size(); ++ipath) { + if (expected_input_path == input_paths[ipath]) { + input_path_id = ipath; + break; + } + } + /* If the input_path id is invalid, error out! */ + if (input_path_id == input_paths.size()) { + VTR_LOG_ERROR("Invalid default path '%s' for interconnect '%s' which inputs are '%s'\n", + expected_input_path.c_str(), + interconnect_name.c_str(), + pb_interc->input_string); + return CMD_EXEC_FATAL_ERROR; + } + + vpr_bitstream_annotation.set_interconnect_default_path_id(pb_interc, input_path_id); + + link_success = true; + } + + /* If fail to link bitstream setting to architecture, error out immediately */ + if (false == link_success) { + VTR_LOG_ERROR("Fail to find an interconnect '%s' with default path '%s', which is defined in bitstream setting from VPR architecture description\n", + interconnect_name.c_str(), + expected_input_path.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + } + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Annotate bitstream setting based on VPR device information + * - Fill pb_type -related mapping + * - Fill interconnect -related mapping + *******************************************************************/ +int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, + const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, + VprBitstreamAnnotation& vpr_bitstream_annotation) { + + int status = CMD_EXEC_SUCCESS; + + status = annotate_bitstream_pb_type_setting(bitstream_setting, + vpr_device_ctx, + vpr_bitstream_annotation); + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + + status = annotate_bitstream_interconnect_setting(bitstream_setting, + vpr_device_ctx, vpr_device_annotation, + vpr_bitstream_annotation); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/annotate_bitstream_setting.h b/openfpga/src/annotation/annotate_bitstream_setting.h index 053ca2fbe..45d6316dd 100644 --- a/openfpga/src/annotation/annotate_bitstream_setting.h +++ b/openfpga/src/annotation/annotate_bitstream_setting.h @@ -16,6 +16,7 @@ namespace openfpga { int annotate_bitstream_setting(const BitstreamSetting& bitstream_setting, const DeviceContext& vpr_device_ctx, + const VprDeviceAnnotation& vpr_device_annotation, VprBitstreamAnnotation& vpr_bitstream_annotation); } /* end namespace openfpga */ diff --git a/openfpga/src/annotation/vpr_bitstream_annotation.cpp b/openfpga/src/annotation/vpr_bitstream_annotation.cpp index 3361d598c..38842cbff 100644 --- a/openfpga/src/annotation/vpr_bitstream_annotation.cpp +++ b/openfpga/src/annotation/vpr_bitstream_annotation.cpp @@ -4,6 +4,7 @@ #include "vtr_log.h" #include "vtr_assert.h" #include "vpr_bitstream_annotation.h" +#include "mux_bitstream_constants.h" /* namespace openfpga begins */ namespace openfpga { @@ -78,6 +79,16 @@ size_t VprBitstreamAnnotation::pb_type_mode_select_bitstream_offset(t_pb_type* p return 0; } +size_t VprBitstreamAnnotation::interconnect_default_path_id(t_interconnect* interconnect) const { + auto result = interconnect_default_path_ids_.find(interconnect); + if (result != interconnect_default_path_ids_.end()) { + return result->second; + } + + /* Not found, return an invalid input id */ + return DEFAULT_PATH_ID; +} + /************************************************************************ * Public mutators ***********************************************************************/ @@ -111,4 +122,9 @@ void VprBitstreamAnnotation::set_pb_type_mode_select_bitstream_offset(t_pb_type* mode_select_bitstream_offsets_[pb_type] = offset; } +void VprBitstreamAnnotation::set_interconnect_default_path_id(t_interconnect* interconnect, + const size_t& default_path_id) { + interconnect_default_path_ids_[interconnect] = default_path_id; +} + } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/vpr_bitstream_annotation.h b/openfpga/src/annotation/vpr_bitstream_annotation.h index c562e4aa2..134530f25 100644 --- a/openfpga/src/annotation/vpr_bitstream_annotation.h +++ b/openfpga/src/annotation/vpr_bitstream_annotation.h @@ -38,6 +38,7 @@ class VprBitstreamAnnotation { e_bitstream_source_type pb_type_mode_select_bitstream_source(t_pb_type* pb_type) const; std::string pb_type_mode_select_bitstream_content(t_pb_type* pb_type) const; size_t pb_type_mode_select_bitstream_offset(t_pb_type* pb_type) const; + size_t interconnect_default_path_id(t_interconnect* interconnect) const; public: /* Public mutators */ void set_pb_type_bitstream_source(t_pb_type* pb_type, const e_bitstream_source_type& bitstream_source); @@ -52,6 +53,8 @@ class VprBitstreamAnnotation { const std::string& bitstream_content); void set_pb_type_mode_select_bitstream_offset(t_pb_type* pb_type, const size_t& offset); + void set_interconnect_default_path_id(t_interconnect* interconnect, + const size_t& default_path_id); private: /* Internal data */ /* For regular bitstreams */ /* A look up for pb type to find bitstream source type */ @@ -68,6 +71,12 @@ class VprBitstreamAnnotation { std::map mode_select_bitstream_contents_; /* Offset to be applied to mode-select bitstream */ std::map mode_select_bitstream_offsets_; + + /* A look up for interconnect to find default path indices + * Note: this is different from the default path in bitstream setting which is the index + * of inputs in the context of the interconnect input string + */ + std::map interconnect_default_path_ids_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/base/openfpga_link_arch.cpp b/openfpga/src/base/openfpga_link_arch.cpp index 63a0b0430..3da3f3ae1 100644 --- a/openfpga/src/base/openfpga_link_arch.cpp +++ b/openfpga/src/base/openfpga_link_arch.cpp @@ -177,7 +177,9 @@ int link_arch(OpenfpgaContext& openfpga_ctx, /* Build bitstream annotation based on bitstream settings */ if (CMD_EXEC_FATAL_ERROR == annotate_bitstream_setting(openfpga_ctx.bitstream_setting(), g_vpr_ctx.device(), + openfpga_ctx.vpr_device_annotation(), openfpga_ctx.mutable_vpr_bitstream_annotation())) { + return CMD_EXEC_FATAL_ERROR; } diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 1fb2360e9..e90d73321 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -189,6 +189,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); VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index f0cfab7dd..d5241a451 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -129,6 +129,7 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag const MuxLibrary& mux_lib, 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) { @@ -197,6 +198,12 @@ void build_physical_block_pin_interc_bitstream(BitstreamManager& bitstream_manag } } + /* Overwrite the default path if defined in bitstream annotation */ + if ( (size_t(DEFAULT_PATH_ID) == mux_input_pin_id) + && (mux_input_pin_id != bitstream_annotation.interconnect_default_path_id(cur_interc)) ) { + mux_input_pin_id = bitstream_annotation.interconnect_default_path_id(cur_interc); + } + /* Generate bitstream depend on both technology and structure of this MUX */ std::vector mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, mux_input_pin_id); @@ -266,6 +273,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + 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, @@ -276,7 +284,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode); @@ -288,7 +296,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode); @@ -300,7 +308,7 @@ void build_physical_block_interc_port_bitstream(BitstreamManager& bitstream_mana for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode); @@ -327,6 +335,7 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager, const MuxLibrary& mux_lib, 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) { @@ -348,7 +357,7 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager, */ build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, physical_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode); @@ -367,13 +376,13 @@ void build_physical_block_interc_bitstream(BitstreamManager& bitstream_manager, /* For each child_pb_graph_node input pins*/ build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode); /* For clock pins, we should do the same work */ build_physical_block_interc_port_bitstream(bitstream_manager, parent_configurable_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, + atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode); } @@ -534,6 +543,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const e_side& border_side, const PhysicalPb& physical_pb, const PhysicalPbId& pb_id, @@ -578,7 +588,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, rec_build_physical_block_bitstream(bitstream_manager, pb_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, - device_annotation, + device_annotation, bitstream_annotation, border_side, physical_pb, child_pb, &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), @@ -623,7 +633,7 @@ void rec_build_physical_block_bitstream(BitstreamManager& bitstream_manager, build_physical_block_interc_bitstream(bitstream_manager, pb_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, - device_annotation, + device_annotation, bitstream_annotation, physical_pb_graph_node, physical_pb, physical_mode); } @@ -644,6 +654,7 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const DeviceGrid& grids, const vtr::Point& grid_coord, const e_side& border_side) { @@ -692,7 +703,8 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager, rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, - device_annotation, border_side, + device_annotation, bitstream_annotation, + border_side, PhysicalPb(), PhysicalPbId::INVALID(), lb_type->pb_graph_head, z); } else { @@ -707,7 +719,8 @@ void build_physical_block_bitstream(BitstreamManager& bitstream_manager, rec_build_physical_block_bitstream(bitstream_manager, grid_configurable_block, module_manager, circuit_lib, mux_lib, atom_ctx, - device_annotation, border_side, + device_annotation, bitstream_annotation, + border_side, phy_pb, top_pb_id, pb_graph_head, z); } } @@ -731,6 +744,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose) { VTR_LOGV(verbose, "Generating bitstream for core grids..."); @@ -753,7 +767,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, cluster_annotation, - place_annotation, + place_annotation, bitstream_annotation, grids, grid_coord, NUM_SIDES); } } @@ -780,7 +794,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, cluster_annotation, - place_annotation, + place_annotation, bitstream_annotation, grids, io_coordinate, io_side); } } diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.h b/openfpga/src/fpga_bitstream/build_grid_bitstream.h index be2425c5a..9d2c3d010 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.h @@ -14,6 +14,7 @@ #include "vpr_device_annotation.h" #include "vpr_clustering_annotation.h" #include "vpr_placement_annotation.h" +#include "vpr_bitstream_annotation.h" /******************************************************************** * Function declaration @@ -32,6 +33,7 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, + const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose); } /* end namespace openfpga */