Skip to content

[WIP] Per-edge delays #2880

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1b306c0
fix some typos in comments
soheilshahrouz Jan 29, 2025
9677848
cleaned print_switch_usage a little bit to use std::vector instead of…
soheilshahrouz Jan 29, 2025
5bd1131
add RRGraphView::edge_delay
soheilshahrouz Jan 29, 2025
af5a56e
added t_rr_switch_offset_inf struct
soheilshahrouz Jan 29, 2025
ea06ff4
finished the implementation of RRGraphView::edge_delay()
soheilshahrouz Jan 29, 2025
e2321b5
add methods to RRGraphBuilder for modifying rr_switch_offset_inf_
soheilshahrouz Jan 29, 2025
a03bfc0
add rr_switch_offset_inf argument to RRGraphView constructor
soheilshahrouz Jan 29, 2025
d4973a8
partially implemented load_rr_edge_attribute_offset_file()
soheilshahrouz Jan 30, 2025
8de3b3c
add RRGraphBuilder::set_edge_offset_id() method and call it in load_r…
soheilshahrouz Jan 30, 2025
e0f3483
store actual unique delays instead of offsets
soheilshahrouz Jan 30, 2025
c6d6a40
update edge_switch_offset_inf_ in the edge is already mapped
soheilshahrouz Feb 1, 2025
417bf61
create a t_rr_switch_offset_inf for each t_rr_switch_inf added to RR …
soheilshahrouz Feb 2, 2025
df1318b
init rr_switch_offset_inf_ when RR graph is read from a file
soheilshahrouz Feb 2, 2025
dda0e33
add --read_rr_edge_delay_offset_file command line option
soheilshahrouz Feb 2, 2025
df6062c
update rr_switch_offset_inf when rr_switch is updated based on fanin …
soheilshahrouz Feb 3, 2025
dd1df5c
call edge_delay() instead of accessing switch delay
soheilshahrouz Feb 3, 2025
412638f
Merge branch 'master' into per_edge_delay
soheilshahrouz Feb 3, 2025
017abab
clear edge_switch_offset_inf_ in RRGraphStorage
soheilshahrouz Feb 3, 2025
31f617a
replace raw pointers with std::vector for seg_details_x/y
soheilshahrouz Feb 3, 2025
91aed46
replace t_clb_to_clb_directs* with std::vector<t_clb_to_clb_directs>&
soheilshahrouz Feb 3, 2025
190f8b0
resize rr_switch_offset_inf_ and rr_switch_inf_ together
soheilshahrouz Feb 3, 2025
00739ed
rename t_rr_switch_offset_inf to t_rr_switch_override_inf
soheilshahrouz Feb 5, 2025
3cc543f
add edge attribute methods
soheilshahrouz Feb 5, 2025
5bc080e
replace accesses to member vars of t_rr_switch with RRGraphView API c…
soheilshahrouz Feb 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions libs/libarchfpga/src/physical_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1872,6 +1872,35 @@ struct t_rr_switch_inf {
SwitchType type_ = SwitchType::INVALID;
};

struct t_rr_switch_override_inf {
float R = 0.f;
float Cin = 0.;
float Cout = 0.;
float Cinternal = 0.;
float Tdel = 0.;

t_rr_switch_override_inf() = default;
t_rr_switch_override_inf(const t_rr_switch_inf& switch_inf)
: R(switch_inf.R)
, Cin(switch_inf.Cin)
, Cout(switch_inf.Cout)
, Cinternal(switch_inf.Cinternal)
, Tdel(switch_inf.Tdel) {}

t_rr_switch_override_inf& operator=(const t_rr_switch_override_inf& other) {
if (this != &other) { // Self-assignment check
R = other.R;
Cin = other.Cin;
Cout = other.Cout;
Cinternal = other.Cinternal;
Tdel = other.Tdel;
}
return *this;
}

auto operator<=>(const t_rr_switch_override_inf&) const = default;
};

