debugging the annotation to physical mode of pb_types
This commit is contained in:
parent
a6fbbce33e
commit
5ecb771673
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "command.h"
|
||||
#include "command_context.h"
|
||||
#include "openfpga_context.h"
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -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*/
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue