bug fixed for routing annotation and routing net fix-up
This commit is contained in:
parent
cccbb9fd49
commit
99f5a86b49
|
@ -19,6 +19,7 @@ set_target_properties(libopenfpgautil PROPERTIES PREFIX "") #Avoid extra 'lib' p
|
||||||
|
|
||||||
#Specify link-time dependancies
|
#Specify link-time dependancies
|
||||||
target_link_libraries(libopenfpgautil
|
target_link_libraries(libopenfpgautil
|
||||||
|
libarchfpga
|
||||||
libvtrutil)
|
libvtrutil)
|
||||||
|
|
||||||
#Create the test executable
|
#Create the test executable
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
/********************************************************************
|
||||||
|
* Memeber function for class SideManagerManager
|
||||||
|
*******************************************************************/
|
||||||
|
#include "openfpga_side_manager.h"
|
||||||
|
|
||||||
|
/* namespace openfpga begins */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/* Constructors */
|
||||||
|
SideManager::SideManager(enum e_side side) {
|
||||||
|
side_ = side;
|
||||||
|
}
|
||||||
|
|
||||||
|
SideManager::SideManager() {
|
||||||
|
side_ = NUM_SIDES;
|
||||||
|
}
|
||||||
|
|
||||||
|
SideManager::SideManager(size_t side) {
|
||||||
|
set_side(side);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Public Accessors */
|
||||||
|
enum e_side SideManager::get_side() const {
|
||||||
|
return side_;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum e_side SideManager::get_opposite() const {
|
||||||
|
switch (side_) {
|
||||||
|
case TOP:
|
||||||
|
return BOTTOM;
|
||||||
|
case RIGHT:
|
||||||
|
return LEFT;
|
||||||
|
case BOTTOM:
|
||||||
|
return TOP;
|
||||||
|
case LEFT:
|
||||||
|
return RIGHT;
|
||||||
|
default:
|
||||||
|
return NUM_SIDES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum e_side SideManager::get_rotate_clockwise() const {
|
||||||
|
switch (side_) {
|
||||||
|
case TOP:
|
||||||
|
return RIGHT;
|
||||||
|
case RIGHT:
|
||||||
|
return BOTTOM;
|
||||||
|
case BOTTOM:
|
||||||
|
return LEFT;
|
||||||
|
case LEFT:
|
||||||
|
return TOP;
|
||||||
|
default:
|
||||||
|
return NUM_SIDES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum e_side SideManager::get_rotate_counterclockwise() const {
|
||||||
|
switch (side_) {
|
||||||
|
case TOP:
|
||||||
|
return LEFT;
|
||||||
|
case RIGHT:
|
||||||
|
return TOP;
|
||||||
|
case BOTTOM:
|
||||||
|
return RIGHT;
|
||||||
|
case LEFT:
|
||||||
|
return BOTTOM;
|
||||||
|
default:
|
||||||
|
return NUM_SIDES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SideManager::validate() const {
|
||||||
|
if (NUM_SIDES == side_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SideManager::to_size_t() const {
|
||||||
|
switch (side_) {
|
||||||
|
case TOP:
|
||||||
|
return 0;
|
||||||
|
case RIGHT:
|
||||||
|
return 1;
|
||||||
|
case BOTTOM:
|
||||||
|
return 2;
|
||||||
|
case LEFT:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert to char* */
|
||||||
|
const char* SideManager::c_str() const {
|
||||||
|
switch (side_) {
|
||||||
|
case TOP:
|
||||||
|
return "top";
|
||||||
|
case RIGHT:
|
||||||
|
return "right";
|
||||||
|
case BOTTOM:
|
||||||
|
return "bottom";
|
||||||
|
case LEFT:
|
||||||
|
return "left";
|
||||||
|
default:
|
||||||
|
return "invalid_side";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert to char* */
|
||||||
|
std::string SideManager::to_string() const {
|
||||||
|
std::string ret;
|
||||||
|
switch (side_) {
|
||||||
|
case TOP:
|
||||||
|
ret.assign("top");
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
ret.assign("right");
|
||||||
|
break;
|
||||||
|
case BOTTOM:
|
||||||
|
ret.assign("bottom");
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
ret.assign("left");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret.assign("invalid_side");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Public Mutators */
|
||||||
|
void SideManager::set_side(size_t side) {
|
||||||
|
switch (side) {
|
||||||
|
case 0:
|
||||||
|
side_ = TOP;
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
side_ = RIGHT;
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
side_ = BOTTOM;
|
||||||
|
return;
|
||||||
|
case 3:
|
||||||
|
side_ = LEFT;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
side_ = NUM_SIDES;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideManager::set_side(enum e_side side) {
|
||||||
|
side_ = side;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideManager::set_opposite() {
|
||||||
|
side_ = get_opposite();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideManager::rotate_clockwise() {
|
||||||
|
side_ = get_rotate_clockwise();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideManager::rotate_counterclockwise() {
|
||||||
|
side_ = get_rotate_counterclockwise();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace openfpga ends */
|
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef OPENFPGA_SIDE_MANAGER_H
|
||||||
|
#define OPENFPGA_SIDE_MANAGER_H
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Include header files that are required by function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/* Header files form archfpga library */
|
||||||
|
#include "physical_types.h"
|
||||||
|
|
||||||
|
/* namespace openfpga begins */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Define a class for the sides of a physical block in FPGA architecture
|
||||||
|
* Basically, each block has four sides :
|
||||||
|
* TOP, RIGHT, BOTTOM, LEFT
|
||||||
|
* This class aims to provide a easy proctol for manipulating a side
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
class SideManager {
|
||||||
|
public: /* Constructor */
|
||||||
|
SideManager(enum e_side side);
|
||||||
|
SideManager();
|
||||||
|
SideManager(size_t side);
|
||||||
|
public: /* Accessors */
|
||||||
|
enum e_side get_side() const;
|
||||||
|
enum e_side get_opposite() const;
|
||||||
|
enum e_side get_rotate_clockwise() const;
|
||||||
|
enum e_side get_rotate_counterclockwise() const;
|
||||||
|
bool validate() const;
|
||||||
|
size_t to_size_t() const;
|
||||||
|
const char* c_str() const;
|
||||||
|
std::string to_string() const;
|
||||||
|
public: /* Mutators */
|
||||||
|
void set_side(size_t side);
|
||||||
|
void set_side(enum e_side side);
|
||||||
|
void set_opposite();
|
||||||
|
void rotate_clockwise();
|
||||||
|
void rotate_counterclockwise();
|
||||||
|
private: /* internal data */
|
||||||
|
enum e_side side_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace openfpga ends */
|
||||||
|
|
||||||
|
#endif
|
|
@ -16,26 +16,33 @@ namespace openfpga {
|
||||||
* based on VPR routing results
|
* based on VPR routing results
|
||||||
* - Unmapped rr_node will use invalid ids
|
* - Unmapped rr_node will use invalid ids
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
void annotate_rr_node_nets(const ClusteringContext& vpr_clustering_ctx,
|
void annotate_rr_node_nets(const DeviceContext& device_ctx,
|
||||||
const RoutingContext& vpr_routing_ctx,
|
const ClusteringContext& clustering_ctx,
|
||||||
VprRoutingAnnotation& vpr_routing_annotation) {
|
const RoutingContext& routing_ctx,
|
||||||
|
VprRoutingAnnotation& vpr_routing_annotation,
|
||||||
|
const bool& verbose) {
|
||||||
size_t counter = 0;
|
size_t counter = 0;
|
||||||
VTR_LOG("Annotating rr_node with routed nets...");
|
VTR_LOG("Annotating rr_node with routed nets...");
|
||||||
|
VTR_LOGV(verbose, "\n");
|
||||||
|
|
||||||
for (auto net_id : vpr_clustering_ctx.clb_nlist.nets()) {
|
for (auto net_id : clustering_ctx.clb_nlist.nets()) {
|
||||||
/* Ignore nets that are not routed */
|
/* Ignore nets that are not routed */
|
||||||
if (true == vpr_clustering_ctx.clb_nlist.net_is_ignored(net_id)) {
|
if (true == clustering_ctx.clb_nlist.net_is_ignored(net_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Ignore used in local cluster only, reserved one CLB pin */
|
/* Ignore used in local cluster only, reserved one CLB pin */
|
||||||
if (false == vpr_clustering_ctx.clb_nlist.net_sinks(net_id).size()) {
|
if (false == clustering_ctx.clb_nlist.net_sinks(net_id).size()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
t_trace* tptr = vpr_routing_ctx.trace[net_id].head;
|
t_trace* tptr = routing_ctx.trace[net_id].head;
|
||||||
while (tptr != nullptr) {
|
while (tptr != nullptr) {
|
||||||
RRNodeId rr_node = tptr->index;
|
RRNodeId rr_node = tptr->index;
|
||||||
vpr_routing_annotation.set_rr_node_net(rr_node, net_id);
|
/* Ignore source and sink nodes, they are the common node multiple starting and ending points */
|
||||||
counter++;
|
if ( (SOURCE != device_ctx.rr_graph.node_type(rr_node))
|
||||||
|
&& (SINK != device_ctx.rr_graph.node_type(rr_node)) ) {
|
||||||
|
vpr_routing_annotation.set_rr_node_net(rr_node, net_id);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
tptr = tptr->next;
|
tptr = tptr->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
void annotate_rr_node_nets(const ClusteringContext& vpr_clustering_ctx,
|
void annotate_rr_node_nets(const DeviceContext& device_ctx,
|
||||||
const RoutingContext& vpr_routing_ctx,
|
const ClusteringContext& clustering_ctx,
|
||||||
VprRoutingAnnotation& vpr_routing_annotation);
|
const RoutingContext& routing_ctx,
|
||||||
|
VprRoutingAnnotation& vpr_routing_annotation,
|
||||||
|
const bool& verbose);
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ void VprRoutingAnnotation::set_rr_node_net(const RRNodeId& rr_node,
|
||||||
VTR_ASSERT(size_t(rr_node) < rr_node_nets_.size());
|
VTR_ASSERT(size_t(rr_node) < rr_node_nets_.size());
|
||||||
/* Warn any override attempt */
|
/* Warn any override attempt */
|
||||||
if (ClusterNetId::INVALID() != rr_node_nets_[rr_node]) {
|
if (ClusterNetId::INVALID() != rr_node_nets_[rr_node]) {
|
||||||
VTR_LOG_WARN("Override the net '%ld' for node'%ld' with in routing context annotation!\n",
|
VTR_LOG_WARN("Override the net '%ld' for node '%ld' with in routing context annotation!\n",
|
||||||
size_t(net_id), size_t(rr_node));
|
size_t(net_id), size_t(rr_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,9 @@ void link_arch(OpenfpgaContext& openfpga_context,
|
||||||
*/
|
*/
|
||||||
openfpga_context.mutable_vpr_routing_annotation().init(g_vpr_ctx.device().rr_graph);
|
openfpga_context.mutable_vpr_routing_annotation().init(g_vpr_ctx.device().rr_graph);
|
||||||
|
|
||||||
annotate_rr_node_nets(g_vpr_ctx.clustering(), g_vpr_ctx.routing(),
|
annotate_rr_node_nets(g_vpr_ctx.device(), g_vpr_ctx.clustering(), g_vpr_ctx.routing(),
|
||||||
openfpga_context.mutable_vpr_routing_annotation());
|
openfpga_context.mutable_vpr_routing_annotation(),
|
||||||
|
cmd_context.option_enable(cmd, opt_verbose));
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
/* Headers from vpr library */
|
/* Headers from vpr library */
|
||||||
#include "vpr_utils.h"
|
#include "vpr_utils.h"
|
||||||
|
|
||||||
|
/* Headers from openfpgautil library */
|
||||||
|
#include "openfpga_side_manager.h"
|
||||||
|
|
||||||
#include "pb_type_utils.h"
|
#include "pb_type_utils.h"
|
||||||
#include "openfpga_pb_pin_fixup.h"
|
#include "openfpga_pb_pin_fixup.h"
|
||||||
|
|
||||||
|
@ -56,6 +59,7 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct
|
||||||
VprClusteringAnnotation& vpr_clustering_annotation,
|
VprClusteringAnnotation& vpr_clustering_annotation,
|
||||||
const vtr::Point<size_t>& grid_coord,
|
const vtr::Point<size_t>& grid_coord,
|
||||||
const ClusterBlockId& blk_id,
|
const ClusterBlockId& blk_id,
|
||||||
|
const e_side& border_side,
|
||||||
const bool& verbose) {
|
const bool& verbose) {
|
||||||
/* Handle each pin */
|
/* Handle each pin */
|
||||||
auto logical_block = clustering_ctx.clb_nlist.block_type(blk_id);
|
auto logical_block = clustering_ctx.clb_nlist.block_type(blk_id);
|
||||||
|
@ -66,6 +70,7 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct
|
||||||
int physical_pin = get_physical_pin(physical_tile, logical_block, j);
|
int physical_pin = get_physical_pin(physical_tile, logical_block, j);
|
||||||
auto pin_class = physical_tile->pin_class[physical_pin];
|
auto pin_class = physical_tile->pin_class[physical_pin];
|
||||||
auto class_inf = physical_tile->class_inf[pin_class];
|
auto class_inf = physical_tile->class_inf[pin_class];
|
||||||
|
|
||||||
t_rr_type rr_node_type;
|
t_rr_type rr_node_type;
|
||||||
if (class_inf.type == DRIVER) {
|
if (class_inf.type == DRIVER) {
|
||||||
rr_node_type = OPIN;
|
rr_node_type = OPIN;
|
||||||
|
@ -74,49 +79,74 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct
|
||||||
rr_node_type = IPIN;
|
rr_node_type = IPIN;
|
||||||
}
|
}
|
||||||
std::vector<e_side> pin_sides = find_logic_tile_pin_side(physical_tile, physical_pin);
|
std::vector<e_side> pin_sides = find_logic_tile_pin_side(physical_tile, physical_pin);
|
||||||
/* As some grid go across columns or rows, we may not have the pin on any side */
|
/* As some grid has height/width offset, we may not have the pin on any side */
|
||||||
if (0 == pin_sides.size()) {
|
if (0 == pin_sides.size()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const e_side& pin_side : pin_sides) {
|
/* For regular grid, we should have pin only one side!
|
||||||
/* Find the net mapped to this pin in routing results */
|
* I/O grids: VPR creates the grid with duplicated pins on every side
|
||||||
const RRNodeId& rr_node = device_ctx.rr_graph.find_node(grid_coord.x(), grid_coord.y(), rr_node_type, physical_pin, pin_side);
|
* but the expected side (only used side) will be opposite side of the border side!
|
||||||
if (false == device_ctx.rr_graph.valid_node_id(rr_node)) {
|
*/
|
||||||
continue;
|
e_side pin_side = NUM_SIDES;
|
||||||
}
|
if (NUM_SIDES == border_side) {
|
||||||
/* Get the cluster net id which has been mapped to this net */
|
VTR_ASSERT(1 == pin_sides.size());
|
||||||
ClusterNetId routing_net_id = vpr_routing_annotation.rr_node_net(rr_node);
|
pin_side = pin_sides[0];
|
||||||
|
} else {
|
||||||
/* Find the net mapped to this pin in clustering results*/
|
SideManager side_manager(border_side);
|
||||||
ClusterNetId cluster_net_id = clustering_ctx.clb_nlist.block_net(blk_id, j);
|
VTR_ASSERT(pin_sides.end() != std::find(pin_sides.begin(), pin_sides.end(), side_manager.get_opposite()));
|
||||||
|
pin_side = side_manager.get_opposite();
|
||||||
/* If matched, we finish here */
|
|
||||||
if (routing_net_id == cluster_net_id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Add to net modification */
|
|
||||||
vpr_clustering_annotation.rename_net(blk_id, j, routing_net_id);
|
|
||||||
|
|
||||||
std::string routing_net_name("unmapped");
|
|
||||||
if (ClusterNetId::INVALID() != routing_net_id) {
|
|
||||||
routing_net_name = clustering_ctx.clb_nlist.net_name(routing_net_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string cluster_net_name("unmapped");
|
|
||||||
if (ClusterNetId::INVALID() != cluster_net_id) {
|
|
||||||
cluster_net_name = clustering_ctx.clb_nlist.net_name(cluster_net_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
VTR_LOGV(verbose,
|
|
||||||
"Fixed up net '%s' mapping mismatch at clustered block '%s' pin '%s[%d]' (was net '%s')\n",
|
|
||||||
routing_net_name.c_str(),
|
|
||||||
clustering_ctx.clb_nlist.block_pb(blk_id)->name,
|
|
||||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
|
|
||||||
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number,
|
|
||||||
cluster_net_name.c_str()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find the net mapped to this pin in routing results */
|
||||||
|
const RRNodeId& rr_node = device_ctx.rr_graph.find_node(grid_coord.x(), grid_coord.y(), rr_node_type, physical_pin, pin_side);
|
||||||
|
if (false == device_ctx.rr_graph.valid_node_id(rr_node)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Get the cluster net id which has been mapped to this net */
|
||||||
|
ClusterNetId routing_net_id = vpr_routing_annotation.rr_node_net(rr_node);
|
||||||
|
|
||||||
|
/* Find the net mapped to this pin in clustering results*/
|
||||||
|
ClusterNetId cluster_net_id = clustering_ctx.clb_nlist.block_net(blk_id, j);
|
||||||
|
|
||||||
|
/* Ignore those net have never been routed */
|
||||||
|
if ( (ClusterNetId::INVALID() != cluster_net_id)
|
||||||
|
&& (true == clustering_ctx.clb_nlist.net_is_ignored(cluster_net_id))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ignore used in local cluster only, reserved one CLB pin */
|
||||||
|
if (false == clustering_ctx.clb_nlist.net_sinks(cluster_net_id).size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If matched, we finish here */
|
||||||
|
if (routing_net_id == cluster_net_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Add to net modification */
|
||||||
|
vpr_clustering_annotation.rename_net(blk_id, j, routing_net_id);
|
||||||
|
|
||||||
|
std::string routing_net_name("unmapped");
|
||||||
|
if (ClusterNetId::INVALID() != routing_net_id) {
|
||||||
|
routing_net_name = clustering_ctx.clb_nlist.net_name(routing_net_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cluster_net_name("unmapped");
|
||||||
|
if (ClusterNetId::INVALID() != cluster_net_id) {
|
||||||
|
cluster_net_name = clustering_ctx.clb_nlist.net_name(cluster_net_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
VTR_LOGV(verbose,
|
||||||
|
"Fixed up net '%s' mapping mismatch at clustered block '%s' pin 'grid[%ld][%ld].%s.%s[%d]' (was net '%s')\n",
|
||||||
|
routing_net_name.c_str(),
|
||||||
|
clustering_ctx.clb_nlist.block_pb(blk_id)->name,
|
||||||
|
grid_coord.x(), grid_coord.y(),
|
||||||
|
clustering_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node->pb_type->name,
|
||||||
|
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->port->name,
|
||||||
|
get_pb_graph_node_pin_from_block_pin(blk_id, physical_pin)->pin_number,
|
||||||
|
cluster_net_name.c_str()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,12 +161,15 @@ void update_pb_pin_with_post_routing_results(const DeviceContext& device_ctx,
|
||||||
const VprRoutingAnnotation& vpr_routing_annotation,
|
const VprRoutingAnnotation& vpr_routing_annotation,
|
||||||
VprClusteringAnnotation& vpr_clustering_annotation,
|
VprClusteringAnnotation& vpr_clustering_annotation,
|
||||||
const bool& verbose) {
|
const bool& verbose) {
|
||||||
for (size_t x = 0; x < device_ctx.grid.width(); ++x) {
|
/* Update the core logic (center blocks of the FPGA) */
|
||||||
for (size_t y = 0; y < device_ctx.grid.height(); ++y) {
|
for (size_t x = 1; x < device_ctx.grid.width() - 1; ++x) {
|
||||||
|
for (size_t y = 1; y < device_ctx.grid.height() - 1; ++y) {
|
||||||
/* Bypass the EMPTY tiles */
|
/* Bypass the EMPTY tiles */
|
||||||
if (device_ctx.EMPTY_PHYSICAL_TILE_TYPE == device_ctx.grid[x][y].type) {
|
if (true == is_empty_type(device_ctx.grid[x][y].type)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
/* We must have an regular (non-I/O) type here */
|
||||||
|
VTR_ASSERT(false == is_io_type(device_ctx.grid[x][y].type));
|
||||||
/* Get the mapped blocks to this grid */
|
/* Get the mapped blocks to this grid */
|
||||||
for (const ClusterBlockId& cluster_blk_id : placement_ctx.grid_blocks[x][y].blocks) {
|
for (const ClusterBlockId& cluster_blk_id : placement_ctx.grid_blocks[x][y].blocks) {
|
||||||
/* Skip invalid ids */
|
/* Skip invalid ids */
|
||||||
|
@ -147,7 +180,55 @@ void update_pb_pin_with_post_routing_results(const DeviceContext& device_ctx,
|
||||||
vtr::Point<size_t> grid_coord(x, y);
|
vtr::Point<size_t> grid_coord(x, y);
|
||||||
update_cluster_pin_with_post_routing_results(device_ctx, clustering_ctx,
|
update_cluster_pin_with_post_routing_results(device_ctx, clustering_ctx,
|
||||||
vpr_routing_annotation, vpr_clustering_annotation,
|
vpr_routing_annotation, vpr_clustering_annotation,
|
||||||
grid_coord, cluster_blk_id,
|
grid_coord, cluster_blk_id, NUM_SIDES,
|
||||||
|
verbose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the periperal I/O blocks at fours sides of FPGA */
|
||||||
|
std::vector<e_side> io_sides{TOP, RIGHT, BOTTOM, LEFT};
|
||||||
|
std::map<e_side, std::vector<vtr::Point<size_t>>> io_coords;
|
||||||
|
|
||||||
|
/* TOP side */
|
||||||
|
for (size_t x = 1; x < device_ctx.grid.width() - 1; ++x) {
|
||||||
|
io_coords[TOP].push_back(vtr::Point<size_t>(x, device_ctx.grid.height() -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RIGHT side */
|
||||||
|
for (size_t y = 1; y < device_ctx.grid.height() - 1; ++y) {
|
||||||
|
io_coords[RIGHT].push_back(vtr::Point<size_t>(device_ctx.grid.width() -1, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BOTTOM side */
|
||||||
|
for (size_t x = 1; x < device_ctx.grid.width() - 1; ++x) {
|
||||||
|
io_coords[BOTTOM].push_back(vtr::Point<size_t>(x, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LEFT side */
|
||||||
|
for (size_t y = 1; y < device_ctx.grid.height() - 1; ++y) {
|
||||||
|
io_coords[LEFT].push_back(vtr::Point<size_t>(0, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Walk through io grid on by one */
|
||||||
|
for (const e_side& io_side : io_sides) {
|
||||||
|
for (const vtr::Point<size_t>& io_coord : io_coords[io_side]) {
|
||||||
|
/* Bypass EMPTY grid */
|
||||||
|
if (true == is_empty_type(device_ctx.grid[io_coord.x()][io_coord.y()].type)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* We must have an I/O type here */
|
||||||
|
VTR_ASSERT(true == is_io_type(device_ctx.grid[io_coord.x()][io_coord.y()].type));
|
||||||
|
/* Get the mapped blocks to this grid */
|
||||||
|
for (const ClusterBlockId& cluster_blk_id : placement_ctx.grid_blocks[io_coord.x()][io_coord.y()].blocks) {
|
||||||
|
/* Skip invalid ids */
|
||||||
|
if (ClusterBlockId::INVALID() == cluster_blk_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Update on I/O grid */
|
||||||
|
update_cluster_pin_with_post_routing_results(device_ctx, clustering_ctx,
|
||||||
|
vpr_routing_annotation, vpr_clustering_annotation,
|
||||||
|
io_coord, cluster_blk_id, io_side,
|
||||||
verbose);
|
verbose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue