[core] adding rr spatial lookup for clock nodes only

This commit is contained in:
tangxifan 2023-02-26 22:23:17 -08:00
parent db36f87dfa
commit 87a9146082
9 changed files with 269 additions and 18 deletions

View File

@ -38,6 +38,36 @@ std::vector<ClockLevelId> ClockNetwork::levels(
return ret;
}
std::vector<ClockTreePinId> ClockNetwork::pins(const ClockTreeId& tree_id,
const ClockLevelId& level,
const t_rr_type& track_type,
const Direction& direction) const {
std::vector<ClockTreePinId> ret;
/* Avoid to repeatedly count the tracks which can be shared by spines
* For two or more spines that locate in different coordinates, they can share
* the same routing tracks. Therefore, we only ensure that routing tracks in
* their demanding direction (INC and DEC) are satisfied
*/
bool dir_flags = false;
for (ClockSpineId curr_spine : spines(tree_id)) {
if (spine_levels_[curr_spine] != size_t(level)) {
continue;
}
if (spine_track_type(curr_spine) == track_type) {
if (!dir_flags && spine_direction(curr_spine) == direction) {
ret.reserve(ret.size() + tree_width(spine_parent_trees_[curr_spine]));
for (size_t i = 0; i < tree_width(spine_parent_trees_[curr_spine]); ++i) {
ret.push_back(ClockTreePinId(i));
}
dir_flags = true;
}
}
}
return ret;
}
/************************************************************************
* Public Accessors : Basic data query
***********************************************************************/

View File

@ -53,6 +53,10 @@ class ClockNetwork {
std::vector<ClockLevelId> levels(const ClockTreeId& tree_id) const;
/* Return a list of spine id under a clock tree */
std::vector<ClockSpineId> spines(const ClockTreeId& tree_id) const;
/* Return a list of clock pins in a bus of clock tree at a given level and direction */
std::vector<ClockTreePinId> pins(const ClockTreeId& tree_id, const ClockLevelId& level,
const t_rr_type& track_type,
const Direction& direction) const;
public: /* Public Accessors: Basic data query */
/* Return the number of routing tracks required by a selected clock tree at a

View File

@ -16,11 +16,13 @@ namespace openfpga { // Begin namespace openfpga
struct clock_level_id_tag;
struct clock_tree_id_tag;
struct clock_tree_pin_id_tag;
struct clock_spine_id_tag;
struct clock_switch_point_id_tag;
typedef vtr::StrongId<clock_level_id_tag> ClockLevelId;
typedef vtr::StrongId<clock_tree_id_tag> ClockTreeId;
typedef vtr::StrongId<clock_tree_pin_id_tag> ClockTreePinId;
typedef vtr::StrongId<clock_spine_id_tag> ClockSpineId;
typedef vtr::StrongId<clock_switch_point_id_tag> ClockSwitchPointId;

View File

@ -0,0 +1,99 @@
#include "vtr_assert.h"
#include "vtr_log.h"
#include "rr_clock_spatial_lookup.h"
namespace openfpga { // begin namespace openfpga
RRClockSpatialLookup::RRClockSpatialLookup() {
}
RRNodeId RRClockSpatialLookup::find_node(int x,
int y,
const ClockTreeId& tree,
const ClockLevelId& lvl,
const ClockTreePinId& pin,
const Direction& direction) const {
size_t dir = size_t(direction);
/* Pre-check: the x, y, side and ptc should be non negative numbers! Otherwise, return an invalid id */
if ((x < 0) || (y < 0) || (direction != Direction::INC && direction != Direction::DEC)) {
return RRNodeId::INVALID();
}
/* Sanity check to ensure the x, y, side and ptc are in range
* - Return an valid id by searching in look-up when all the parameters are in range
* - Return an invalid id if any out-of-range is detected
*/
if (size_t(dir) >= rr_node_indices_.size()) {
return RRNodeId::INVALID();
}
if (size_t(x) >= rr_node_indices_[dir].dim_size(0)) {
return RRNodeId::INVALID();
}
if (size_t(y) >= rr_node_indices_[dir].dim_size(1)) {
return RRNodeId::INVALID();
}
auto result_tree = rr_node_indices_[dir][x][y].find(tree);
if (result_tree == rr_node_indices_[dir][x][y].end()) {
return RRNodeId::INVALID();
}
auto result_lvl = result_tree->second.find(lvl);
if (result_lvl == result_tree->second.end()) {
return RRNodeId::INVALID();
}
auto result_pin = result_lvl->second.find(pin);
if (result_pin == result_lvl->second.end()) {
return RRNodeId::INVALID();
}
return result_pin->second;
}
void RRClockSpatialLookup::add_node(RRNodeId node,
int x,
int y,
const ClockTreeId& tree,
const ClockLevelId& lvl,
const ClockTreePinId& pin,
const Direction& direction) {
size_t dir = size_t(direction);
VTR_ASSERT(node); /* Must have a valid node id to be added */
VTR_ASSERT_SAFE(2 == rr_node_indices_[dir].ndims());
resize_nodes(x, y, direction);
/* Resize on demand finished; Register the node */
rr_node_indices_[dir][x][y][tree][lvl][pin] = node;
}
void RRClockSpatialLookup::resize_nodes(int x,
int y,
const Direction& direction) {
/* Expand the fast look-up if the new node is out-of-range
* This may seldom happen because the rr_graph building function
* should ensure the fast look-up well organized
*/
size_t dir = size_t(direction);
VTR_ASSERT(dir < rr_node_indices_.size());
VTR_ASSERT(x >= 0);
VTR_ASSERT(y >= 0);
if ((x >= int(rr_node_indices_[dir].dim_size(0)))
|| (y >= int(rr_node_indices_[dir].dim_size(1)))) {
rr_node_indices_[dir].resize({std::max(rr_node_indices_[dir].dim_size(0), size_t(x) + 1),
std::max(rr_node_indices_[dir].dim_size(1), size_t(y) + 1)});
}
}
void RRClockSpatialLookup::clear() {
for (auto& data : rr_node_indices_) {
data.clear();
}
}
} // end namespace openfpga

