[core] clock edges interconnecting clock tracks across levels

This commit is contained in:
tangxifan 2023-02-27 15:10:36 -08:00
parent b6eace8fac
commit 9ec4d690db
3 changed files with 182 additions and 8 deletions

View File

@ -244,6 +244,10 @@ bool ClockNetwork::empty() const { return 0 == tree_ids_.size(); }
bool ClockNetwork::is_valid() const { return !is_dirty_; }
ClockLevelId ClockNetwork::next_level(const ClockLevelId& lvl) const {
return ClockLevelId(size_t(lvl) + 1);
}
/************************************************************************
* Public Mutators
***********************************************************************/
@ -502,6 +506,12 @@ bool ClockNetwork::valid_tree_id(const ClockTreeId& tree_id) const {
(tree_id == tree_ids_[tree_id]);
}
bool ClockNetwork::valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_id) const {
return valid_tree_id(tree_id) &&
(size_t(lvl_id) < tree_depth(tree_id));
}
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

@ -110,6 +110,11 @@ class ClockNetwork {
/* Check if there are clock tree */
bool empty() const;
bool is_valid() const;
/* Get the level id which is next to the current level
* Note that this follows the same rule in computing levels in update_tree_depth()
* If the rule has been changed, this API should be changed as well
*/
ClockLevelId next_level(const ClockLevelId& lvl) const;
public: /* Public Mutators */
/* Reserve a number of spines to be memory efficent */
@ -148,6 +153,8 @@ class ClockNetwork {
public: /* Public invalidators/validators */
/* Show if the tree id is a valid for data queries */
bool valid_tree_id(const ClockTreeId& tree_id) const;
/* Show if the level id is a valid for a given tree */
bool valid_level_id(const ClockTreeId& tree_id, const ClockLevelId& lvl_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

@ -165,26 +165,183 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder,
}
/********************************************************************
* Add edges for the clock nodes in a given connection block
* Find the destination nodes for a driver clock node in a given connection block
* There are two types of destination nodes:
* - Straight connection where the driver clock node connects to another clock node
* in the same direction and at the same level as well as clock index
* For example
*
* clk0_lvl0_chanx[1][1] -->------------->---> clk0_lvl0_chanx[2][1]
*
* - Turning connections where the driver clock node makes turns to connect other clock nodes
* at 1-level up and in the same clock index
*
*
* clk0_lvl1_chany[1][2]
* ^
* |
* clk0_lvl0_chanx[1][1] -->---------+--->---> clk0_lvl0_chanx[2][1]
* clk0_lvl0_chanx[1][1] -->---------+
* |
* v
* clk0_lvl1_chany[1][1]
*
* Coordindate system:
*
* +----------+----------+------------+
* | Grid | CBy | Grid |
* | [x][y+1] | [x][y+1] | [x+1][y+1] |
* +----------+----------+------------+
* | CBx | SB | CBx |
* | [x][y] | [x][y] | [x+1][y] |
* +----------+----------+------------+
* | Grid | CBy | Grid |
* | [x][y] | [x][y] | [x+1][y] |
* +----------+----------+------------+
*
*******************************************************************/
static
std::vector<RRNodeId> find_clock_track2track_node(const vtr::Point<size_t>& chan_coord,
std::vector<RRNodeId> find_clock_track2track_node(const RRGraphView& rr_graph_view,
const ClockNetwork& clk_ntwk,
const RRClockSpatialLookup& clk_rr_lookup,
const t_rr_type& chan_type,
const vtr::Point<size_t>& chan_coord,
const ClockTreeId& clk_tree,
const ClockLevelId& clk_lvl,
const ClockTreePinId& clk_pin,
const Direction& direction) {
std::vector<RRNodeId> des_nodes;
return des_nodes
/* Straight connection */
vtr::Point<size_t> straight_des_coord = chan_coord;
if (chan_type == CHANX) {
if (direction == Direction::INC) {
straight_des_coord.set_x(straight_des_coord.x() + 1);
} else {
VTR_ASSERT(direction == Direction::DEC);
straight_des_coord.set_x(straight_des_coord.x() - 1);
}
} else {
VTR_ASSERT(chan_type == CHANY);
if (direction == Direction::INC) {
straight_des_coord.set_y(straight_des_coord.y() + 1);
} else {
VTR_ASSERT(direction == Direction::DEC);
straight_des_coord.set_y(straight_des_coord.y() - 1);
}
}
RRNodeId straight_des_node = clk_rr_lookup.find_node(straight_des_coord.x(), straight_des_coord.y(), clk_tree, clk_lvl, clk_pin, direction);
if (rr_graph_view.valid_node(straight_des_node)) {
VTR_ASSERT(chan_type == rr_graph_view.node_type(straight_des_node));
des_nodes.push_back(straight_des_node);
}
/* Check the next level if this is the last level, there are no turns available */
ClockLevelId next_clk_lvl = clk_ntwk.next_level(clk_lvl);
if (!clk_ntwk.valid_level_id(clk_tree, next_clk_lvl)) {
return des_nodes;
}
/* left turn connection */
vtr::Point<size_t> left_des_coord = chan_coord;
Direction left_direction = direction;
t_rr_type left_des_chan_type = chan_type;
if (chan_type == CHANX) {
left_des_chan_type = CHANY;
if (direction == Direction::INC) {
/*
* ^
* |
* -->+
*/
left_des_coord.set_y(left_des_coord.y() + 1);
} else {
/*
* +<--
* |
* v
*/
VTR_ASSERT(direction == Direction::DEC);
left_des_coord.set_x(left_des_coord.x() - 1);
}
} else {
VTR_ASSERT(chan_type == CHANY);
left_des_chan_type = CHANX;
if (direction == Direction::INC) {
/*
* <--+
* ^
* |
*/
left_direction = Direction::DEC;
} else {
VTR_ASSERT(direction == Direction::DEC);
/*
* |
* v
* +-->
*/
left_direction = Direction::INC;
left_des_coord.set_x(left_des_coord.x() + 1);
left_des_coord.set_y(left_des_coord.y() - 1);
}
}
RRNodeId left_des_node = clk_rr_lookup.find_node(left_des_coord.x(), left_des_coord.y(), clk_tree, next_clk_lvl, clk_pin, left_direction);
if (rr_graph_view.valid_node(left_des_node)) {
VTR_ASSERT(left_des_chan_type == rr_graph_view.node_type(left_des_node));
des_nodes.push_back(left_des_node);
}
/* right turn connection */
vtr::Point<size_t> right_des_coord = chan_coord;
Direction right_direction = direction;
t_rr_type right_des_chan_type = chan_type;
if (chan_type == CHANX) {
right_des_chan_type = CHANY;
if (direction == Direction::INC) {
/*
* -->+
* |
* v
*/
right_direction = Direction::DEC;
} else {
/*
* ^
* |
* +<--
*/
VTR_ASSERT(direction == Direction::DEC);
right_direction = Direction::INC;
right_des_coord.set_x(right_des_coord.x() - 1);
right_des_coord.set_y(right_des_coord.y() + 1);
}
} else {
VTR_ASSERT(chan_type == CHANY);
right_des_chan_type = CHANX;
if (direction == Direction::INC) {
/*
* +-->
* ^
* |
*/
right_des_coord.set_x(right_des_coord.x() + 1);
} else {
VTR_ASSERT(direction == Direction::DEC);
/*
* |
* v
* <--+
*/
right_des_coord.set_y(right_des_coord.y() - 1);
}
}
RRNodeId right_des_node = clk_rr_lookup.find_node(right_des_coord.x(), right_des_coord.y(), clk_tree, next_clk_lvl, clk_pin, right_direction);
if (rr_graph_view.valid_node(right_des_node)) {
VTR_ASSERT(right_des_chan_type == rr_graph_view.node_type(right_des_node));
des_nodes.push_back(right_des_node);
}
return des_nodes;
}
/********************************************************************
@ -202,11 +359,11 @@ static void add_rr_graph_block_clock_edges(
/* find the driver clock node through lookup */
RRNodeId src_node = clk_rr_lookup.find_node(
chan_coord.x(), chan_coord.y(), itree, ilvl, ipin, node_dir);
VTR_ASSERT(src_node);
/* TODO: find the fan-out clock node through lookup */
for (RRNodeId des_node : find_clock_track2track_node(chan_coord, itree, ilvl, ipin, node_dir)) {
VTR_ASSERT(rr_graph_view.valid_node(src_node));
/* find the fan-out clock node through lookup */
for (RRNodeId des_node : find_clock_track2track_node(rr_graph_view, clk_ntwk, clk_rr_lookup, chan_type, chan_coord, itree, ilvl, ipin, node_dir)) {
/* Create edges */
VTR_ASSERT(des_node);
VTR_ASSERT(rr_graph_view.valid_node(des_node));
rr_graph_builder.create_edge(src_node, des_node, clk_ntwk.default_switch());
edge_count++;
}