From 2ff8fb87379517e72057c594934a289f0a983506 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Feb 2023 16:52:54 -0800 Subject: [PATCH] [core] wrapping up clock routing command --- .../src/base/clock_network.cpp | 56 +++++++++++++ .../src/base/clock_network.h | 9 +++ .../src/annotation/route_clock_rr_graph.cpp | 81 ++++++++++++------- 3 files changed, 119 insertions(+), 27 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index d53e5bbef..a8a065ffe 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -68,6 +68,15 @@ std::vector ClockNetwork::pins( return ret; } +std::vector ClockNetwork::pins( + const ClockTreeId& tree_id) const { + std::vector 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 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> ClockNetwork::spine_coordinates( + const ClockSpineId& spine_id) const { + vtr::Point start_coord = spine_start_point(spine_id); + vtr::Point end_coord = spine_end_point(spine_id); + std::vector> 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(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(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(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(start_coord.x(), iy)); + } + } + } + + return coords; +} + std::vector 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]); diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index d29f5711e..14ab3fab4 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -59,6 +59,7 @@ class ClockNetwork { const ClockLevelId& level, const t_rr_type& track_type, const Direction& direction) const; + std::vector 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 spine_start_point(const ClockSpineId& spine_id) const; vtr::Point 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> 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( diff --git a/openfpga/src/annotation/route_clock_rr_graph.cpp b/openfpga/src/annotation/route_clock_rr_graph.cpp index b26122a9f..47a70f965 100644 --- a/openfpga/src/annotation/route_clock_rr_graph.cpp +++ b/openfpga/src/annotation/route_clock_rr_graph.cpp @@ -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> spine_coords = clk_ntwk.spine_coords(ispine); + std::vector> spine_coords = + clk_ntwk.spine_coordinates(ispine); for (size_t icoord = 0; icoord < spine_coords.size() - 1; ++icoord) { - vtr::Point src_coord = spine_coords[icoord]; - vtr::Point des_coord = spine_coords[icoord + 1]; + vtr::Point src_coord = spine_coords[icoord]; + vtr::Point 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 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 des_coord = clk_ntwk.spine_start_point(des_spine); + for (ClockSwitchPointId switch_point_id : + clk_ntwk.spine_switch_points(ispine)) { + vtr::Point 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 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 src_coord = spine_coords[icoord]; + vtr::Point 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; }