View File

@ -0,0 +1,102 @@
#ifndef RR_CLOCK_SPATIAL_LOOKUP_H
#define RR_CLOCK_SPATIAL_LOOKUP_H
/**
* @file
* @brief This RRClockSpatialLookup class encapsulates
* the node-lookup for clock nodes in a routing resource graph
*
* A data structure built to find the id of an routing resource node
* (rr_node) given information about its physical position and type in a clock network
* The data structure is mostly needed during building the clock part of a routing resource graph
*
* The data structure allows users to
*
* - Update the look-up with new nodes
* - Find the id of a node with given information, e.g., x, y, type etc.
*/
#include "vtr_geometry.h"
#include "vtr_vector.h"
#include "physical_types.h"
#include "rr_node_types.h"
#include "rr_graph_fwd.h"
#include "clock_network_fwd.h"
namespace openfpga { // begin namespace openfpga
class RRClockSpatialLookup {
/* -- Constructors -- */
public:
/* Explicitly define the only way to create an object */
explicit RRClockSpatialLookup();
/* Disable copy constructors and copy assignment operator
* This is to avoid accidental copy because it could be an expensive operation considering that the
* memory footprint of the data structure could ~ Gb
* Using the following syntax, we prohibit accidental 'pass-by-value' which can be immediately caught
* by compiler
*/
RRClockSpatialLookup(const RRClockSpatialLookup&) = delete;
void operator=(const RRClockSpatialLookup&) = delete;
/* -- Accessors -- */
public:
/**
* @brief Returns the index of the specified routing resource node.
*
* @param (x, y) are the grid location within the FPGA
* @param clk_tree specifies the id of the clock tree in a clock network,
* @param clk_level specifies the level of the clock node in a clock network (typically multi-level),
* @param clk_pin specifies the pin id of the clock node in a bus of clock tree (consider multiple clock in a tree)
* @param direction specifies how the clock node will propagate the signal (either in a horizental or a vertical way)
*
* @note An invalid id will be returned if the node does not exist
*/
RRNodeId find_node(int x,
int y,
const ClockTreeId& tree,
const ClockLevelId& lvl,
const ClockTreePinId& pin,
const Direction& direction) const;
/* -- Mutators -- */
public:
/**
* @brief Register a node in the fast look-up
*
* @note You must have a valid node id to register the node in the lookup
*
* @param (x, y) are the grid location within the FPGA
* @param clk_tree specifies the id of the clock tree in a clock network,
* @param clk_level specifies the level of the clock node in a clock network (typically multi-level),
* @param clk_pin specifies the pin id of the clock node in a bus of clock tree (consider multiple clock in a tree)
* @param direction specifies how the clock node will propagate the signal (either in a horizental or a vertical way)
*
* @note a node added with this call will not create a node in the rr_graph node list
* You MUST add the node in the rr_graph so that the node is valid
*/
void add_node(RRNodeId node,
int x,
int y,
const ClockTreeId& clk_tree,
const ClockLevelId& clk_lvl,
const ClockTreePinId& clk_pin,
const Direction& direction);
/** @brief Clear all the data inside */
void clear();
private: /* Private mutators */
/** @brief Resize the nodes upon needs */
void resize_nodes(int x, int y, const Direction& direction);
/* -- Internal data storage -- */
private:
/* Fast look-up: [INC|DEC][0..grid_width][0..grid_height][tree_id][level_id][clock_pin_id] */
std::array<vtr::NdMatrix<std::map<ClockTreeId, std::map<ClockLevelId, std::map<ClockTreePinId, RRNodeId>>>, 2>, 2> rr_node_indices_;
};
} // end namespace openfpga
#endif

