debugging the annotation to physical mode of pb_types

This commit is contained in:
tangxifan 2020-01-27 17:43:22 -07:00
parent a6fbbce33e
commit 5ecb771673
11 changed files with 231 additions and 32 deletions

View File

@ -390,6 +390,10 @@ void Shell<T>::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;
}

View File

@ -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;

View File

@ -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<std::string>& target_pb_type_names,
const std::vector<std::string>& 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<std::string> target_pb_type_names;
std::vector<std::string> 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 */

View File

@ -4,8 +4,6 @@
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "command.h"
#include "command_context.h"
#include "openfpga_context.h"
/********************************************************************

View File

@ -48,7 +48,7 @@ void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& 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<ShellCommandId> 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);

View File

@ -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 */

View File

@ -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

View File

@ -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<t_pb_type*, t_mode*>::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<t_pb_type*, t_mode*>::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*/

View File

@ -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<t_pb_type*, bool> is_physical_pb_types_;
std::map<t_pb_type*, t_pb_type*> physical_pb_types_;

View File

@ -10,13 +10,13 @@ namespace openfpga {
void add_vpr_commands(openfpga::Shell<OpenfpgaContext>& 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);
}

View File

@ -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