[core] io name map now supports dummy port direction
This commit is contained in:
parent
0811409c4f
commit
8bd9ae02fd
|
@ -119,7 +119,8 @@ bool IoNameMap::fpga_top_port_is_dummy(const BasicPort& fpga_top_port) const {
|
|||
return !fpga_core_port(fpga_top_port).is_valid();
|
||||
}
|
||||
|
||||
IoNameMap::e_dummy_port_direction IoNameMap::fpga_top_dummy_port_direction(const BasicPort& fpga_top_port) const {
|
||||
IoNameMap::e_dummy_port_direction IoNameMap::fpga_top_dummy_port_direction(
|
||||
const BasicPort& fpga_top_port) const {
|
||||
for (auto& kv : dummy_port_direction_) {
|
||||
BasicPort cand = str2port(kv.first);
|
||||
if (cand.contained(fpga_top_port)) {
|
||||
|
@ -131,7 +132,9 @@ IoNameMap::e_dummy_port_direction IoNameMap::fpga_top_dummy_port_direction(const
|
|||
}
|
||||
|
||||
bool IoNameMap::empty() const {
|
||||
return top2core_io_name_keys_.empty() && top2core_io_name_map_.empty() && core2top_io_name_keys_.empty() && core2top_io_name_map_.empty() && dummy_port_direction_.empty();
|
||||
return top2core_io_name_keys_.empty() && top2core_io_name_map_.empty() &&
|
||||
core2top_io_name_keys_.empty() && core2top_io_name_map_.empty() &&
|
||||
dummy_port_direction_.empty();
|
||||
}
|
||||
|
||||
int IoNameMap::set_io_pair(const BasicPort& fpga_top_port,
|
||||
|
@ -203,7 +206,8 @@ int IoNameMap::set_io_pair(const BasicPort& fpga_top_port,
|
|||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port, const e_dummy_port_direction& direction) {
|
||||
int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port,
|
||||
const e_dummy_port_direction& direction) {
|
||||
/* Must be a true dummy port, none of its pins have been paired! */
|
||||
std::string top_port_str = port2str(fpga_top_port);
|
||||
/* First, find the pin name matching */
|
||||
|
@ -236,7 +240,8 @@ int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port, const e_dummy_port_d
|
|||
if (kv.second != direction) {
|
||||
/* Throw a error because the dummy pin should NOT be mapped before! */
|
||||
VTR_LOG_ERROR(
|
||||
"Dummy port '%s' of fpga_top is already assigned to a different direction through another dummy port definition '%s'!\n",
|
||||
"Dummy port '%s' of fpga_top is already assigned to a different "
|
||||
"direction through another dummy port definition '%s'!\n",
|
||||
port2str(fpga_top_port).c_str(), port2str(cand).c_str());
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
@ -246,7 +251,7 @@ int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port, const e_dummy_port_d
|
|||
}
|
||||
if (!dir_defined) {
|
||||
dummy_port_direction_[top_port_str] = direction;
|
||||
}
|
||||
}
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -258,20 +263,43 @@ BasicPort IoNameMap::str2port(const std::string& port_str) const {
|
|||
return PortParser(port_str).port();
|
||||
}
|
||||
|
||||
IoNameMap::e_dummy_port_direction IoNameMap::str2dummy_port_dir(const std::string& dir_str, const bool& verbose) const {
|
||||
for (int itype = IoNameMap::e_dummy_port_direction::INPUT; itype != IoNameMap::e_dummy_direction::NUM_TYPES; ++itype) {
|
||||
if (dir_str == std::string(DUMMY_PORT_DIR_STRING_[itype])) {
|
||||
return static_case<IoNameMap::e_dummy_port_direction>(itype);
|
||||
}
|
||||
}
|
||||
std::string IoNameMap::dummy_port_dir_all2str() const {
|
||||
std::string full_types = "[";
|
||||
for (int itype = IoNameMap::e_dummy_port_direction::INPUT; itype != IoNameMap::e_dummy_direction::NUM_TYPES; ++itype) {
|
||||
for (int itype = size_t(IoNameMap::e_dummy_port_direction::INPUT);
|
||||
itype != size_t(IoNameMap::e_dummy_port_direction::NUM_TYPES); ++itype) {
|
||||
full_types += std::string(DUMMY_PORT_DIR_STRING_[itype]) + std::string("|");
|
||||
}
|
||||
}
|
||||
full_types.pop_back();
|
||||
full_types += "]";
|
||||
VTR_LOGV_ERROR(verbose, "Invalid direction for dummy port! Expect %s\n", full_types.c_str());
|
||||
return full_types;
|
||||
}
|
||||
|
||||
IoNameMap::e_dummy_port_direction IoNameMap::str2dummy_port_dir(
|
||||
const std::string& dir_str, const bool& verbose) const {
|
||||
for (int itype = size_t(IoNameMap::e_dummy_port_direction::INPUT);
|
||||
itype != size_t(IoNameMap::e_dummy_port_direction::NUM_TYPES); ++itype) {
|
||||
if (dir_str == std::string(DUMMY_PORT_DIR_STRING_[itype])) {
|
||||
return static_cast<IoNameMap::e_dummy_port_direction>(itype);
|
||||
}
|
||||
}
|
||||
VTR_LOGV_ERROR(verbose, "Invalid direction for dummy port! Expect %s\n",
|
||||
dummy_port_dir_all2str().c_str());
|
||||
return IoNameMap::e_dummy_port_direction::NUM_TYPES;
|
||||
}
|
||||
|
||||
std::string IoNameMap::dummy_port_dir2str(const e_dummy_port_direction& dir,
|
||||
const bool& verbose) const {
|
||||
if (!valid_dummy_port_direction(dir)) {
|
||||
VTR_LOGV_ERROR(verbose, "Invalid direction for dummy port! Expect %s\n",
|
||||
dummy_port_dir_all2str().c_str());
|
||||
return std::string();
|
||||
}
|
||||
return std::string(DUMMY_PORT_DIR_STRING_[size_t(dir)]);
|
||||
}
|
||||
|
||||
bool IoNameMap::valid_dummy_port_direction(
|
||||
const IoNameMap::e_dummy_port_direction& direction) const {
|
||||
return direction != IoNameMap::e_dummy_port_direction::NUM_TYPES;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -20,12 +20,8 @@ namespace openfpga {
|
|||
*/
|
||||
class IoNameMap {
|
||||
public: /* Types */
|
||||
enum class e_dummy_port_direction {
|
||||
INPUT = 0,
|
||||
OUTPUT,
|
||||
INOUT,
|
||||
NUM_TYPES
|
||||
};
|
||||
enum class e_dummy_port_direction { INPUT = 0, OUTPUT, INOUT, NUM_TYPES };
|
||||
|
||||
public: /* Public accessors */
|
||||
/** @brief Get all the fpga top ports */
|
||||
std::vector<BasicPort> fpga_top_ports() const;
|
||||
|
@ -38,7 +34,8 @@ class IoNameMap {
|
|||
/** @brief Identify if the fpga_top port is dummy or not */
|
||||
bool fpga_top_port_is_dummy(const BasicPort& fpga_top_port) const;
|
||||
/** @brief Get the direction of a dummy port */
|
||||
e_dummy_port_direction fpga_top_dummy_port_direction(const BasicPort& fpga_top_port) const;
|
||||
e_dummy_port_direction fpga_top_dummy_port_direction(
|
||||
const BasicPort& fpga_top_port) const;
|
||||
/** @brief Identify if there are any naming rules inside */
|
||||
bool empty() const;
|
||||
|
||||
|
@ -49,17 +46,29 @@ class IoNameMap {
|
|||
const BasicPort& fpga_core_port);
|
||||
/** @brief Add a dummy port at the fpga top, which is not mapped any port at
|
||||
* fpga_core */
|
||||
int set_dummy_io(const BasicPort& fpga_top_port, const e_dummy_port_direction& direction);
|
||||
int set_dummy_io(const BasicPort& fpga_top_port,
|
||||
const e_dummy_port_direction& direction);
|
||||
|
||||
public: /* Public utility */
|
||||
/** @brief Parse the dummy port direction from string to valid type. Parser error can be turned on */
|
||||
e_dummy_port_direction str2dummy_port_dir(const std::string& dir_str, const bool& verbose = false) const;
|
||||
/** @brief Parse the dummy port direction from string to valid type. Parser
|
||||
* error can be turned on */
|
||||
e_dummy_port_direction str2dummy_port_dir(const std::string& dir_str,
|
||||
const bool& verbose = false) const;
|
||||
/** @brief Output the string representing dummy port direction */
|
||||
std::string dummy_port_dir2str(const e_dummy_port_direction& dir,
|
||||
const bool& verbose = false) const;
|
||||
/** @brief Validate the dummy port direction */
|
||||
bool valid_dummy_port_direction(
|
||||
const e_dummy_port_direction& direction) const;
|
||||
|
||||
private: /* Internal utility */
|
||||
/* Convert a port info to string, which can be used to store keys */
|
||||
std::string port2str(const BasicPort& port) const;
|
||||
/* Convert a string to port, which can be used to echo internal info */
|
||||
BasicPort str2port(const std::string& port_str) const;
|
||||
/* Generate a string include all the valid directions of the dummy port.
|
||||
* Useful for printing debugging messages */
|
||||
std::string dummy_port_dir_all2str() const;
|
||||
|
||||
private: /* Internal Data */
|
||||
/* fpga_top -> fpga_core io_name_keys. Use the port name to find all the port
|
||||
|
@ -76,7 +85,8 @@ class IoNameMap {
|
|||
std::map<std::string, e_dummy_port_direction> dummy_port_direction_;
|
||||
|
||||
/* Constants */
|
||||
std::array<const char*, e_dummy_port_direction::NUM_TYPES> DUMMY_PORT_DIR_STRING_;
|
||||
std::array<const char*, size_t(e_dummy_port_direction::NUM_TYPES)>
|
||||
DUMMY_PORT_DIR_STRING_;
|
||||
};
|
||||
|
||||
} /* End namespace openfpga*/
|
||||
|
|
|
@ -10,6 +10,8 @@ constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_CORE_NAME = "core_name";
|
|||
constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_IS_DUMMY = "is_dummy";
|
||||
constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION = "direction";
|
||||
|
||||
constexpr std::array<const char*, 3> XML_IO_NAME_MAP_DUMMY_PORT_DIRECTION_STRING = {{"input", "output", "inout"}}; //String versions of side orientations
|
||||
constexpr std::array<const char*, 3>
|
||||
XML_IO_NAME_MAP_DUMMY_PORT_DIRECTION_STRING = {
|
||||
{"input", "output", "inout"}}; // String versions of side orientations
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
/* Headers from vtr util library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from libopenfpga util library */
|
||||
|
@ -45,12 +46,15 @@ static int read_xml_io_map_port(pugi::xml_node& xml_port,
|
|||
std::string dir_str =
|
||||
get_attribute(xml_port, XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION, loc_data)
|
||||
.as_string();
|
||||
IoNameMap::e_dummy_port_direction dummy_port_dir = io_name_map.str2dummy_port_dir(dir_str, true);
|
||||
IoNameMap::e_dummy_port_direction dummy_port_dir =
|
||||
io_name_map.str2dummy_port_dir(dir_str, true);
|
||||
if (!io_name_map.valid_dummy_port_direction(dummy_port_dir)) {
|
||||
VTR_LOG_ERROR("Invalid direction for dummy port '%s'!\n", top_port.to_verilog_string().c_str());
|
||||
VTR_LOG_ERROR("Invalid direction for dummy port '%s'!\n",
|
||||
top_port.to_verilog_string().c_str());
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
return io_name_map.set_dummy_io(top_port, dummy_port_dir); /* Early return */
|
||||
return io_name_map.set_dummy_io(top_port,
|
||||
dummy_port_dir); /* Early return */
|
||||
}
|
||||
|
||||
/* This is not a dummy io, create the io mapping */
|
||||
|
|
|
@ -44,6 +44,10 @@ static int write_xml_io_map_port(std::fstream& fp, const IoNameMap& io_name_map,
|
|||
|
||||
if (io_name_map.fpga_top_port_is_dummy(fpga_top_port)) {
|
||||
write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_IS_DUMMY, "true");
|
||||
IoNameMap::e_dummy_port_direction dir =
|
||||
io_name_map.fpga_top_dummy_port_direction(fpga_top_port);
|
||||
write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION,
|
||||
io_name_map.dummy_port_dir2str(dir, true).c_str());
|
||||
} else {
|
||||
BasicPort fpga_core_port = io_name_map.fpga_core_port(fpga_top_port);
|
||||
write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_CORE_NAME,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "build_device_module.h"
|
||||
#include "build_fabric_global_port_info.h"
|
||||
#include "build_fabric_io_location_map.h"
|
||||
#include "build_fpga_core_wrapper_module.h"
|
||||
#include "command.h"
|
||||
#include "command_context.h"
|
||||
#include "command_exit_codes.h"
|
||||
|
@ -254,12 +255,13 @@ int add_fpga_core_to_fabric_template(T& openfpga_ctx, const Command& cmd,
|
|||
IoNameMap io_name_map;
|
||||
CommandOptionId opt_io_naming = cmd.option("io_naming");
|
||||
if (true == cmd_context.option_enable(cmd, opt_io_naming)) {
|
||||
read_xml_io_name_map(cmd_context.option_value(cmd, opt_io_naming), io_name_map);
|
||||
read_xml_io_name_map(cmd_context.option_value(cmd, opt_io_naming).c_str(),
|
||||
io_name_map);
|
||||
}
|
||||
|
||||
return add_fpga_core_to_device_module_graph(
|
||||
openfpga_ctx.mutable_module_graph(), io_name_map, core_inst_name, frame_view,
|
||||
verbose_output);
|
||||
openfpga_ctx.mutable_module_graph(), io_name_map, core_inst_name,
|
||||
frame_view, verbose_output);
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "build_fpga_core_wrapper_module.h"
|
||||
#include "command_exit_codes.h"
|
||||
#include "openfpga_naming.h"
|
||||
#include "build_fpga_core_wrapper_module.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
@ -19,14 +19,10 @@ namespace openfpga {
|
|||
/********************************************************************
|
||||
* Create a custom fpga_top module by applying naming rules
|
||||
*******************************************************************/
|
||||
static
|
||||
int create_fpga_top_module_using_naming_rules(ModuleManager& module_manager,
|
||||
const ModuleId& core_module,
|
||||
const std::string& top_module_name,
|
||||
const IoNameMap& io_naming,
|
||||
const std::string& instance_name,
|
||||
const bool& add_nets,
|
||||
const bool& verbose) {
|
||||
static int create_fpga_top_module_using_naming_rules(
|
||||
ModuleManager& module_manager, const ModuleId& core_module,
|
||||
const std::string& top_module_name, const IoNameMap& io_naming,
|
||||
const std::string& instance_name, const bool& add_nets, const bool& verbose) {
|
||||
/* Create a new module with the given name */
|
||||
ModuleId wrapper_module = module_manager.add_module(top_module_name);
|
||||
if (!wrapper_module) {
|
||||
|
@ -34,41 +30,50 @@ int create_fpga_top_module_using_naming_rules(ModuleManager& module_manager,
|
|||
}
|
||||
/* Add the existing module as an instance */
|
||||
module_manager.add_child_module(wrapper_module, core_module, false);
|
||||
module_manager.set_child_instance_name(wrapper_module, core_module, 0, instance_name);
|
||||
module_manager.set_child_instance_name(wrapper_module, core_module, 0,
|
||||
instance_name);
|
||||
|
||||
/* TODO: Add ports from I/O naming rules:
|
||||
* - Add ports which has been defined in the naming rules
|
||||
* - Add ports from the core module, which does not appear in the naming rules
|
||||
*/
|
||||
for (BasicPort top_port : io_naming.fpga_top_ports()) {
|
||||
/* For dummy port, just add it. Port type should be defined from io naming rules */
|
||||
/* For dummy port, just add it. Port type should be defined from io naming
|
||||
* rules */
|
||||
if (io_naming.fpga_top_port_is_dummy(top_port)) {
|
||||
ModuleManager::e_module_port_type port_type = ModuleManager::e_module_port_type::MODULE_INOUT_PORT;
|
||||
if (IoNameMap::e_dummy_port_direction::INPUT == io_naming.fpga_top_dummy_port_direction(top_port)) {
|
||||
ModuleManager::e_module_port_type port_type =
|
||||
ModuleManager::e_module_port_type::MODULE_INOUT_PORT;
|
||||
if (IoNameMap::e_dummy_port_direction::INPUT ==
|
||||
io_naming.fpga_top_dummy_port_direction(top_port)) {
|
||||
port_type = ModuleManager::e_module_port_type::MODULE_INPUT_PORT;
|
||||
} else if (IoNameMap::e_dummy_port_direction::OUTPUT == io_naming.fpga_top_dummy_port_direction(top_port)) {
|
||||
} else if (IoNameMap::e_dummy_port_direction::OUTPUT ==
|
||||
io_naming.fpga_top_dummy_port_direction(top_port)) {
|
||||
port_type = ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT;
|
||||
} else if (IoNameMap::e_dummy_port_direction::INOUT == io_naming.fpga_top_dummy_port_direction(top_port));
|
||||
} else if (IoNameMap::e_dummy_port_direction::INOUT ==
|
||||
io_naming.fpga_top_dummy_port_direction(top_port)) {
|
||||
port_type = ModuleManager::e_module_port_type::MODULE_INOUT_PORT;
|
||||
} else {
|
||||
VTR_LOG_ERROR("fpga_top dummy port '%s' has an invalid direction. Expect [input|output|inout]!\n", top_port.to_verilog_string().c_str());
|
||||
VTR_LOG_ERROR(
|
||||
"fpga_top dummy port '%s' has an invalid direction. Expect "
|
||||
"[input|output|inout]!\n",
|
||||
top_port.to_verilog_string().c_str());
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
module_manager.add_port(wrapper_module, top_port, port_type);
|
||||
continue; /* Finish for this port addition */
|
||||
}
|
||||
/* Get the port type which should be same as the fpga_core port */
|
||||
BasicPort core_port : io_naming.fpga_core_port(top_port);
|
||||
BasicPort core_port = io_naming.fpga_core_port(top_port);
|
||||
if (!core_port.is_valid()) {
|
||||
VTR_LOG_ERROR("fpga_top port '%s' is not mapped to any fpga_core port!\n", core_port.to_verilog_string().c_str());
|
||||
VTR_LOG_ERROR("fpga_top port '%s' is not mapped to any fpga_core port!\n",
|
||||
core_port.to_verilog_string().c_str());
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
//module_manager.add_port(wrapper_module, top_port, );
|
||||
// module_manager.add_port(wrapper_module, top_port, );
|
||||
}
|
||||
|
||||
/* TODO: Add nets */
|
||||
if (add_nets) {
|
||||
|
||||
}
|
||||
|
||||
/* TODO: Update the fabric global ports */
|
||||
|
@ -103,7 +108,8 @@ int add_fpga_core_to_device_module_graph(ModuleManager& module_manager,
|
|||
top_module_name.c_str(), core_module_name.c_str());
|
||||
|
||||
/* Create a wrapper module under the existing fpga_top
|
||||
* - if there are no io naming rules, just use the default API to create a wrapper
|
||||
* - if there are no io naming rules, just use the default API to create a
|
||||
* wrapper
|
||||
* - if there are io naming rules, use dedicated function to handle
|
||||
*/
|
||||
ModuleId new_top_module;
|
||||
|
@ -117,7 +123,9 @@ int add_fpga_core_to_device_module_graph(ModuleManager& module_manager,
|
|||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
} else {
|
||||
status = create_fpga_top_module_using_naming_rules(module_manager, top_module, top_module_name, io_naming, core_inst_name, !frame_view, verbose);
|
||||
status = create_fpga_top_module_using_naming_rules(
|
||||
module_manager, top_module, top_module_name, io_naming, core_inst_name,
|
||||
!frame_view, verbose);
|
||||
if (CMD_EXEC_SUCCESS != status) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "module_manager.h"
|
||||
#include "io_name_map.h"
|
||||
#include <string>
|
||||
|
||||
#include "io_name_map.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
|
Loading…
Reference in New Issue