diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp index 0a52fda0b..9d5f8833e 100644 --- a/libopenfpga/libopenfpgashell/src/shell.tpp +++ b/libopenfpga/libopenfpgashell/src/shell.tpp @@ -390,6 +390,10 @@ void Shell::execute_command(const char* cmd_line, free(argv[itok]); } free(argv); + + /* Change the status of the command */ + command_status_[cmd_id] = true; + /* Finish for macro command, return */ return; } diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index a1e750d69..36901e6f0 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -789,22 +789,6 @@ struct t_pb_type { t_pin_to_pin_annotation* annotations = nullptr; /* [0..num_annotations-1] */ int num_annotations = 0; - /************************************************************************ - * Xifan Tang: Add useful methods for pb_type - * - A pb_type is considered to be primitive when it has zero modes - * However, this not always true. An exception is the LUT_CLASS - * VPR added two modes by default to a LUT pb_type. Therefore, - * for LUT_CLASS, it is a primitive when it is binded to a blif model - * - A pb_type is the root pb_type when it has no parent mode - ************************************************************************/ - bool is_primitive() const { - if (LUT_CLASS == class_type) { - return nullptr != blif_model; - } - return 0 == num_modes; - } - bool is_root() const { return parent_mode == nullptr; } - /* Power related members */ t_pb_type_power* pb_type_power = nullptr; diff --git a/openfpga/src/base/openfpga_link_arch.cpp b/openfpga/src/base/openfpga_link_arch.cpp index 4af1f00ac..239829e8e 100644 --- a/openfpga/src/base/openfpga_link_arch.cpp +++ b/openfpga/src/base/openfpga_link_arch.cpp @@ -3,9 +3,11 @@ * which are built on the libarchopenfpga library *******************************************************************/ /* Headers from vtrutil library */ +#include "vtr_assert.h" #include "vtr_log.h" #include "vpr_pb_type_annotation.h" +#include "pb_type_utils.h" #include "openfpga_link_arch.h" /* Include global variables of VPR */ @@ -14,15 +16,57 @@ /* begin namespace openfpga */ namespace openfpga { +/******************************************************************** + * This function will traverse pb_type graph from its top to find + * a pb_type with a given name as well as its hierarchy + *******************************************************************/ +static +t_pb_type* try_find_pb_type_with_given_path(t_pb_type* top_pb_type, + const std::vector& target_pb_type_names, + const std::vector& target_pb_mode_names) { + /* Ensure that number of parent names and modes matches */ + VTR_ASSERT_SAFE(target_pb_type_names.size() == target_pb_mode_names.size() + 1); + + t_pb_type* cur_pb_type = top_pb_type; + + /* We start from the first element of the parent names and parent modes. + * If the pb_type does not match in name, we fail + * If we cannot find a mode match the name, we fail + */ + for (size_t i = 0; i < target_pb_type_names.size() - 1; ++i) { + /* If this level does not match, search fail */ + if (target_pb_type_names[i] != std::string(cur_pb_type->name)) { + return nullptr; + } + /* Find if the mode matches */ + t_mode* cur_mode = find_pb_type_mode(cur_pb_type, target_pb_mode_names[i].c_str()); + if (nullptr == cur_mode) { + return nullptr; + } + /* Go to the next level of pb_type */ + cur_pb_type = find_mode_child_pb_type(cur_mode, target_pb_type_names[i + 1].c_str()); + if (nullptr == cur_pb_type) { + return nullptr; + } + /* If this is already the last pb_type in the list, this is what we want */ + if (i == target_pb_type_names.size() - 1) { + return cur_pb_type; + } + } + + /* Reach here, it means we find nothing */ + return nullptr; +} + /******************************************************************** * This function will recursively traverse pb_type graph to ensure * 1. there is only a physical mode under each pb_type * 2. physical mode appears only when its parent is a physical mode. *******************************************************************/ static -void rec_check_pb_type_physical_mode(const t_pb_type& cur_pb_type) { +void rec_check_pb_type_physical_mode(t_pb_type* cur_pb_type) { /* We do not check any primitive pb_type */ - if (true == cur_pb_type.is_primitive()) { + if (true == is_primitive_pb_type(cur_pb_type)) { return; } @@ -31,10 +75,10 @@ void rec_check_pb_type_physical_mode(const t_pb_type& cur_pb_type) { */ /* Traverse all the modes for identifying idle mode */ - for (int imode = 0; cur_pb_type.num_modes; ++imode) { + for (int imode = 0; cur_pb_type->num_modes; ++imode) { /* Check each pb_type_child */ - for (int ichild = 0; ichild < cur_pb_type.modes[imode].num_pb_type_children; ++ichild) { - rec_check_pb_type_physical_mode(cur_pb_type.modes[imode].pb_type_children[ichild]); + for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) { + rec_check_pb_type_physical_mode(&(cur_pb_type->modes[imode].pb_type_children[ichild])); } } } @@ -46,19 +90,68 @@ void rec_check_pb_type_physical_mode(const t_pb_type& cur_pb_type) { * - identify the physical pb_type for operating pb_types in VPR *******************************************************************/ static -void build_physical_pb_type_vpr_annotation(const DeviceContext& vpr_device_ctx, +void build_vpr_physical_pb_type_annotation(const DeviceContext& vpr_device_ctx, const Arch& openfpga_arch, VprPbTypeAnnotation& vpr_pb_type_annotation) { /* Walk through the pb_type annotation stored in the openfpga arch */ for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) { + /* Since our target is to annotate the physical mode name, + * we can skip those has not physical mode defined + */ + if (true == pb_type_annotation.physical_mode_name().empty()) { + continue; + } + + /* Identify if the pb_type is operating or physical, + * For operating pb_type, get the full name of operating pb_type + * For physical pb_type, get the full name of physical pb_type + */ + std::vector target_pb_type_names; + std::vector target_pb_mode_names; + + if (true == pb_type_annotation.is_operating_pb_type()) { + target_pb_type_names = pb_type_annotation.operating_parent_pb_type_names(); + target_pb_type_names.push_back(pb_type_annotation.operating_pb_type_name()); + target_pb_mode_names = pb_type_annotation.operating_parent_mode_names(); + } + + if (true == pb_type_annotation.is_physical_pb_type()) { + target_pb_type_names = pb_type_annotation.physical_parent_pb_type_names(); + target_pb_type_names.push_back(pb_type_annotation.physical_pb_type_name()); + target_pb_mode_names = pb_type_annotation.physical_parent_mode_names(); + } + + /* We must have at least one pb_type in the list */ + VTR_ASSERT_SAFE(0 < target_pb_type_names.size()); + /* Pb type information are located at the logic_block_types in the device context of VPR - * We iterate over the vectors and annotate the pb_type + * We iterate over the vectors and find the pb_type matches the parent_pb_type_name */ 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) { + /* Not found, error out! */ + VTR_LOG_ERROR("Unable to find the pb_type '%s' in VPR architecture definition!\n", + target_pb_type_names.back().c_str()); + } + + /* Found, we update the annotation by assigning the physical mode */ + t_mode* physical_mode = find_pb_type_mode(target_pb_type, pb_type_annotation.physical_mode_name().c_str()); + vpr_pb_type_annotation.add_pb_type_physical_mode(target_pb_type, physical_mode); + + /* Give a message */ + VTR_LOG("Annotate pb_type '%s' with physical mode '%s'\n", + target_pb_type->name, physical_mode->name); } } } @@ -72,7 +165,7 @@ void build_physical_pb_type_vpr_annotation(const DeviceContext& vpr_device_ctx, void link_arch(OpenfpgaContext& openfpga_context) { /* Annotate physical pb_type in the VPR pb_type graph */ - build_physical_pb_type_vpr_annotation(g_vpr_ctx.device(), openfpga_context.arch(), + build_vpr_physical_pb_type_annotation(g_vpr_ctx.device(), openfpga_context.arch(), openfpga_context.mutable_vpr_pb_type_annotation()); /* Annotate idle pb_type in the VPR pb_type graph */ @@ -83,4 +176,3 @@ void link_arch(OpenfpgaContext& openfpga_context) { } } /* end namespace openfpga */ - diff --git a/openfpga/src/base/openfpga_link_arch.h b/openfpga/src/base/openfpga_link_arch.h index be957c5b0..c36c57711 100644 --- a/openfpga/src/base/openfpga_link_arch.h +++ b/openfpga/src/base/openfpga_link_arch.h @@ -4,8 +4,6 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "command.h" -#include "command_context.h" #include "openfpga_context.h" /******************************************************************** diff --git a/openfpga/src/base/openfpga_setup_command.cpp b/openfpga/src/base/openfpga_setup_command.cpp index fdc7a4e98..af078446a 100644 --- a/openfpga/src/base/openfpga_setup_command.cpp +++ b/openfpga/src/base/openfpga_setup_command.cpp @@ -48,7 +48,7 @@ void add_openfpga_setup_commands(openfpga::Shell& shell) { shell.set_command_class(shell_cmd_link_openfpga_arch_id, openfpga_setup_cmd_class); shell.set_command_execute_function(shell_cmd_link_openfpga_arch_id, link_arch); /* The 'link_openfpga_arch' command should NOT be executed before 'read_openfpga_arch' and 'vpr' */ - const ShellCommandId& shell_cmd_vpr_id = shell.command("vpr"); + const ShellCommandId& shell_cmd_vpr_id = shell.command(std::string("vpr")); std::vector cmd_dependency_link_openfpga_arch; cmd_dependency_link_openfpga_arch.push_back(shell_cmd_read_arch_id); cmd_dependency_link_openfpga_arch.push_back(shell_cmd_vpr_id); diff --git a/openfpga/src/base/pb_type_utils.cpp b/openfpga/src/base/pb_type_utils.cpp new file mode 100644 index 000000000..8eb3c42a1 --- /dev/null +++ b/openfpga/src/base/pb_type_utils.cpp @@ -0,0 +1,59 @@ +/******************************************************************** + * This file includes most utilized functions for the pb_type + * and pb_graph_node data structure in the OpenFPGA context + *******************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_log.h" + +#include "pb_type_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * A pb_type is considered to be primitive when it has zero modes + * However, this not always true. An exception is the LUT_CLASS + * VPR added two modes by default to a LUT pb_type. Therefore, + * for LUT_CLASS, it is a primitive when it is binded to a blif model + ************************************************************************/ +bool is_primitive_pb_type(t_pb_type* pb_type) { + if (LUT_CLASS == pb_type->class_type) { + return nullptr != pb_type->blif_model; + } + return 0 == pb_type->num_modes; +} + +/************************************************************************ + * A pb_type is the root pb_type when it has no parent mode + ************************************************************************/ +bool is_root_pb_type(t_pb_type* pb_type) { + return pb_type->parent_mode == nullptr; +} + +/************************************************************************ + * With a given mode name, find the mode pointer + ************************************************************************/ +t_mode* find_pb_type_mode(t_pb_type* pb_type, const char* mode_name) { + for (int i = 0; i < pb_type->num_modes; ++i) { + if (std::string(mode_name) == std::string(pb_type->modes[i].name)) { + return &(pb_type->modes[i]); + } + } + /* Note found, return a nullptr */ + return nullptr; +} + +/************************************************************************ + * With a given pb_type name, find the pb_type pointer + ************************************************************************/ +t_pb_type* find_mode_child_pb_type(t_mode* mode, const char* child_name) { + for (int i = 0; i < mode->num_pb_type_children; ++i) { + if (std::string(child_name) == std::string(mode->pb_type_children[i].name)) { + return &(mode->pb_type_children[i]); + } + } + /* Note found, return a nullptr */ + return nullptr; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/base/pb_type_utils.h b/openfpga/src/base/pb_type_utils.h new file mode 100644 index 000000000..c0c1881d5 --- /dev/null +++ b/openfpga/src/base/pb_type_utils.h @@ -0,0 +1,26 @@ +#ifndef PB_TYPE_UTILS_H +#define PB_TYPE_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "physical_types.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +bool is_primitive_pb_type(t_pb_type* pb_type); + +bool is_root_pb_type(t_pb_type* pb_type); + +t_mode* find_pb_type_mode(t_pb_type* pb_type, const char* mode_name); + +t_pb_type* find_mode_child_pb_type(t_mode* mode, const char* child_name); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/base/vpr_pb_type_annotation.cpp b/openfpga/src/base/vpr_pb_type_annotation.cpp index 70532cae4..1d4beb1ff 100644 --- a/openfpga/src/base/vpr_pb_type_annotation.cpp +++ b/openfpga/src/base/vpr_pb_type_annotation.cpp @@ -15,4 +15,30 @@ VprPbTypeAnnotation::VprPbTypeAnnotation() { return; } +/************************************************************************ + * Public mutators + ***********************************************************************/ +t_mode* VprPbTypeAnnotation::physical_mode(t_pb_type* pb_type) const { + /* Ensure that the pb_type is in the list */ + std::map::const_iterator it = physical_pb_modes_.find(pb_type); + if (it == physical_pb_modes_.end()) { + return nullptr; + } + return physical_pb_modes_.at(pb_type); +} + +/************************************************************************ + * Public mutators + ***********************************************************************/ +void VprPbTypeAnnotation::add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode) { + /* Warn any override attempt */ + std::map::const_iterator it = physical_pb_modes_.find(pb_type); + if (it != physical_pb_modes_.end()) { + VTR_LOG_WARN("Override the annotation between pb_type '%s' and it physical mode '%s'!\n", + pb_type->name, physical_mode->name); + } + + physical_pb_modes_[pb_type] = physical_mode; +} + } /* End namespace openfpga*/ diff --git a/openfpga/src/base/vpr_pb_type_annotation.h b/openfpga/src/base/vpr_pb_type_annotation.h index 8fb6318b8..5410a7ca9 100644 --- a/openfpga/src/base/vpr_pb_type_annotation.h +++ b/openfpga/src/base/vpr_pb_type_annotation.h @@ -27,6 +27,10 @@ namespace openfpga { class VprPbTypeAnnotation { public: /* Constructor */ VprPbTypeAnnotation(); + public: /* Public accessors */ + t_mode* physical_mode(t_pb_type* pb_type) const; + public: /* Public mutators */ + void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode); private: /* Internal data */ std::map is_physical_pb_types_; std::map physical_pb_types_; diff --git a/openfpga/src/vpr_wrapper/vpr_command.cpp b/openfpga/src/vpr_wrapper/vpr_command.cpp index 5baa1ec84..d87ffa32b 100644 --- a/openfpga/src/vpr_wrapper/vpr_command.cpp +++ b/openfpga/src/vpr_wrapper/vpr_command.cpp @@ -10,13 +10,13 @@ namespace openfpga { void add_vpr_commands(openfpga::Shell& shell) { /* Add a new class of commands */ - ShellCommandClassId arith_cmd_class = shell.add_command_class("VPR"); + ShellCommandClassId vpr_cmd_class = shell.add_command_class("VPR"); /* Create a macro command of 'vpr' which will call the main engine of vpr */ Command shell_cmd_vpr("vpr"); ShellCommandId shell_cmd_vpr_id = shell.add_command(shell_cmd_vpr, "Start VPR core engine to pack, place and route a BLIF design on a FPGA architecture"); - shell.set_command_class(shell_cmd_vpr_id, arith_cmd_class); + shell.set_command_class(shell_cmd_vpr_id, vpr_cmd_class); shell.set_command_execute_function(shell_cmd_vpr_id, vpr::vpr); } diff --git a/openfpga/test_script/s298.openfpga b/openfpga/test_script/s298.openfpga index d9d1e15ca..ad12f4807 100644 --- a/openfpga/test_script/s298.openfpga +++ b/openfpga/test_script/s298.openfpga @@ -1,2 +1,8 @@ -# Run VPR for the RISC-V core -vpr ./test_arch/k6_frac_N10_frac_chain_depop50_mem32K_40nm.xml ./test_blif/s298.blif +# Run VPR for the s298 design +vpr ./test_vpr_arch/k6_N10_40nm.xml ./test_blif/s298.blif + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ./test_openfpga_arch/k6_N10_40nm_openfpga.xml + +# Annotate the OpenFPGA architecture to VPR data base +link_openfpga_arch