diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index 87cd94da1..389e6678b 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -25,9 +25,53 @@ ClockNetwork::clock_tree_range ClockNetwork::trees() const { return vtr::make_range(tree_ids_.begin(), tree_ids_.end()); } +std::vector ClockNetwork::levels(const ClockTreeId& tree_id) const { + std::vector ret; + for (size_t ilvl = 0; ilvl < tree_depth(tree_id); ++ilvl) { + ret.push_back(ClockLevelId(ilvl)); + } + return ret; +} + /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ +t_rr_type ClockNetwork::spine_track_type(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_start_end_points(spine_id)); + if (spine_start_point(spine_id).y() == spine_end_point(spine_id).y()) { + return CHANX; + } + return CHANY; +} + +Direction ClockNetwork::spine_direction(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_start_end_points(spine_id)); + if (spine_track_type(spine_id) == CHANX) { + if (spine_start_point(spine_id).x() < spine_end_point(spine_id).x()) { + return Direction::INC; + } + } else { + VTR_ASSERT(spine_track_type(spine_id) == CHANY); + if (spine_start_point(spine_id).y() < spine_end_point(spine_id).y()) { + return Direction::INC; + } + } + return Direction::DEC; +} + +size_t ClockNetwork::num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, const t_rr_type& direction) const { + size_t num_tracks = 0; + for (ClockSpineId curr_spine : spines(tree_id)) { + if (spine_levels_[curr_spine] != size_t(level)) { + continue; + } + if (spine_track_type(curr_spine) == direction) { + num_tracks++; + } + } + return num_tracks; +} + std::string ClockNetwork::default_segment_name() const { return default_segment_name_; } @@ -339,4 +383,12 @@ bool ClockNetwork::valid_spine_switch_point_id( return size_t(switch_point_id) < spine_switch_points_[spine_id].size(); } +bool ClockNetwork::valid_spine_start_end_points(const ClockSpineId& spine_id) const { + VTR_ASSERT(valid_spine_id(spine_id)); + if ((spine_start_point(spine_id).x() != spine_end_point(spine_id).x()) && (spine_start_point(spine_id).y() != spine_end_point(spine_id).y())) { + return false; + } + return true; +} + } // End of namespace openfpga diff --git a/libs/libclkarchopenfpga/src/base/clock_network.h b/libs/libclkarchopenfpga/src/base/clock_network.h index 8dbda835a..e4bc20f7d 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.h +++ b/libs/libclkarchopenfpga/src/base/clock_network.h @@ -15,6 +15,7 @@ /* Headers from openfpgautil library */ #include "clock_network_fwd.h" #include "rr_graph_fwd.h" +#include "rr_node_types.h" namespace openfpga { // Begin namespace openfpga @@ -48,10 +49,14 @@ class ClockNetwork { public: /* Accessors: aggregates */ size_t num_trees() const; clock_tree_range trees() const; + /* Return the range of clock levels */ + std::vector levels(const ClockTreeId& tree_id) const; /* Return a list of spine id under a clock tree */ std::vector spines(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 given level and direction */ + size_t num_tracks(const ClockTreeId& tree_id, const ClockLevelId& level, const t_rr_type& direction) const; std::string default_segment_name() const; std::string default_switch_name() const; std::string tree_name(const ClockTreeId& tree_id) const; @@ -60,6 +65,20 @@ 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; + /* Identify the direction of a spine, depending on its starting and ending points + * - CHANX represents a horizental routing track + * - CHANY represents a vertical routing track + */ + t_rr_type spine_track_type(const ClockSpineId& spine_id) const; + /* Identify the direction of a spine, depending on its starting and ending points + * INC represents + * - a CHANX track goes from left to right, or + * - a CHANY track goes from bottom to top + * DEC represents + * - a CHANX track goes from right to left, or + * - a CHANY track goes from top to bottom + */ + Direction spine_direction(const ClockSpineId& spine_id) const; /* Return the unique id of switch points under a clock spine*/ std::vector spine_switch_points( const ClockSpineId& spine_id) const; @@ -116,6 +135,8 @@ class ClockNetwork { bool valid_spine_switch_point_id( const ClockSpineId& spine_id, const ClockSwitchPointId& switch_point_id) const; + /* Valid starting and ending point should indicate either this is a X-direction spine or a Y-direction spine. Diagonal spine is not supported! */ + bool valid_spine_start_end_points(const ClockSpineId& spine_id) const; private: /* Private mutators */ /* Build internal links between spines under a given tree */ diff --git a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h index cc4af5f70..a18dc4394 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network_fwd.h +++ b/libs/libclkarchopenfpga/src/base/clock_network_fwd.h @@ -14,10 +14,12 @@ namespace openfpga { // Begin namespace openfpga +struct clock_level_id_tag; struct clock_tree_id_tag; struct clock_spine_id_tag; struct clock_switch_point_id_tag; +typedef vtr::StrongId ClockLevelId; typedef vtr::StrongId ClockTreeId; typedef vtr::StrongId ClockSpineId; typedef vtr::StrongId ClockSwitchPointId; diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index fdf650f65..1e6f85921 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -21,11 +21,15 @@ namespace openfpga { * - Layer 2: CHANX *******************************************************************/ static -size_t estimate_clock_rr_graph_num_nodes(const ClockNetwork& clk_ntwk, +size_t estimate_clock_rr_graph_num_chan_nodes(const ClockNetwork& clk_ntwk, const t_rr_type& chan_type) { size_t num_nodes = 0; - + for (auto itree : clk_ntwk.trees()) { + for (auto ilvl : clk_ntwk.levels(itree)) { + num_nodes += clk_ntwk.num_tracks(itree, ilvl, chan_type); + } + } return num_nodes; } @@ -109,7 +113,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, /* Report number of added clock nodes and edges */ VTR_LOGV( verbose, - "Appended %lu clock nodes (+%.2f\%) and %lu clock edges to routing resource graph.\n", + "Appended %lu clock nodes (+%.2f%) and %lu clock edges to routing resource graph.\n", num_clock_nodes, (float)(num_clock_nodes / orig_num_nodes), num_clock_edges); return CMD_EXEC_SUCCESS;