View File

@ -84,6 +84,7 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids,
* with direction, ptc and coordinates etc.
*******************************************************************/
static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
RRClockSpatialLookup& clk_rr_lookup,
const RRGraphView& rr_graph_view,
const ClockNetwork& clk_ntwk,
const vtr::Point<size_t> chan_coord,
@ -98,9 +99,7 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
for (auto itree : clk_ntwk.trees()) {
for (auto ilvl : clk_ntwk.levels(itree)) {
for (auto node_dir : {Direction::INC, Direction::DEC}) {
for (size_t itrack = 0;
itrack < clk_ntwk.num_tracks(itree, ilvl, chan_type, node_dir);
++itrack) {
for (auto ipin : clk_ntwk.pins(itree, ilvl, chan_type, node_dir)) {
RRNodeId clk_node = rr_graph_builder.create_node(
chan_coord.x(), chan_coord.y(), chan_type, curr_node_ptc);
rr_graph_builder.set_node_direction(clk_node, node_dir);
@ -111,8 +110,8 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
size_t(clk_ntwk.default_segment())));
/* FIXME: need to set rc_index and cost_index when building the graph
* in VTR */
/* TODO: register the node to a dedicated lookup for clock nodes only
*/
/* register the node to a dedicated lookup */
clk_rr_lookup.add_node(clk_node, chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir);
/* Update ptc count and go to next */
curr_node_ptc++;
}
@ -123,11 +122,10 @@ static void add_rr_graph_block_clock_nodes(RRGraphBuilder& rr_graph_builder,
/********************************************************************
* Add clock nodes one by one to the routing resource graph.
* Assign node-level attributes properly
* TODO: consider to have a fast lookup for clock nodes. For example,
*find_clock_node(tree_id, level_id, clock_id)
* Assign node-level attributes properly and register in dedicated lookup
*******************************************************************/
static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
RRClockSpatialLookup& clk_rr_lookup,
const RRGraphView& rr_graph_view,
const DeviceGrid& grids,
const bool& through_channel,
@ -142,7 +140,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
(false == is_chanx_exist(grids, chanx_coord))) {
continue;
}
add_rr_graph_block_clock_nodes(rr_graph_builder, rr_graph_view, clk_ntwk,
add_rr_graph_block_clock_nodes(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk,
chanx_coord, CHANX,
CHANX_COST_INDEX_START);
}
@ -159,7 +157,7 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
continue;
}
add_rr_graph_block_clock_nodes(
rr_graph_builder, rr_graph_view, clk_ntwk, chany_coord, CHANY,
rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, CHANY,
CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments());
}
}
@ -168,7 +166,9 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
/********************************************************************
* Add edges for the clock nodes in a given connection block
*******************************************************************/
static
void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder,
const RRClockSpatialLookup& clk_rr_lookup,
const RRGraphView& rr_graph_view,
const ClockNetwork& clk_ntwk,
const vtr::Point<size_t> chan_coord,
@ -176,10 +176,10 @@ void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder,
for (auto itree : clk_ntwk.trees()) {
for (auto ilvl : clk_ntwk.levels(itree)) {
for (auto node_dir : {Direction::INC, Direction::DEC}) {
for (size_t itrack = 0;
itrack < clk_ntwk.num_tracks(itree, ilvl, chan_type, node_dir);
++itrack) {
/* TODO: find the driver clock node through lookup */
for (auto ipin : clk_ntwk.pins(itree, ilvl, chan_type, node_dir)) {
/* find the driver clock node through lookup */
RRNodeId driver_node = clk_rr_lookup.find_node(chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir);
VTR_ASSERT(driver_node);
/* TODO: find the fan-out clock node through lookup */
/* TODO: Create edges */
}
@ -208,7 +208,9 @@ void add_rr_graph_block_clock_edges(RRGraphBuilder& rr_graph_builder,
* v
* clk0_lvl1_chany[1][1]
*******************************************************************/
static
void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
const RRClockSpatialLookup& clk_rr_lookup,
const RRGraphView& rr_graph_view,
const DeviceGrid& grids,
const bool& through_channel,
@ -223,7 +225,7 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
(false == is_chanx_exist(grids, chanx_coord))) {
continue;
}
add_rr_graph_block_clock_edges(rr_graph_builder, rr_graph_view, clk_ntwk,
add_rr_graph_block_clock_edges(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk,
chanx_coord, CHANX);
}
}
@ -238,7 +240,7 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
(false == is_chany_exist(grids, chany_coord))) {
continue;
}
add_rr_graph_block_clock_edges(rr_graph_builder, rr_graph_view, clk_ntwk,
add_rr_graph_block_clock_edges(rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk,
chany_coord, CHANY);
}
}
@ -253,7 +255,9 @@ void add_rr_graph_clock_edges(RRGraphBuilder& rr_graph_builder,
* - Sanity checks
*******************************************************************/
int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
const ClockNetwork& clk_ntwk, const bool& verbose) {
RRClockSpatialLookup& clk_rr_lookup,
const ClockNetwork& clk_ntwk,
const bool& verbose) {
vtr::ScopedStartFinishTimer timer(
"Appending programmable clock network to routing resource graph");
@ -282,6 +286,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
/* Add clock nodes */
add_rr_graph_clock_nodes(vpr_device_ctx.rr_graph_builder,
clk_rr_lookup,
vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
vpr_device_ctx.arch->through_channel, clk_ntwk);
VTR_ASSERT(num_clock_nodes + orig_num_nodes ==
@ -290,6 +295,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
/* TODO: Add edges between clock nodes*/
size_t num_clock_edges = 0;
add_rr_graph_clock_edges(vpr_device_ctx.rr_graph_builder,
static_cast<const RRClockSpatialLookup&>(clk_rr_lookup),
vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
vpr_device_ctx.arch->through_channel, clk_ntwk);

View File

@ -5,6 +5,7 @@
* Include header files that are required by function declaration
*******************************************************************/
#include "clock_network.h"
#include "rr_clock_spatial_lookup.h"
#include "vpr_context.h"
/********************************************************************
@ -15,7 +16,9 @@
namespace openfpga {
int append_clock_rr_graph(DeviceContext& vpr_device_ctx,
const ClockNetwork& clk_ntwk, const bool& verbose);
RRClockSpatialLookup& clk_rr_lookup,
const ClockNetwork& clk_ntwk,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -6,6 +6,7 @@
#include "bitstream_manager.h"
#include "bitstream_setting.h"
#include "clock_network.h"
#include "rr_clock_spatial_lookup.h"
#include "decoder_library.h"
#include "device_rr_gsb.h"
#include "fabric_bitstream.h"
@ -63,6 +64,7 @@ class OpenfpgaContext : public Context {
return bitstream_setting_;
}
const openfpga::ClockNetwork& clock_arch() const { return clock_arch_; }
const openfpga::RRClockSpatialLookup& clock_rr_lookup() const { return clock_rr_lookup_; }
const openfpga::VprDeviceAnnotation& vpr_device_annotation() const {
return vpr_device_annotation_;
}
@ -119,6 +121,7 @@ class OpenfpgaContext : public Context {
return bitstream_setting_;
}
openfpga::ClockNetwork& mutable_clock_arch() { return clock_arch_; }
openfpga::RRClockSpatialLookup& mutable_clock_rr_lookup() { return clock_rr_lookup_; }
openfpga::VprDeviceAnnotation& mutable_vpr_device_annotation() {
return vpr_device_annotation_;
}
@ -169,6 +172,7 @@ class OpenfpgaContext : public Context {
openfpga::SimulationSetting sim_setting_;
openfpga::BitstreamSetting bitstream_setting_;
openfpga::ClockNetwork clock_arch_;
openfpga::RRClockSpatialLookup clock_rr_lookup_;
/* Annotation to pb_type of VPR */
openfpga::VprDeviceAnnotation vpr_device_annotation_;

View File

@ -199,6 +199,7 @@ int append_clock_rr_graph_template(T& openfpga_ctx, const Command& cmd,
CommandOptionId opt_verbose = cmd.option("verbose");
return append_clock_rr_graph(g_vpr_ctx.mutable_device(),
openfpga_ctx.mutable_clock_rr_lookup(),
openfpga_ctx.clock_arch(),
cmd_context.option_enable(cmd, opt_verbose));
}