/**
* @struct t_direct_inf
* @brief Lists all the important information about a direct chain connection.
Expand Down
3 changes: 2 additions & 1 deletion libs/librrgraph/src/base/rr_graph_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ void RRGraphBuilder::clear() {
rr_edge_metadata_.clear();
rr_segments_.clear();
rr_switch_inf_.clear();
rr_switch_override_inf_.clear();
}

void RRGraphBuilder::reorder_nodes(e_rr_node_reorder_algorithm reorder_rr_graph_nodes_algorithm,
Expand All @@ -93,7 +94,7 @@ void RRGraphBuilder::reorder_nodes(e_rr_node_reorder_algorithm reorder_rr_graph_
n = RRNodeId(cur_idx++);
}

// This method works well. The intution is that highly connected nodes are enumerated first (together),
// This method works well. The intuition is that highly connected nodes are enumerated first (together),
// and since there will be a lot of nodes with the same degree, they are then ordered based on some
// distance from the starting node.
if (reorder_rr_graph_nodes_algorithm == DEGREE_BFS) {
Expand Down
32 changes: 29 additions & 3 deletions libs/librrgraph/src/base/rr_graph_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,13 @@ class RRGraphBuilder {
inline RRSwitchId add_rr_switch(const t_rr_switch_inf& switch_info) {
//Allocate an ID
RRSwitchId switch_id = RRSwitchId(rr_switch_inf_.size());

rr_switch_inf_.push_back(switch_info);

t_rr_switch_override_inf switch_override_info(switch_info);
rr_switch_override_inf_.push_back(switch_override_info);

VTR_ASSERT_DEBUG(rr_switch_inf_.size() == rr_switch_override_inf_.size());

return switch_id;
}
/**
Expand All @@ -118,13 +122,29 @@ class RRGraphBuilder {
return rr_switch_inf_;
}

inline RRSwitchOffsetInfoId add_rr_switch_override_info(const t_rr_switch_override_inf& switch_override_info) {
VTR_ASSERT_DEBUG(rr_switch_inf_.size() <= rr_switch_override_inf_.size());
// Allocate an ID
RRSwitchOffsetInfoId switch_offset_info_id = RRSwitchOffsetInfoId(rr_switch_override_inf_.size());
rr_switch_override_inf_.push_back(switch_override_info);
return switch_offset_info_id;
}

inline void set_edge_offset_id(RREdgeId edge_id, RRSwitchOffsetInfoId offset_id) {
node_storage_.set_edge_offset_id(edge_id, offset_id);
}

inline vtr::vector<RRSwitchOffsetInfoId, t_rr_switch_override_inf>& rr_switch_offset_inf() {
return rr_switch_override_inf_;
}

/** @brief Set the type of a node with a given valid id */
inline void set_node_type(RRNodeId id, t_rr_type type) {
node_storage_.set_node_type(id, type);
}

/** @brief Set the node name with a given valid id */
inline void set_node_name(RRNodeId id, std::string name) {
inline void set_node_name(RRNodeId id, const std::string& name) {
node_storage_.set_node_name(id, name);
}
/**
Expand Down Expand Up @@ -315,6 +335,9 @@ class RRGraphBuilder {
inline void reserve_switches(size_t num_switches) {
this->rr_switch_inf_.reserve(num_switches);
}
inline void reserve_switch_offse_info(size_t num_offsets) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name mispelt?

this->rr_switch_override_inf_.reserve(num_offsets);
}
/** @brief This function resize node storage to accomidate size RR nodes. */
inline void resize_nodes(size_t size) {
node_storage_.resize(size);
Expand All @@ -328,6 +351,7 @@ class RRGraphBuilder {
/** @brief This function resize rr_switch to accomidate size RR Switch. */
inline void resize_switches(size_t size) {
rr_switch_inf_.resize(size);
rr_switch_override_inf_.resize(size);
}

/** @brief Validate that edge data is partitioned correctly
Expand Down Expand Up @@ -357,7 +381,7 @@ class RRGraphBuilder {
/** @brief Disable the flags which would prevent adding adding extra-resources, when flat-routing
* is enabled, to the RR Graph
* @note
* When flat-routing is enabled, intra-cluster resources are added to the RR Graph after global rosources
* When flat-routing is enabled, intra-cluster resources are added to the RR Graph after global resources
* are already added. This function disables the flags which would prevent adding extra-resources to the RR Graph
*/
inline void reset_rr_graph_flags() {
Expand Down Expand Up @@ -396,6 +420,8 @@ class RRGraphBuilder {
/* Detailed information about the switches, which are used in the RRGraph */
vtr::vector<RRSwitchId, t_rr_switch_inf> rr_switch_inf_;

vtr::vector<RRSwitchOffsetInfoId, t_rr_switch_override_inf> rr_switch_override_inf_;

/** @warning The Metadata should stay as an independent data structure from the rest of the internal data,
* e.g., node_lookup! */
/* Metadata is an extra data on rr-nodes and edges, respectively, that is not used by vpr
Expand Down
1 change: 1 addition & 0 deletions libs/librrgraph/src/base/rr_graph_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ typedef vtr::StrongId<rr_node_id_tag, uint32_t> RRNodeId;
typedef vtr::StrongId<rr_edge_id_tag, uint32_t> RREdgeId;
typedef vtr::StrongId<rr_indexed_data_id_tag, uint32_t> RRIndexedDataId;
typedef vtr::StrongId<rr_switch_id_tag, uint16_t> RRSwitchId;
typedef vtr::StrongId<rr_switch_id_tag, uint16_t> RRSwitchOffsetInfoId;
typedef vtr::StrongId<rr_segment_id_tag, uint16_t> RRSegmentId;
typedef vtr::StrongId<rc_index_tag, uint16_t> NodeRCIndex;

Expand Down
46 changes: 40 additions & 6 deletions libs/librrgraph/src/base/rr_graph_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ void t_rr_graph_storage::reserve_edges(size_t num_edges) {
edge_src_node_.reserve(num_edges);
edge_dest_node_.reserve(num_edges);
edge_switch_.reserve(num_edges);
edge_switch_offset_inf_.reserve(num_edges);
edge_remapped_.reserve(num_edges);
}

Expand All @@ -19,6 +20,7 @@ void t_rr_graph_storage::emplace_back_edge(RRNodeId src, RRNodeId dest, short ed
edge_src_node_.emplace_back(src);
edge_dest_node_.emplace_back(dest);
edge_switch_.emplace_back(edge_switch);
edge_switch_offset_inf_.emplace_back(remapped ? (RRSwitchOffsetInfoId)edge_switch : RRSwitchOffsetInfoId::INVALID());
edge_remapped_.emplace_back(remapped);
}

Expand All @@ -43,10 +45,11 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges
edge_src_node_.reserve(new_capacity);
edge_dest_node_.reserve(new_capacity);
edge_switch_.reserve(new_capacity);
edge_switch_offset_inf_.reserve(new_capacity);
edge_remapped_.reserve(new_capacity);
}

for (const auto& new_edge : *rr_edges_to_create) {
for (const t_rr_edge_info& new_edge : *rr_edges_to_create) {
emplace_back_edge(
new_edge.from_node,
new_edge.to_node,
Expand All @@ -64,7 +67,7 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges
* edge_swapper is a reference for the src/dest/switch tuple, and can convert
* to and from t_rr_edge_info, the value_type for edge_sort_iterator.
*
* edge_compare_src_node_and_configurable_first is a comparision operator
* edge_compare_src_node_and_configurable_first is a comparison operator
* that first partitions the edge data by source rr node, and then by
* configurable switches first. Sorting by this comparision operator means that
* the edge data is directly usable for each node by simply slicing the arrays.
Expand All @@ -87,6 +90,7 @@ struct edge_swapper {
storage_->edge_src_node_[edge] = storage_->edge_src_node_[other_edge];
storage_->edge_dest_node_[edge] = storage_->edge_dest_node_[other_edge];
storage_->edge_switch_[edge] = storage_->edge_switch_[other_edge];
storage_->edge_switch_offset_inf_[edge] = storage_->edge_switch_offset_inf_[other_edge];
storage_->edge_remapped_[edge] = storage_->edge_remapped_[other_edge];
return *this;
}
Expand All @@ -97,6 +101,7 @@ struct edge_swapper {
storage_->edge_src_node_[RREdgeId(idx_)] = RRNodeId(edge.from_node);
storage_->edge_dest_node_[RREdgeId(idx_)] = RRNodeId(edge.to_node);
storage_->edge_switch_[RREdgeId(idx_)] = edge.switch_type;
storage_->edge_switch_offset_inf_[RREdgeId(idx_)] = edge.remapped ? (RRSwitchOffsetInfoId)edge.switch_type : RRSwitchOffsetInfoId::INVALID();
storage_->edge_remapped_[RREdgeId(idx_)] = edge.remapped;
return *this;
}
Expand All @@ -123,6 +128,7 @@ struct edge_swapper {
std::swap(a.storage_->edge_src_node_[a_edge], a.storage_->edge_src_node_[b_edge]);
std::swap(a.storage_->edge_dest_node_[a_edge], a.storage_->edge_dest_node_[b_edge]);
std::swap(a.storage_->edge_switch_[a_edge], a.storage_->edge_switch_[b_edge]);
std::swap(a.storage_->edge_switch_offset_inf_[a_edge], a.storage_->edge_switch_offset_inf_[b_edge]);
std::vector<bool>::swap(a.storage_->edge_remapped_[a_edge], a.storage_->edge_remapped_[b_edge]);
}

Expand Down Expand Up @@ -161,7 +167,7 @@ class edge_sort_iterator {
// it needs to "act" like a pointer. One thing that it should do is that a
// const variable of this type should be de-referenceable. Therefore, this
// method should be const method; however, this requires modifying the class
// and may yield worst performance. For now the std::stable_sort allows this
// and may yield worse performance. For now the std::stable_sort allows this
// but in the future it may not. If this breaks, this is why.
// See issue #2517 and PR #2522
edge_swapper& operator*() {
Expand Down Expand Up @@ -354,6 +360,7 @@ void t_rr_graph_storage::assign_first_edges() {
size_t num_edges = edge_src_node_.size();
VTR_ASSERT(edge_dest_node_.size() == num_edges);
VTR_ASSERT(edge_switch_.size() == num_edges);
VTR_ASSERT(edge_switch_offset_inf_.size() == num_edges);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think one flyweight for edge data would be best, rather than two (switch_inf and edge_switch_offset_inf). Try to store one flyweight id per edge; we can set it up the same way as today during rr-graph building and then update it if the user requests that with an option saying they want a detailed delay file.

VTR_ASSERT(edge_remapped_.size() == num_edges);
while (true) {
VTR_ASSERT(first_id < num_edges);
Expand Down Expand Up @@ -410,7 +417,7 @@ void t_rr_graph_storage::init_fan_in() {
node_fan_in_.resize(node_storage_.size(), 0);
node_fan_in_.shrink_to_fit();
//Walk the graph and increment fanin on all downstream nodes
for(const auto& edge_id : edge_dest_node_.keys()) {
for(const RREdgeId edge_id : edge_dest_node_.keys()) {
node_fan_in_[edge_dest_node_[edge_id]] += 1;
}
}
Expand Down Expand Up @@ -497,6 +504,7 @@ void t_rr_graph_storage::remap_rr_node_switch_indices(const t_arch_switch_fanin&
for (size_t i = 0; i < edge_src_node_.size(); ++i) {
RREdgeId edge(i);
if(edge_remapped_[edge]) {
VTR_ASSERT(edge_switch_offset_inf_[edge].is_valid());
continue;
}

Expand All @@ -514,6 +522,7 @@ void t_rr_graph_storage::remap_rr_node_switch_indices(const t_arch_switch_fanin&
int rr_switch_index = itr->second;

edge_switch_[edge] = rr_switch_index;
edge_switch_offset_inf_[edge] = (RRSwitchOffsetInfoId)rr_switch_index;
edge_remapped_[edge] = true;
}
remapped_edges_ = true;
Expand Down Expand Up @@ -548,6 +557,14 @@ void t_rr_graph_storage::partition_edges(const vtr::vector<RRSwitchId, t_rr_swit
VTR_ASSERT_SAFE(validate(rr_switches));
}

void t_rr_graph_storage::set_edge_offset_id(RREdgeId edge_id, RRSwitchOffsetInfoId offset_id) {
VTR_ASSERT_DEBUG(partitioned_);
VTR_ASSERT_DEBUG(remapped_edges_);
VTR_ASSERT_DEBUG(edge_switch_offset_inf_[edge_id].is_valid());

edge_switch_offset_inf_[edge_id] = offset_id;
}

t_edge_size t_rr_graph_storage::num_configurable_edges(RRNodeId id, const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switches) const {
VTR_ASSERT(!node_first_edge_.empty() && remapped_edges_);

Expand All @@ -572,6 +589,21 @@ bool t_rr_graph_storage::edge_is_configurable(RRNodeId id, t_edge_size iedge, co
return rr_switches[RRSwitchId(iswitch)].configurable();
}

bool t_rr_graph_storage::edge_is_configurable(RREdgeId id, const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switches) const {
auto iswitch = edge_switch(id);
return rr_switches[RRSwitchId(iswitch)].configurable();
}

bool t_rr_graph_storage::edge_is_buffered(RRNodeId id, t_edge_size iedge, const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switches) const {
auto iswitch = edge_switch(id, iedge);
return rr_switches[RRSwitchId(iswitch)].buffered();
}

bool t_rr_graph_storage::edge_is_buffered(RREdgeId id, const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switches) const {
auto iswitch = edge_switch(id);
return rr_switches[RRSwitchId(iswitch)].buffered();
}

bool t_rr_graph_storage::validate_node(RRNodeId node_id, const vtr::vector<RRSwitchId, t_rr_switch_inf>& rr_switches) const {
t_edge_size iedge = 0;
for (auto edge : edges(node_id)) {
Expand Down Expand Up @@ -618,7 +650,7 @@ const std::string& t_rr_graph_storage::node_direction_string(RRNodeId id) const
}

const char* t_rr_graph_storage::node_side_string(RRNodeId id) const {
for (const e_side& side : TOTAL_2D_SIDES) {
for (const e_side side : TOTAL_2D_SIDES) {
if (is_node_on_specific_side(id, side)) {
return TOTAL_2D_SIDE_STRINGS[side];
}
Expand Down Expand Up @@ -720,7 +752,7 @@ void t_rr_graph_storage::set_node_type(RRNodeId id, t_rr_type new_type) {
node_storage_[id].type_ = new_type;
}

void t_rr_graph_storage::set_node_name(RRNodeId id, std::string new_name) {
void t_rr_graph_storage::set_node_name(RRNodeId id, const std::string& new_name) {
node_name_.insert(std::make_pair(id, new_name));
}
void t_rr_graph_storage::set_node_coordinates(RRNodeId id, short x1, short y1, short x2, short y2) {
Expand Down Expand Up @@ -856,6 +888,7 @@ void t_rr_graph_storage::reorder(const vtr::vector<RRNodeId, RRNodeId>& order,
auto old_edge_src_node = edge_src_node_;
auto old_edge_dest_node = edge_dest_node_;
auto old_edge_switch = edge_switch_;
auto old_edge_switch_offset_inf_ = edge_switch_offset_inf_;
auto old_edge_remapped = edge_remapped_;
RREdgeId cur_edge(0);

Expand All @@ -869,6 +902,7 @@ void t_rr_graph_storage::reorder(const vtr::vector<RRNodeId, RRNodeId>& order,
edge_src_node_[cur_edge] = order[old_edge_src_node[e]]; // == n?
edge_dest_node_[cur_edge] = order[old_edge_dest_node[e]];
edge_switch_[cur_edge] = old_edge_switch[e];
edge_switch_offset_inf_[cur_edge] = old_edge_switch_offset_inf_[e];
edge_remapped_[cur_edge] = old_edge_remapped[e];
cur_edge = RREdgeId(size_t(cur_edge) + 1);
}
Expand Down
Loading
Loading