[core] wrapping up clock routing command
This commit is contained in:
parent
bd2608d3e0
commit
2ff8fb8737
|
@ -68,6 +68,15 @@ std::vector<ClockTreePinId> ClockNetwork::pins(
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::vector<ClockTreePinId> ClockNetwork::pins(
|
||||
const ClockTreeId& tree_id) const {
|
||||
std::vector<ClockTreePinId> ret;
|
||||
for (size_t i = 0; i < tree_width(tree_id); ++i) {
|
||||
ret.push_back(ClockTreePinId(i));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query
|
||||
***********************************************************************/
|
||||
|
@ -206,6 +215,48 @@ vtr::Point<int> ClockNetwork::spine_end_point(
|
|||
return spine_end_points_[spine_id];
|
||||
}
|
||||
|
||||
ClockLevelId ClockNetwork::spine_level(const ClockSpineId& spine_id) const {
|
||||
VTR_ASSERT(valid_spine_id(spine_id));
|
||||
if (is_dirty_) {
|
||||
VTR_LOG_ERROR("Unable to identify spine level when data is still dirty!\n");
|
||||
exit(1);
|
||||
}
|
||||
return ClockLevelId(spine_levels_[spine_id]);
|
||||
}
|
||||
|
||||
std::vector<vtr::Point<int>> ClockNetwork::spine_coordinates(
|
||||
const ClockSpineId& spine_id) const {
|
||||
vtr::Point<int> start_coord = spine_start_point(spine_id);
|
||||
vtr::Point<int> end_coord = spine_end_point(spine_id);
|
||||
std::vector<vtr::Point<int>> coords;
|
||||
if (Direction::INC == spine_direction(spine_id)) {
|
||||
if (CHANX == spine_track_type(spine_id)) {
|
||||
for (int ix = start_coord.x(); ix <= end_coord.x(); ix++) {
|
||||
coords.push_back(vtr::Point<int>(ix, start_coord.y()));
|
||||
}
|
||||
} else {
|
||||
VTR_ASSERT(CHANY == spine_track_type(spine_id));
|
||||
for (int iy = start_coord.y(); iy <= end_coord.y(); iy++) {
|
||||
coords.push_back(vtr::Point<int>(start_coord.x(), iy));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VTR_ASSERT(Direction::DEC == spine_direction(spine_id));
|
||||
if (CHANX == spine_track_type(spine_id)) {
|
||||
for (int ix = start_coord.x(); ix >= end_coord.x(); ix--) {
|
||||
coords.push_back(vtr::Point<int>(ix, start_coord.y()));
|
||||
}
|
||||
} else {
|
||||
VTR_ASSERT(CHANY == spine_track_type(spine_id));
|
||||
for (int iy = start_coord.y(); iy >= end_coord.y(); iy--) {
|
||||
coords.push_back(vtr::Point<int>(start_coord.x(), iy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
||||
std::vector<ClockSwitchPointId> ClockNetwork::spine_switch_points(
|
||||
const ClockSpineId& spine_id) const {
|
||||
VTR_ASSERT(valid_spine_id(spine_id));
|
||||
|
@ -571,6 +622,11 @@ bool ClockNetwork::is_last_level(const ClockTreeId& tree_id,
|
|||
return valid_tree_id(tree_id) && (size_t(lvl_id) == tree_depth(tree_id) - 1);
|
||||
}
|
||||
|
||||
bool ClockNetwork::is_last_level(const ClockSpineId& spine_id) const {
|
||||
return spine_level(spine_id) ==
|
||||
ClockLevelId(tree_depth(spine_parent_trees_[spine_id]) - 1);
|
||||
}
|
||||
|
||||
bool ClockNetwork::valid_spine_id(const ClockSpineId& spine_id) const {
|
||||
return (size_t(spine_id) < spine_ids_.size()) &&
|
||||
(spine_id == spine_ids_[spine_id]);
|
||||
|
|
|
@ -59,6 +59,7 @@ class ClockNetwork {
|
|||
const ClockLevelId& level,
|
||||
const t_rr_type& track_type,
|
||||
const Direction& direction) const;
|
||||
std::vector<ClockTreePinId> pins(const ClockTreeId& tree_id) const;
|
||||
|
||||
public: /* Public Accessors: Basic data query */
|
||||
/* Return the number of routing tracks required by a selected clock tree at a
|
||||
|
@ -80,6 +81,12 @@ class ClockNetwork {
|
|||
std::string spine_name(const ClockSpineId& spine_id) const;
|
||||
vtr::Point<int> spine_start_point(const ClockSpineId& spine_id) const;
|
||||
vtr::Point<int> spine_end_point(const ClockSpineId& spine_id) const;
|
||||
/* Return the level where the spine locates in the multi-layer clock tree
|
||||
* structure */
|
||||
ClockLevelId spine_level(const ClockSpineId& spine_id) const;
|
||||
/* Return the list of coordinates that a spine will go across */
|
||||
std::vector<vtr::Point<int>> spine_coordinates(
|
||||
const ClockSpineId& spine_id) const;
|
||||
/* Identify the direction of a spine, depending on its starting and ending
|
||||
* points
|
||||
* - CHANX represents a horizental routing track
|
||||
|
@ -169,6 +176,8 @@ class ClockNetwork {
|
|||
const ClockLevelId& lvl_id) const;
|
||||
/* Identify if the level is the last level of the given tree */
|
||||
bool is_last_level(const ClockTreeId& tree_id, const ClockLevelId& lvl) const;
|
||||
/* Identify if the spine is at the last level of its tree */
|
||||
bool is_last_level(const ClockSpineId& spine_id) const;
|
||||
/* Show if the tree id is a valid for data queries */
|
||||
bool valid_spine_id(const ClockSpineId& spine_id) const;
|
||||
bool valid_spine_switch_point_id(
|
||||
|
|
|
@ -16,48 +16,73 @@ namespace openfpga {
|
|||
* - route the spine-to-spine switching points
|
||||
* - route the spine-to-IPIN connections (only for the last level)
|
||||
*******************************************************************/
|
||||
static
|
||||
int route_clock_tree_rr_graph() {
|
||||
static int route_clock_tree_rr_graph(
|
||||
VprRoutingAnnotation& vpr_routing_annotation, const RRGraphView& rr_graph,
|
||||
const RRClockSpatialLookup& clk_rr_lookup, const ClockNetwork& clk_ntwk,
|
||||
const ClockTreeId clk_tree) {
|
||||
for (auto ispine : clk_ntwk.spines(clk_tree)) {
|
||||
for (auto ipin : clk_ntwk.pins(clk_tree)) {
|
||||
/* Route the spine from starting point to ending point */
|
||||
std::vector<vtr::Point<size_t>> spine_coords = clk_ntwk.spine_coords(ispine);
|
||||
std::vector<vtr::Point<int>> spine_coords =
|
||||
clk_ntwk.spine_coordinates(ispine);
|
||||
for (size_t icoord = 0; icoord < spine_coords.size() - 1; ++icoord) {
|
||||
vtr::Point<size_t> src_coord = spine_coords[icoord];
|
||||
vtr::Point<size_t> des_coord = spine_coords[icoord + 1];
|
||||
vtr::Point<int> src_coord = spine_coords[icoord];
|
||||
vtr::Point<int> des_coord = spine_coords[icoord + 1];
|
||||
Direction src_spine_direction = clk_ntwk.spine_direction(ispine);
|
||||
Direction des_spine_direction = clk_ntwk.spine_direction(ispine);
|
||||
ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine);
|
||||
ClockLevelId des_spine_level = clk_ntwk.spine_level(ispine);
|
||||
RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction);
|
||||
RRNodeId des_node = clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree, des_spine_level, ipin, des_spine_direction);
|
||||
vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node);
|
||||
ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine);
|
||||
ClockLevelId des_spine_level = clk_ntwk.spine_level(ispine);
|
||||
RRNodeId src_node =
|
||||
clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree,
|
||||
src_spine_level, ipin, src_spine_direction);
|
||||
RRNodeId des_node =
|
||||
clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree,
|
||||
des_spine_level, ipin, des_spine_direction);
|
||||
VTR_ASSERT(rr_graph.valid_node(src_node));
|
||||
VTR_ASSERT(rr_graph.valid_node(des_node));
|
||||
vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node,
|
||||
src_node);
|
||||
}
|
||||
/* Route the spine-to-spine switching points */
|
||||
for (ClockSwitchPointId switch_point_id : clk_ntwk.spine_switch_points(ispine)) {
|
||||
vtr::Point<size_t> src_coord = clk_ntwk.spine_switch_point(ispine, switch_point_id);
|
||||
ClockSpineId des_spine = clk_ntwk.spine_switch_point_tap(ispine, switch_point_id);
|
||||
vtr::Point<size_t> des_coord = clk_ntwk.spine_start_point(des_spine);
|
||||
for (ClockSwitchPointId switch_point_id :
|
||||
clk_ntwk.spine_switch_points(ispine)) {
|
||||
vtr::Point<int> src_coord =
|
||||
clk_ntwk.spine_switch_point(ispine, switch_point_id);
|
||||
ClockSpineId des_spine =
|
||||
clk_ntwk.spine_switch_point_tap(ispine, switch_point_id);
|
||||
vtr::Point<int> des_coord = clk_ntwk.spine_start_point(des_spine);
|
||||
Direction src_spine_direction = clk_ntwk.spine_direction(ispine);
|
||||
Direction des_spine_direction = clk_ntwk.spine_direction(des_spine);
|
||||
ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine);
|
||||
ClockLevelId des_spine_level = clk_ntwk.spine_level(des_spine);
|
||||
RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction);
|
||||
RRNodeId des_node = clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree, des_spine_level, ipin, des_spine_direction);
|
||||
vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node);
|
||||
ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine);
|
||||
ClockLevelId des_spine_level = clk_ntwk.spine_level(des_spine);
|
||||
RRNodeId src_node =
|
||||
clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree,
|
||||
src_spine_level, ipin, src_spine_direction);
|
||||
RRNodeId des_node =
|
||||
clk_rr_lookup.find_node(des_coord.x(), des_coord.y(), clk_tree,
|
||||
des_spine_level, ipin, des_spine_direction);
|
||||
VTR_ASSERT(rr_graph.valid_node(src_node));
|
||||
VTR_ASSERT(rr_graph.valid_node(des_node));
|
||||
vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node,
|
||||
src_node);
|
||||
}
|
||||
/* Route the spine-to-IPIN connections (only for the last level) */
|
||||
if (clk_ntwk.is_last_level(clk_tree, ispine)) {
|
||||
if (clk_ntwk.is_last_level(ispine)) {
|
||||
/* Connect to any fan-out node which is IPIN */
|
||||
for (size_t icoord = 0; icoord < spine_coords.size(); ++icoord) {
|
||||
vtr::Point<size_t> src_coord = spine_coords[icoord];
|
||||
vtr::Point<int> src_coord = spine_coords[icoord];
|
||||
Direction src_spine_direction = clk_ntwk.spine_direction(ispine);
|
||||
ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine);
|
||||
RRNodeId src_node = clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree, src_spine_level, ipin, src_spine_direction);
|
||||
for (RREdgeId edge : rr_graph.edges(src_node)) {
|
||||
ClockLevelId src_spine_level = clk_ntwk.spine_level(ispine);
|
||||
RRNodeId src_node =
|
||||
clk_rr_lookup.find_node(src_coord.x(), src_coord.y(), clk_tree,
|
||||
src_spine_level, ipin, src_spine_direction);
|
||||
for (RREdgeId edge : rr_graph.edge_range(src_node)) {
|
||||
RRNodeId des_node = rr_graph.edge_sink_node(edge);
|
||||
if (rr_graph.node_type(des_node) == IPIN) {
|
||||
vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node, src_node);
|
||||
VTR_ASSERT(rr_graph.valid_node(src_node));
|
||||
VTR_ASSERT(rr_graph.valid_node(des_node));
|
||||
vpr_routing_annotation.set_rr_node_prev_node(rr_graph, des_node,
|
||||
src_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,9 +121,11 @@ int route_clock_rr_graph(VprRoutingAnnotation& vpr_routing_annotation,
|
|||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: Route spines one by one */
|
||||
/* Route spines one by one */
|
||||
for (auto itree : clk_ntwk.trees()) {
|
||||
int status = route_clock_tree_rr_graph();
|
||||
int status =
|
||||
route_clock_tree_rr_graph(vpr_routing_annotation, vpr_device_ctx.rr_graph,
|
||||
clk_rr_lookup, clk_ntwk, itree);
|
||||
if (status == CMD_EXEC_FATAL_ERROR) {
|
||||
return status;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue