[core] wrapping up clock routing command

This commit is contained in:
tangxifan 2023-02-28 16:52:54 -08:00
parent bd2608d3e0
commit 2ff8fb8737
3 changed files with 119 additions and 27 deletions

View File

@ -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]);

View File

@ -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(

View File

@ -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;
}