[Tool] Upgrade openfpga to support extended global tile port definition
This commit is contained in:
parent
0b74575606
commit
9a441fa5cc
|
@ -30,25 +30,12 @@ static
|
|||
void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
openfpga::TileAnnotation& tile_annotation) {
|
||||
/* We have two mandatory XML attributes
|
||||
* 1. name of the port
|
||||
* 2. name of the tile and ports in the format of <tile_name>.<tile_port_name>
|
||||
/* We have mandatory XML attributes:
|
||||
* - name of the port
|
||||
*/
|
||||
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 */
|
||||
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());
|
||||
TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr);
|
||||
|
||||
/* Report any duplicated port names */
|
||||
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());
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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
|
||||
*******************************************************************/
|
||||
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;
|
||||
|
||||
/* Parse configuration protocol root node */
|
||||
|
|
|
@ -30,16 +30,21 @@ std::string TileAnnotation::global_port_name(const TileGlobalPortId& global_port
|
|||
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));
|
||||
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));
|
||||
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 {
|
||||
VTR_ASSERT(valid_global_port_id(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
|
||||
***********************************************************************/
|
||||
TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name,
|
||||
const std::string& tile_name,
|
||||
const BasicPort& tile_port) {
|
||||
TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name) {
|
||||
/* Ensure that the name is unique */
|
||||
std::map<std::string, TileGlobalPortId>::iterator it = global_port_name2ids_.find(port_name);
|
||||
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());
|
||||
global_port_ids_.push_back(port_id);
|
||||
global_port_names_.push_back(port_name);
|
||||
global_port_tile_names_.push_back(tile_name);
|
||||
global_port_tile_ports_.push_back(tile_port);
|
||||
global_port_tile_names_.emplace_back();
|
||||
global_port_tile_ports_.emplace_back();
|
||||
global_port_tile_coordinates_.emplace_back();
|
||||
global_port_is_clock_.push_back(false);
|
||||
global_port_is_set_.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;
|
||||
}
|
||||
|
||||
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,
|
||||
const bool& is_clock) {
|
||||
VTR_ASSERT(valid_global_port_id(global_port_id));
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <array>
|
||||
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_geometry.h"
|
||||
|
||||
#include "openfpga_port.h"
|
||||
|
||||
|
@ -39,8 +40,9 @@ class TileAnnotation {
|
|||
global_port_range global_ports() const;
|
||||
public: /* Public accessors */
|
||||
std::string global_port_name(const TileGlobalPortId& global_port_id) const;
|
||||
std::string global_port_tile_name(const TileGlobalPortId& global_port_id) const;
|
||||
BasicPort global_port_tile_port(const TileGlobalPortId& global_port_id) const;
|
||||
std::vector<std::string> global_port_tile_names(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_set(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.
|
||||
* Users should set it through the set_global_port_is_clock() function
|
||||
*/
|
||||
TileGlobalPortId create_global_port(const std::string& port_name,
|
||||
const std::string& tile_name,
|
||||
const BasicPort& tile_port);
|
||||
TileGlobalPortId create_global_port(const std::string& port_name);
|
||||
/* Add tile port information */
|
||||
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,
|
||||
const bool& is_clock);
|
||||
void set_global_port_is_set(const TileGlobalPortId& global_port_id,
|
||||
|
@ -70,8 +75,9 @@ class TileAnnotation {
|
|||
/* Global port information for tiles */
|
||||
vtr::vector<TileGlobalPortId, TileGlobalPortId> global_port_ids_;
|
||||
vtr::vector<TileGlobalPortId, std::string> global_port_names_;
|
||||
vtr::vector<TileGlobalPortId, std::string> global_port_tile_names_;
|
||||
vtr::vector<TileGlobalPortId, BasicPort> global_port_tile_ports_;
|
||||
vtr::vector<TileGlobalPortId, std::vector<std::string>> global_port_tile_names_;
|
||||
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_reset_;
|
||||
vtr::vector<TileGlobalPortId, bool> global_port_is_set_;
|
||||
|
|
|
@ -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());
|
||||
|
||||
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_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));
|
||||
|
||||
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>";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -695,27 +695,36 @@ void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager,
|
|||
* that are defined as global in tile annotation
|
||||
*******************************************************************/
|
||||
static
|
||||
void build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const ModulePortId& top_module_port,
|
||||
const TileAnnotation& tile_annotation,
|
||||
const TileGlobalPortId& tile_global_port,
|
||||
const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& grid_coordinate,
|
||||
const e_side& border_side,
|
||||
const vtr::Matrix<size_t>& grid_instance_ids) {
|
||||
int build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const ModulePortId& top_module_port,
|
||||
const TileAnnotation& tile_annotation,
|
||||
const TileGlobalPortId& tile_global_port,
|
||||
const BasicPort& tile_port_to_connect,
|
||||
const DeviceGrid& grids,
|
||||
const vtr::Point<size_t>& grid_coordinate,
|
||||
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;
|
||||
/* 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 */
|
||||
int grid_pin_index = physical_tile->num_pins;
|
||||
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!!! */
|
||||
VTR_ASSERT(size_t(tile_port.num_pins) == tile_annotation.global_port_tile_port(tile_global_port).get_width());
|
||||
/* TODO: Should check there is only port matching!!! */
|
||||
if (false == ref_tile_port.contained(tile_port_to_connect)) {
|
||||
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;
|
||||
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,
|
||||
top_module, 0, top_module_port,
|
||||
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 DeviceGrid& grids,
|
||||
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
|
||||
*/
|
||||
std::vector<BasicPort> global_ports_to_add;
|
||||
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));
|
||||
/* The global port size is derived from the maximum port size among all the tile port defintion */
|
||||
if (ModulePortId::INVALID() == module_port) {
|
||||
BasicPort global_port_to_add;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
VTR_ASSERT(ModulePortId::INVALID() != top_module_port);
|
||||
|
||||
/* Spot the port from child modules from core grids */
|
||||
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
|
||||
for (size_t iy = 1; iy < grids.height() - 1; ++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;
|
||||
}
|
||||
for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); ++tile_info_id) {
|
||||
std::string tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id];
|
||||
BasicPort tile_port = tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id];
|
||||
/* Find the coordinates for the wanted tiles */
|
||||
vtr::Point<size_t> start_coord(1, 1);
|
||||
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];
|
||||
bool out_of_range = false;
|
||||
|
||||
/* Bypass the tiles whose names do not match */
|
||||
if (std::string(grids[ix][iy].type->name) != tile_annotation.global_port_tile_name(tile_global_port)) {
|
||||
continue;
|
||||
/* -1 means all the x should be considered */
|
||||
if (size_t(-1) != range.x()) {
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
/* -1 means all the y should be considered */
|
||||
if (size_t(-1) != range.y()) {
|
||||
if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) {
|
||||
out_of_range = true;
|
||||
} else {
|
||||
/* 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) */
|
||||
if ( (0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset)
|
||||
|| (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) {
|
||||
continue;
|
||||
}
|
||||
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
|
||||
if ( (0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset)
|
||||
|| (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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)) {
|
||||
continue;
|
||||
}
|
||||
/* Bypass the tiles whose names do not match */
|
||||
if (std::string(grids[io_coordinate.x()][io_coordinate.y()].type->name) != tile_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
io_coordinate,
|
||||
io_side,
|
||||
grid_instance_ids);
|
||||
/* Check if the coordinate satisfy the tile coordinate defintion
|
||||
* - Bypass if the x is a specific number (!= -1), and io_coordinate is different
|
||||
* - Bypass if the y is a specific number (!= -1), and io_coordinate is different
|
||||
*/
|
||||
if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) {
|
||||
continue;
|
||||
}
|
||||
if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) {
|
||||
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,
|
||||
io_coordinate,
|
||||
io_side,
|
||||
grid_instance_ids);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -21,6 +21,9 @@ FabricBitstream::FabricBitstream() {
|
|||
|
||||
num_regions_ = 0;
|
||||
invalid_region_ids_.clear();
|
||||
|
||||
use_address_ = false;
|
||||
use_wl_address_ = false;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
|
|
|
@ -102,107 +102,125 @@ int check_tile_annotation_conflicts_with_physical_tile(const TileAnnotation& til
|
|||
int num_err = 0;
|
||||
|
||||
for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) {
|
||||
/* Must find a valid physical tile in the same name */
|
||||
size_t found_matched_physical_tile = 0;
|
||||
size_t found_matched_physical_tile_port = 0;
|
||||
for (const t_physical_tile_type& physical_tile : physical_tile_types) {
|
||||
if (std::string(physical_tile.name) != tile_annotation.global_port_tile_name(tile_global_port)) {
|
||||
continue;
|
||||
}
|
||||
for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); ++tile_info_id) {
|
||||
/* Must find a valid physical tile in the same name */
|
||||
size_t found_matched_physical_tile = 0;
|
||||
size_t found_matched_physical_tile_port = 0;
|
||||
|
||||
/* Found a match, increment the counter */
|
||||
found_matched_physical_tile++;
|
||||
std::string required_tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id];
|
||||
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_port& tile_port : physical_tile.ports) {
|
||||
if (std::string(tile_port.name) != tile_annotation.global_port_tile_port(tile_global_port).get_name()) {
|
||||
for (const t_physical_tile_type& physical_tile : physical_tile_types) {
|
||||
if (std::string(physical_tile.name) != required_tile_name) {
|
||||
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 (0 == found_matched_physical_tile) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"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(),
|
||||
tile_annotation.global_port_name(tile_global_port).c_str());
|
||||
num_err++;
|
||||
}
|
||||
if (0 == found_matched_physical_tile_port) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"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(),
|
||||
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());
|
||||
num_err++;
|
||||
}
|
||||
/* If we found no match, error out */
|
||||
if (0 == found_matched_physical_tile) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"Tile name '%s' in tile annotation '%s' does not match any physical tile!\n",
|
||||
required_tile_name.c_str(),
|
||||
tile_annotation.global_port_name(tile_global_port).c_str());
|
||||
num_err++;
|
||||
}
|
||||
if (0 == found_matched_physical_tile_port) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile 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());
|
||||
num_err++;
|
||||
}
|
||||
|
||||
/* If we found more than 1 match, error out */
|
||||
if (1 < found_matched_physical_tile) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"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(),
|
||||
tile_annotation.global_port_name(tile_global_port).c_str());
|
||||
num_err++;
|
||||
}
|
||||
if (1 < found_matched_physical_tile_port) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1physical tile 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());
|
||||
num_err++;
|
||||
/* If we found more than 1 match, error out */
|
||||
if (1 < found_matched_physical_tile) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n",
|
||||
required_tile_name.c_str(),
|
||||
tile_annotation.global_port_name(tile_global_port).c_str());
|
||||
num_err++;
|
||||
}
|
||||
if (1 < found_matched_physical_tile_port) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1 physical tile 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());
|
||||
num_err++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue