[Tool] Upgrade openfpga to support extended global tile port definition

This commit is contained in:
tangxifan 2021-01-09 18:47:12 -07:00
parent 0b74575606
commit 9a441fa5cc
7 changed files with 353 additions and 201 deletions

View File

@ -30,25 +30,12 @@ static
void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile, void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
const pugiutil::loc_data& loc_data, const pugiutil::loc_data& loc_data,
openfpga::TileAnnotation& tile_annotation) { openfpga::TileAnnotation& tile_annotation) {
/* We have two mandatory XML attributes /* We have mandatory XML attributes:
* 1. name of the port * - name of the port
* 2. name of the tile and ports in the format of <tile_name>.<tile_port_name>
*/ */
const std::string& name_attr = get_attribute(xml_tile, "name", loc_data).as_string(); const std::string& name_attr = get_attribute(xml_tile, "name", loc_data).as_string();
const std::string& tile_port_name_attr = get_attribute(xml_tile, "tile_port", loc_data).as_string();
/* Extract the tile name */ TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr);
openfpga::StringToken tokenizer(tile_port_name_attr);
std::vector<std::string> tile_port_tokens = tokenizer.split('.');
if (2 != tile_port_tokens.size()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
"Invalid tile_port attribute '%s'! Valid format is <tile_name>.<port_name>\n",
tile_port_name_attr.c_str());
}
/* Extract the tile port information */
openfpga::PortParser tile_port_parser(tile_port_tokens[1]);
TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr, tile_port_tokens[0], tile_port_parser.port());
/* Report any duplicated port names */ /* Report any duplicated port names */
if (TileGlobalPortId::INVALID() == tile_global_port_id) { if (TileGlobalPortId::INVALID() == tile_global_port_id) {
@ -57,6 +44,39 @@ void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
name_attr.c_str()); name_attr.c_str());
} }
/* Iterate over the children under this node,
* each child should be named after <pb_type>
*/
for (pugi::xml_node xml_tile_port : xml_tile.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_tile_port.name() != std::string("tile")) {
bad_tag(xml_tile_port, loc_data, xml_tile, {"tile"});
}
/* Parse the name of the tiles and ports */
const std::string& tile_name_attr = get_attribute(xml_tile_port, "name", loc_data).as_string();
const std::string& port_name_attr = get_attribute(xml_tile_port, "port", loc_data).as_string();
/* Extract the tile port information */
openfpga::PortParser tile_port_parser(port_name_attr);
/* Parse tile coordinates */
vtr::Point<size_t> tile_coord(get_attribute(xml_tile_port, "x", loc_data).as_int(-1),
get_attribute(xml_tile_port, "y", loc_data).as_int(-1));
/* Add tile port information */
tile_annotation.add_global_port_tile_information(tile_global_port_id,
tile_name_attr,
tile_port_parser.port(),
tile_coord);
}
/* Check: Must have at least one global port tile information */
if (true == tile_annotation.global_port_tile_names(tile_global_port_id).empty()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
"Invalid tile annotation for global port '%s'! At least 1 tile port definition is expected!\n",
name_attr.c_str());
}
/* Get is_clock attributes */ /* Get is_clock attributes */
tile_annotation.set_global_port_is_clock(tile_global_port_id, get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); tile_annotation.set_global_port_is_clock(tile_global_port_id, get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
@ -81,7 +101,7 @@ void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
* Top function to parse XML description about tile annotation * Top function to parse XML description about tile annotation
*******************************************************************/ *******************************************************************/
openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node, openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data) { const pugiutil::loc_data& loc_data) {
openfpga::TileAnnotation tile_annotations; openfpga::TileAnnotation tile_annotations;
/* Parse configuration protocol root node */ /* Parse configuration protocol root node */

View File

@ -30,16 +30,21 @@ std::string TileAnnotation::global_port_name(const TileGlobalPortId& global_port
return global_port_names_[global_port_id]; return global_port_names_[global_port_id];
} }
std::string TileAnnotation::global_port_tile_name(const TileGlobalPortId& global_port_id) const { std::vector<std::string> TileAnnotation::global_port_tile_names(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id)); VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_tile_names_[global_port_id]; return global_port_tile_names_[global_port_id];
} }
BasicPort TileAnnotation::global_port_tile_port(const TileGlobalPortId& global_port_id) const { std::vector<BasicPort> TileAnnotation::global_port_tile_ports(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id)); VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_tile_ports_[global_port_id]; return global_port_tile_ports_[global_port_id];
} }
std::vector<vtr::Point<size_t>> TileAnnotation::global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_tile_coordinates_[global_port_id];
}
bool TileAnnotation::global_port_is_clock(const TileGlobalPortId& global_port_id) const { bool TileAnnotation::global_port_is_clock(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id)); VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_clock_[global_port_id]; return global_port_is_clock_[global_port_id];
@ -63,9 +68,7 @@ size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_
/************************************************************************ /************************************************************************
* Public Mutators * Public Mutators
***********************************************************************/ ***********************************************************************/
TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name, TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name) {
const std::string& tile_name,
const BasicPort& tile_port) {
/* Ensure that the name is unique */ /* Ensure that the name is unique */
std::map<std::string, TileGlobalPortId>::iterator it = global_port_name2ids_.find(port_name); std::map<std::string, TileGlobalPortId>::iterator it = global_port_name2ids_.find(port_name);
if (it != global_port_name2ids_.end()) { if (it != global_port_name2ids_.end()) {
@ -76,8 +79,9 @@ TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name
TileGlobalPortId port_id = TileGlobalPortId(global_port_ids_.size()); TileGlobalPortId port_id = TileGlobalPortId(global_port_ids_.size());
global_port_ids_.push_back(port_id); global_port_ids_.push_back(port_id);
global_port_names_.push_back(port_name); global_port_names_.push_back(port_name);
global_port_tile_names_.push_back(tile_name); global_port_tile_names_.emplace_back();
global_port_tile_ports_.push_back(tile_port); global_port_tile_ports_.emplace_back();
global_port_tile_coordinates_.emplace_back();
global_port_is_clock_.push_back(false); global_port_is_clock_.push_back(false);
global_port_is_set_.push_back(false); global_port_is_set_.push_back(false);
global_port_is_reset_.push_back(false); global_port_is_reset_.push_back(false);
@ -89,6 +93,16 @@ TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name
return port_id; return port_id;
} }
void TileAnnotation::add_global_port_tile_information(const TileGlobalPortId& global_port_id,
const std::string& tile_name,
const BasicPort& tile_port,
const vtr::Point<size_t>& tile_coord) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_tile_names_[global_port_id].push_back(tile_name);
global_port_tile_ports_[global_port_id].push_back(tile_port);
global_port_tile_coordinates_[global_port_id].push_back(tile_coord);
}
void TileAnnotation::set_global_port_is_clock(const TileGlobalPortId& global_port_id, void TileAnnotation::set_global_port_is_clock(const TileGlobalPortId& global_port_id,
const bool& is_clock) { const bool& is_clock) {
VTR_ASSERT(valid_global_port_id(global_port_id)); VTR_ASSERT(valid_global_port_id(global_port_id));

View File

@ -9,6 +9,7 @@
#include <array> #include <array>
#include "vtr_vector.h" #include "vtr_vector.h"
#include "vtr_geometry.h"
#include "openfpga_port.h" #include "openfpga_port.h"
@ -39,8 +40,9 @@ class TileAnnotation {
global_port_range global_ports() const; global_port_range global_ports() const;
public: /* Public accessors */ public: /* Public accessors */
std::string global_port_name(const TileGlobalPortId& global_port_id) const; std::string global_port_name(const TileGlobalPortId& global_port_id) const;
std::string global_port_tile_name(const TileGlobalPortId& global_port_id) const; std::vector<std::string> global_port_tile_names(const TileGlobalPortId& global_port_id) const;
BasicPort global_port_tile_port(const TileGlobalPortId& global_port_id) const; std::vector<BasicPort> global_port_tile_ports(const TileGlobalPortId& global_port_id) const;
std::vector<vtr::Point<size_t>> global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const;
bool global_port_is_clock(const TileGlobalPortId& global_port_id) const; bool global_port_is_clock(const TileGlobalPortId& global_port_id) const;
bool global_port_is_set(const TileGlobalPortId& global_port_id) const; bool global_port_is_set(const TileGlobalPortId& global_port_id) const;
bool global_port_is_reset(const TileGlobalPortId& global_port_id) const; bool global_port_is_reset(const TileGlobalPortId& global_port_id) const;
@ -49,9 +51,12 @@ class TileAnnotation {
/* By default, we do not set it as a clock. /* By default, we do not set it as a clock.
* Users should set it through the set_global_port_is_clock() function * Users should set it through the set_global_port_is_clock() function
*/ */
TileGlobalPortId create_global_port(const std::string& port_name, TileGlobalPortId create_global_port(const std::string& port_name);
const std::string& tile_name, /* Add tile port information */
const BasicPort& tile_port); void add_global_port_tile_information(const TileGlobalPortId& global_port_id,
const std::string& tile_name,
const BasicPort& tile_port,
const vtr::Point<size_t>& tile_coord);
void set_global_port_is_clock(const TileGlobalPortId& global_port_id, void set_global_port_is_clock(const TileGlobalPortId& global_port_id,
const bool& is_clock); const bool& is_clock);
void set_global_port_is_set(const TileGlobalPortId& global_port_id, void set_global_port_is_set(const TileGlobalPortId& global_port_id,
@ -70,8 +75,9 @@ class TileAnnotation {
/* Global port information for tiles */ /* Global port information for tiles */
vtr::vector<TileGlobalPortId, TileGlobalPortId> global_port_ids_; vtr::vector<TileGlobalPortId, TileGlobalPortId> global_port_ids_;
vtr::vector<TileGlobalPortId, std::string> global_port_names_; vtr::vector<TileGlobalPortId, std::string> global_port_names_;
vtr::vector<TileGlobalPortId, std::string> global_port_tile_names_; vtr::vector<TileGlobalPortId, std::vector<std::string>> global_port_tile_names_;
vtr::vector<TileGlobalPortId, BasicPort> global_port_tile_ports_; vtr::vector<TileGlobalPortId, std::vector<vtr::Point<size_t>>> global_port_tile_coordinates_;
vtr::vector<TileGlobalPortId, std::vector<BasicPort>> global_port_tile_ports_;
vtr::vector<TileGlobalPortId, bool> global_port_is_clock_; vtr::vector<TileGlobalPortId, bool> global_port_is_clock_;
vtr::vector<TileGlobalPortId, bool> global_port_is_reset_; vtr::vector<TileGlobalPortId, bool> global_port_is_reset_;
vtr::vector<TileGlobalPortId, bool> global_port_is_set_; vtr::vector<TileGlobalPortId, bool> global_port_is_set_;

View File

@ -51,11 +51,6 @@ void write_xml_tile_annotation_global_port(std::fstream& fp,
write_xml_attribute(fp, "name", tile_annotation.global_port_name(global_port_id).c_str()); write_xml_attribute(fp, "name", tile_annotation.global_port_name(global_port_id).c_str());
std::string tile_port_attr = tile_annotation.global_port_tile_name(global_port_id)
+ "."
+ generate_tile_port_name(tile_annotation.global_port_tile_port(global_port_id));
write_xml_attribute(fp, "tile_port", tile_port_attr.c_str());
write_xml_attribute(fp, "is_clock", tile_annotation.global_port_is_clock(global_port_id)); write_xml_attribute(fp, "is_clock", tile_annotation.global_port_is_clock(global_port_id));
write_xml_attribute(fp, "is_set", tile_annotation.global_port_is_set(global_port_id)); write_xml_attribute(fp, "is_set", tile_annotation.global_port_is_set(global_port_id));
@ -64,7 +59,18 @@ void write_xml_tile_annotation_global_port(std::fstream& fp,
write_xml_attribute(fp, "default_value", tile_annotation.global_port_default_value(global_port_id)); write_xml_attribute(fp, "default_value", tile_annotation.global_port_default_value(global_port_id));
fp << "/>" << "\n"; fp << ">" << "\n";
for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(global_port_id).size(); ++tile_info_id) {
fp << "\t\t\t" << "<tile ";
write_xml_attribute(fp, "name", tile_annotation.global_port_tile_names(global_port_id)[tile_info_id].c_str());
write_xml_attribute(fp, "port", generate_tile_port_name(tile_annotation.global_port_tile_ports(global_port_id)[tile_info_id]).c_str());
write_xml_attribute(fp, "x", tile_annotation.global_port_tile_coordinates(global_port_id)[tile_info_id].x());
write_xml_attribute(fp, "y", tile_annotation.global_port_tile_coordinates(global_port_id)[tile_info_id].y());
fp << "/>";
}
fp << "\t\t" << "</global_port>";
} }
/******************************************************************** /********************************************************************

View File

@ -695,27 +695,36 @@ void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager,
* that are defined as global in tile annotation * that are defined as global in tile annotation
*******************************************************************/ *******************************************************************/
static static
void build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager, int build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager,
const ModuleId& top_module, const ModuleId& top_module,
const ModulePortId& top_module_port, const ModulePortId& top_module_port,
const TileAnnotation& tile_annotation, const TileAnnotation& tile_annotation,
const TileGlobalPortId& tile_global_port, const TileGlobalPortId& tile_global_port,
const DeviceGrid& grids, const BasicPort& tile_port_to_connect,
const vtr::Point<size_t>& grid_coordinate, const DeviceGrid& grids,
const e_side& border_side, const vtr::Point<size_t>& grid_coordinate,
const vtr::Matrix<size_t>& grid_instance_ids) { const e_side& border_side,
const vtr::Matrix<size_t>& grid_instance_ids) {
t_physical_tile_type_ptr physical_tile = grids[grid_coordinate.x()][grid_coordinate.y()].type; t_physical_tile_type_ptr physical_tile = grids[grid_coordinate.x()][grid_coordinate.y()].type;
/* Ensure physical tile matches the global port definition */
VTR_ASSERT(std::string(physical_tile->name) == tile_annotation.global_port_tile_name(tile_global_port));
/* Find the port of the grid module according to the tile annotation */ /* Find the port of the grid module according to the tile annotation */
int grid_pin_index = physical_tile->num_pins; int grid_pin_index = physical_tile->num_pins;
for (const t_physical_tile_port& tile_port : physical_tile->ports) { for (const t_physical_tile_port& tile_port : physical_tile->ports) {
if (std::string(tile_port.name) == tile_annotation.global_port_tile_port(tile_global_port).get_name()) { if (std::string(tile_port.name) == tile_port_to_connect.get_name()) {
BasicPort ref_tile_port(tile_port.name, tile_port.num_pins);
/* Port size must match!!! */ /* Port size must match!!! */
VTR_ASSERT(size_t(tile_port.num_pins) == tile_annotation.global_port_tile_port(tile_global_port).get_width()); if (false == ref_tile_port.contained(tile_port_to_connect)) {
/* TODO: Should check there is only port matching!!! */ VTR_LOG_ERROR("Tile annotation '%s' port '%s[%lu:%lu]' is out of the range of physical tile port '%s[%lu:%lu]'!",
tile_annotation.global_port_name(tile_global_port).c_str(),
tile_port_to_connect.get_name().c_str(),
tile_port_to_connect.get_lsb(),
tile_port_to_connect.get_msb(),
ref_tile_port.get_name().c_str(),
ref_tile_port.get_lsb(),
ref_tile_port.get_msb());
return CMD_EXEC_FATAL_ERROR;
}
grid_pin_index = tile_port.absolute_first_pin_index; grid_pin_index = tile_port.absolute_first_pin_index;
break; break;
} }
@ -746,7 +755,19 @@ void build_top_module_global_net_for_given_grid_module(ModuleManager& module_man
add_module_bus_nets(module_manager, top_module, add_module_bus_nets(module_manager, top_module,
top_module, 0, top_module_port, top_module, 0, top_module_port,
grid_module, grid_instance, grid_port_id); grid_module, grid_instance, grid_port_id);
BasicPort src_port = module_manager.module_port(top_module, top_module_port);
for (size_t pin_id = 0; pin_id < tile_port_to_connect.pins().size(); ++pin_id) {
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
top_module, 0,
top_module_port, src_port.pins()[pin_id]);
VTR_ASSERT(ModuleNetId::INVALID() != net);
/* Configure the net sink */
module_manager.add_module_net_sink(top_module, net, grid_module, grid_instance, grid_port_id, tile_port_to_connect.pins()[pin_id]);
}
} }
return CMD_EXEC_SUCCESS;
} }
/******************************************************************** /********************************************************************
@ -757,17 +778,23 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager,
const TileAnnotation& tile_annotation, const TileAnnotation& tile_annotation,
const DeviceGrid& grids, const DeviceGrid& grids,
const vtr::Matrix<size_t>& grid_instance_ids) { const vtr::Matrix<size_t>& grid_instance_ids) {
int status = CMD_EXEC_SUCCESS;
/* Add the global ports which are yet added to the top-level module /* Add the global ports which are NOT yet added to the top-level module
* (in different names than the global ports defined in circuit library * (in different names than the global ports defined in circuit library
*/ */
std::vector<BasicPort> global_ports_to_add; std::vector<BasicPort> global_ports_to_add;
for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) {
ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port)); ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port));
/* The global port size is derived from the maximum port size among all the tile port defintion */
if (ModulePortId::INVALID() == module_port) { if (ModulePortId::INVALID() == module_port) {
BasicPort global_port_to_add; BasicPort global_port_to_add;
global_port_to_add.set_name(tile_annotation.global_port_name(tile_global_port)); global_port_to_add.set_name(tile_annotation.global_port_name(tile_global_port));
global_port_to_add.set_width(tile_annotation.global_port_tile_port(tile_global_port).get_width()); size_t max_port_size = 0;
for (const BasicPort& tile_port : tile_annotation.global_port_tile_ports(tile_global_port)) {
max_port_size = std::max(tile_port.get_width(), max_port_size);
}
global_port_to_add.set_width(max_port_size);
global_ports_to_add.push_back(global_port_to_add); global_ports_to_add.push_back(global_port_to_add);
} }
} }
@ -784,72 +811,130 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager,
ModulePortId top_module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port)); ModulePortId top_module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port));
VTR_ASSERT(ModulePortId::INVALID() != top_module_port); VTR_ASSERT(ModulePortId::INVALID() != top_module_port);
/* Spot the port from child modules from core grids */ for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); ++tile_info_id) {
for (size_t ix = 1; ix < grids.width() - 1; ++ix) { std::string tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id];
for (size_t iy = 1; iy < grids.height() - 1; ++iy) { BasicPort tile_port = tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id];
/* Bypass EMPTY tiles */ /* Find the coordinates for the wanted tiles */
if (true == is_empty_type(grids[ix][iy].type)) { vtr::Point<size_t> start_coord(1, 1);
continue; vtr::Point<size_t> end_coord(grids.width() - 1, grids.height() - 1);
} vtr::Point<size_t> range = tile_annotation.global_port_tile_coordinates(tile_global_port)[tile_info_id];
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ bool out_of_range = false;
if ( (0 < grids[ix][iy].width_offset)
|| (0 < grids[ix][iy].height_offset)) {
continue;
}
/* Bypass the tiles whose names do not match */ /* -1 means all the x should be considered */
if (std::string(grids[ix][iy].type->name) != tile_annotation.global_port_tile_name(tile_global_port)) { if (size_t(-1) != range.x()) {
continue; if ((range.x() < start_coord.x()) || (range.x() > end_coord.x())) {
out_of_range = true;
} else {
/* Set the range */
start_coord.set_x(range.x());
end_coord.set_x(range.x());
} }
/* Create nets and finish connection build-up */
build_top_module_global_net_for_given_grid_module(module_manager,
top_module,
top_module_port,
tile_annotation,
tile_global_port,
grids,
vtr::Point<size_t>(ix, iy),
NUM_SIDES,
grid_instance_ids);
} }
}
/* Walk through all the grids on the perimeter, which are I/O grids */ /* -1 means all the y should be considered */
for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { if (size_t(-1) != range.y()) {
for (const vtr::Point<size_t>& io_coordinate : io_coordinates[io_side]) { if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) {
/* Bypass EMPTY grid */ out_of_range = true;
if (true == is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { } else {
continue; /* Set the range */
} start_coord.set_y(range.y());
end_coord.set_y(range.y());
}
}
/* Error out immediately if the coordinate is not valid! */
if (true == out_of_range) {
VTR_LOG_ERROR("Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of range (%lu:%lu, %lu:%lu)!",
range.x(), range.y(), tile_name.c_str(),
start_coord.x(), end_coord.x(), start_coord.y(), end_coord.y());
return CMD_EXEC_FATAL_ERROR;
}
/* Spot the port from child modules from core grids */
for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) {
for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) {
/* Bypass EMPTY tiles */
if (true == is_empty_type(grids[ix][iy].type)) {
continue;
}
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
if ( (0 < grids[ix][iy].width_offset)
|| (0 < grids[ix][iy].height_offset)) {
continue;
}
/* Bypass the tiles whose names do not match */
if (std::string(grids[ix][iy].type->name) != tile_name) {
continue;
}
/* Create nets and finish connection build-up */
status = build_top_module_global_net_for_given_grid_module(module_manager,
top_module,
top_module_port,
tile_annotation,
tile_global_port,
tile_port,
grids,
vtr::Point<size_t>(ix, iy),
NUM_SIDES,
grid_instance_ids);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
}
}
/* Walk through all the grids on the perimeter, which are I/O grids */
for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) {
for (const vtr::Point<size_t>& io_coordinate : io_coordinates[io_side]) {
/* Bypass EMPTY grid */
if (true == is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) {
continue;
}
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
if ( (0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) if ( (0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset)
|| (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { || (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) {
continue; continue;
} }
/* Bypass the tiles whose names do not match */ /* Bypass the tiles whose names do not match */
if (std::string(grids[io_coordinate.x()][io_coordinate.y()].type->name) != tile_annotation.global_port_tile_name(tile_global_port)) { if (std::string(grids[io_coordinate.x()][io_coordinate.y()].type->name) != tile_name) {
continue; continue;
} }
/* Create nets and finish connection build-up */ /* Check if the coordinate satisfy the tile coordinate defintion
build_top_module_global_net_for_given_grid_module(module_manager, * - Bypass if the x is a specific number (!= -1), and io_coordinate is different
top_module, * - Bypass if the y is a specific number (!= -1), and io_coordinate is different
top_module_port, */
tile_annotation, if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) {
tile_global_port, continue;
grids, }
io_coordinate, if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) {
io_side, continue;
grid_instance_ids); }
/* Create nets and finish connection build-up */
status = build_top_module_global_net_for_given_grid_module(module_manager,
top_module,
top_module_port,
tile_annotation,
tile_global_port,
tile_port,
grids,
io_coordinate,
io_side,
grid_instance_ids);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
}
} }
} }
} }
return CMD_EXEC_SUCCESS; return status;
} }
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -21,6 +21,9 @@ FabricBitstream::FabricBitstream() {
num_regions_ = 0; num_regions_ = 0;
invalid_region_ids_.clear(); invalid_region_ids_.clear();
use_address_ = false;
use_wl_address_ = false;
} }
/************************************************** /**************************************************

View File

@ -102,107 +102,125 @@ int check_tile_annotation_conflicts_with_physical_tile(const TileAnnotation& til
int num_err = 0; int num_err = 0;
for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) {
/* Must find a valid physical tile in the same name */ for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); ++tile_info_id) {
size_t found_matched_physical_tile = 0; /* Must find a valid physical tile in the same name */
size_t found_matched_physical_tile_port = 0; size_t found_matched_physical_tile = 0;
for (const t_physical_tile_type& physical_tile : physical_tile_types) { size_t found_matched_physical_tile_port = 0;
if (std::string(physical_tile.name) != tile_annotation.global_port_tile_name(tile_global_port)) {
continue;
}
/* Found a match, increment the counter */ std::string required_tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id];
found_matched_physical_tile++; BasicPort required_tile_port = tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id];
/* Must found a valid port where both port name and port size must match!!! */ for (const t_physical_tile_type& physical_tile : physical_tile_types) {
for (const t_physical_tile_port& tile_port : physical_tile.ports) { if (std::string(physical_tile.name) != required_tile_name) {
if (std::string(tile_port.name) != tile_annotation.global_port_tile_port(tile_global_port).get_name()) {
continue; continue;
} }
if (size_t(tile_port.num_pins) != tile_annotation.global_port_tile_port(tile_global_port).get_width()) {
continue; /* Found a match, increment the counter */
found_matched_physical_tile++;
/* Must found a valid port where both port name and port size must match!!! */
for (const t_physical_tile_port& tile_port : physical_tile.ports) {
if (std::string(tile_port.name) != required_tile_port.get_name()) {
continue;
}
BasicPort ref_tile_port(tile_port.name, tile_port.num_pins);
/* Port size must be in range!!! */
if (false == ref_tile_port.contained(required_tile_port)) {
VTR_LOG_ERROR("Tile annotation port '%s[%lu:%lu]' is out of the range of physical tile port '%s[%lu:%lu]'!",
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
ref_tile_port.get_name().c_str(),
ref_tile_port.get_lsb(),
ref_tile_port.get_msb());
num_err++;
continue;
}
/* Check if port property matches */
int grid_pin_index = tile_port.absolute_first_pin_index;
if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match physical tile port %s.%s in clock property (one is defined as clock while the other is not)!\n",
required_tile_name.c_str(),
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name);
num_err++;
}
if ((false == tile_port.is_clock)
&& (false == tile_port.is_non_clock_global)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but is not defined as a non-clock global port!\n",
required_tile_name.c_str(),
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name);
num_err++;
}
float pin_Fc = find_physical_tile_pin_Fc(&physical_tile, grid_pin_index);
if (0. != pin_Fc) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but its Fc is not zero '%g' !\n",
required_tile_name.c_str(),
required_tile_port.get_name().c_str(),
required_tile_port.get_lsb(),
required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name, pin_Fc);
}
found_matched_physical_tile_port++;
} }
/* Check if port property matches */
int grid_pin_index = tile_port.absolute_first_pin_index;
if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match physical tile port %s.%s in clock property (one is defined as clock while the other is not)!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name);
num_err++;
}
if ((false == tile_port.is_clock)
&& (false == tile_port.is_non_clock_global)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but is not defined as a non-clock global port!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name);
num_err++;
}
float pin_Fc = find_physical_tile_pin_Fc(&physical_tile, grid_pin_index);
if (0. != pin_Fc) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but its Fc is not zero '%g' !\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str(),
physical_tile.name, tile_port.name, pin_Fc);
}
found_matched_physical_tile_port++;
} }
}
/* If we found no match, error out */ /* If we found no match, error out */
if (0 == found_matched_physical_tile) { if (0 == found_matched_physical_tile) {
VTR_LOGF_ERROR(__FILE__, __LINE__, VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile name '%s' in tile annotation '%s' does not match any physical tile!\n", "Tile name '%s' in tile annotation '%s' does not match any physical tile!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(), required_tile_name.c_str(),
tile_annotation.global_port_name(tile_global_port).c_str()); tile_annotation.global_port_name(tile_global_port).c_str());
num_err++; num_err++;
} }
if (0 == found_matched_physical_tile_port) { if (0 == found_matched_physical_tile_port) {
VTR_LOGF_ERROR(__FILE__, __LINE__, VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile port!\n", "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile port!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(), required_tile_name.c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), required_tile_port.get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), required_tile_port.get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(), required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str()); tile_annotation.global_port_name(tile_global_port).c_str());
num_err++; num_err++;
} }
/* If we found more than 1 match, error out */ /* If we found more than 1 match, error out */
if (1 < found_matched_physical_tile) { if (1 < found_matched_physical_tile) {
VTR_LOGF_ERROR(__FILE__, __LINE__, VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n", "Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(), required_tile_name.c_str(),
tile_annotation.global_port_name(tile_global_port).c_str()); tile_annotation.global_port_name(tile_global_port).c_str());
num_err++; num_err++;
} }
if (1 < found_matched_physical_tile_port) { if (1 < found_matched_physical_tile_port) {
VTR_LOGF_ERROR(__FILE__, __LINE__, VTR_LOGF_ERROR(__FILE__, __LINE__,
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1physical tile port!\n", "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1 physical tile port!\n",
tile_annotation.global_port_tile_name(tile_global_port).c_str(), required_tile_name.c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), required_tile_port.get_name().c_str(),
tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), required_tile_port.get_lsb(),
tile_annotation.global_port_tile_port(tile_global_port).get_msb(), required_tile_port.get_msb(),
tile_annotation.global_port_name(tile_global_port).c_str()); tile_annotation.global_port_name(tile_global_port).c_str());
num_err++; num_err++;
}
} }
} }