Skip to content

Commit 2298aec

Browse files
committed
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-verilog-to-routing into ipin_base_cost
2 parents 6228a71 + 8b907a5 commit 2298aec

31 files changed

+810
-210
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,4 @@ cmake-build-release
160160
# Clangd
161161
#
162162
compile_commands.json
163+
.clangd

doc/src/arch/reference.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,6 @@ Grid Layout Example
589589
590590
.. note:: Exactly one of the ``x`` or ``y`` attributes must be specified.
591591
592-
.. note:: Interposers are experimental and are currently not supported by VPR and using the related tags will not actually result in any changes to the flow.
593592
Defines an interposer cut for modelling 2.5D interposer-based architectures. An interposer cut will cut all connections at location 'loc' along the axis 'dim' Leaving the two sides completely unconnected.
594593
To reconnect the two sides, this tag can have multiple <interdie_wire> tags as children to specify the connection between the two sides.
595594
@@ -2751,7 +2750,7 @@ The number of any additional wires or muxes created by scatter-gather specificat
27512750
Overview of how scatter-gather patterns work. First, connections from a switchblock location are selected according to the specification.
27522751
These selected connection are then muxed and passed through the scatter-gather node, which is typically a wire segment. The scatter-gather node then fans out or scatters in another switchblock location.
27532752
2754-
.. note:: Scatter-Gather patterns are only supported for 3D architectures where the scatter-gather links are unidirectional. They are not currently supported in 2D architectures or with bidirectional sg_links.
2753+
.. note:: Scatter-Gather patterns are only supported for uni-directional 3D and uni-directional 2D architectures. Bidirectional sg_links are not currently supported.
27552754
27562755
When instantiated, a scatter-gather pattern gathers connections from a switchblock and passes the connection through a multiplexer and the scatter-gather node which is typically a wire segment, then scatters or fans out somewhere else in the device. These patterns can be used to define 3D switchblocks. An example is shown below:
27572756

libs/libarchfpga/src/device_grid.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,19 @@ void DeviceGrid::count_instances() {
8989
}
9090
}
9191
}
92+
93+
bool DeviceGrid::has_interposer_cuts() const {
94+
for (const std::vector<int>& layer_h_cuts : horizontal_interposer_cuts_) {
95+
if (!layer_h_cuts.empty()) {
96+
return true;
97+
}
98+
}
99+
100+
for (const std::vector<int>& layer_v_cuts : vertical_interposer_cuts_) {
101+
if (!layer_v_cuts.empty()) {
102+
return true;
103+
}
104+
}
105+
106+
return false;
107+
}

libs/libarchfpga/src/device_grid.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ class DeviceGrid {
211211
return vertical_interposer_cuts_;
212212
}
213213

214+
/// Returns if the grid has any interposer cuts. You should use this function instead of
215+
/// checking if get_horizontal/vertical_interposer_cuts is empty, since the return value
216+
/// of those functions might look something like this: {{}} which is technically not empty.
217+
bool has_interposer_cuts() const;
218+
214219
private:
215220
/// @brief Counts the number of each tile type on each layer and store it in instance_counts_.
216221
/// It is called in the constructor.

libs/librrgraph/src/base/rr_graph_builder.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,18 @@ class RRGraphBuilder {
351351
inline void alloc_and_load_edges(const t_rr_edge_info_set* rr_edges_to_create) {
352352
node_storage_.alloc_and_load_edges(rr_edges_to_create);
353353
}
354+
355+
/** @brief Removes a given list of RREdgeIds from the RR Graph.
356+
* This method does not preserve the order of edges. If you're
357+
* calling it after partition_edges has been called, you will
358+
* need to call partition_edges again.
359+
* This operation is O(#RR Graph edges) and should not be called frequently.
360+
*
361+
* @param rr_edges_to_remove list of RREdgeIds to be removed
362+
*/
363+
inline void remove_edges(std::vector<RREdgeId>& rr_edges_to_remove) {
364+
node_storage_.remove_edges(rr_edges_to_remove);
365+
}
354366

355367
/** @brief Overrides the associated switch for a given edge by
356368
* updating the edge to use the passed in switch. */

libs/librrgraph/src/base/rr_graph_storage.cpp

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
#include "rr_graph_storage.h"
33
#include "physical_types.h"
44
#include "rr_graph_fwd.h"
5+
#include "vtr_assert.h"
56
#include "vtr_error.h"
67
#include "librrgraph_types.h"
8+
#include "vtr_util.h"
79

810
#include <algorithm>
911
#include <cstddef>
12+
#include <ranges>
1013

1114
void t_rr_graph_storage::reserve_edges(size_t num_edges) {
1215
edge_src_node_.reserve(num_edges);
@@ -57,6 +60,50 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges
5760
}
5861
}
5962

63+
void t_rr_graph_storage::remove_edges(std::vector<RREdgeId>& rr_edges_to_remove) {
64+
VTR_ASSERT(!edges_read_);
65+
66+
size_t starting_edge_count = edge_dest_node_.size();
67+
68+
// Sort and make sure all edge indices are unique
69+
vtr::uniquify(rr_edges_to_remove);
70+
VTR_ASSERT_SAFE(std::is_sorted(rr_edges_to_remove.begin(), rr_edges_to_remove.end()));
71+
72+
// Make sure the edge indices are valid
73+
VTR_ASSERT(static_cast<size_t>(rr_edges_to_remove.back()) <= edge_dest_node_.size());
74+
75+
// Index of the last edge
76+
size_t edge_list_end = edge_dest_node_.size() - 1;
77+
78+
// Iterate backwards through the list of indices we want to remove.
79+
80+
for (RREdgeId erase_idx : std::ranges::reverse_view(rr_edges_to_remove)) {
81+
// Copy what's at the end of the list to the index we wanted to remove
82+
edge_dest_node_[erase_idx] = edge_dest_node_[RREdgeId(edge_list_end)];
83+
edge_src_node_[erase_idx] = edge_src_node_[RREdgeId(edge_list_end)];
84+
edge_switch_[erase_idx] = edge_switch_[RREdgeId(edge_list_end)];
85+
edge_remapped_[erase_idx] = edge_remapped_[RREdgeId(edge_list_end)];
86+
87+
// At this point we have no copies of what was at erase_idx and two copies of
88+
// what was at the end of the list. If we make the list one element shorter,
89+
// we end up with a list that has removed the element at erase_idx.
90+
edge_list_end--;
91+
92+
}
93+
94+
// We have a new index to the end of the list, call erase on the elements past that index
95+
// to update the std::vector and shrink the actual data structures.
96+
edge_dest_node_.erase(edge_dest_node_.begin() + edge_list_end + 1, edge_dest_node_.end());
97+
edge_src_node_.erase(edge_src_node_.begin() + edge_list_end + 1, edge_src_node_.end());
98+
edge_switch_.erase(edge_switch_.begin() + edge_list_end + 1, edge_switch_.end());
99+
edge_remapped_.erase(edge_remapped_.begin() + edge_list_end + 1, edge_remapped_.end());
100+
101+
VTR_ASSERT(edge_dest_node_.size() == (starting_edge_count - rr_edges_to_remove.size()));
102+
103+
partitioned_ = false;
104+
}
105+
106+
60107
void t_rr_graph_storage::assign_first_edges() {
61108
VTR_ASSERT(node_first_edge_.empty());
62109

@@ -68,39 +115,42 @@ void t_rr_graph_storage::assign_first_edges() {
68115
edge_src_node_.end()));
69116

70117
size_t node_id = 0;
71-
size_t first_id = 0;
72-
size_t second_id = 0;
118+
size_t first_edge_id = 0;
119+
size_t second_edge_id = 0;
120+
73121
size_t num_edges = edge_src_node_.size();
74122
VTR_ASSERT(edge_dest_node_.size() == num_edges);
75123
VTR_ASSERT(edge_switch_.size() == num_edges);
76124
VTR_ASSERT(edge_remapped_.size() == num_edges);
125+
77126
while (true) {
78-
VTR_ASSERT(first_id < num_edges);
79-
VTR_ASSERT(second_id < num_edges);
80-
size_t current_node_id = size_t(edge_src_node_[RREdgeId(second_id)]);
127+
VTR_ASSERT(first_edge_id < num_edges);
128+
VTR_ASSERT(second_edge_id < num_edges);
129+
130+
size_t current_node_id = size_t(edge_src_node_[RREdgeId(second_edge_id)]);
81131
if (node_id < current_node_id) {
82132
// All edges belonging to node_id are assigned.
83133
while (node_id < current_node_id) {
84134
// Store any edges belongs to node_id.
85135
VTR_ASSERT(node_id < node_first_edge_.size());
86-
node_first_edge_[RRNodeId(node_id)] = RREdgeId(first_id);
87-
first_id = second_id;
136+
node_first_edge_[RRNodeId(node_id)] = RREdgeId(first_edge_id);
137+
first_edge_id = second_edge_id;
88138
node_id += 1;
89139
}
90140

91141
VTR_ASSERT(node_id == current_node_id);
92-
node_first_edge_[RRNodeId(node_id)] = RREdgeId(second_id);
142+
node_first_edge_[RRNodeId(node_id)] = RREdgeId(second_edge_id);
93143
} else {
94-
second_id += 1;
95-
if (second_id == num_edges) {
144+
second_edge_id += 1;
145+
if (second_edge_id == num_edges) {
96146
break;
97147
}
98148
}
99149
}
100150

101151
// All remaining nodes have no edges, set as such.
102152
for (size_t inode = node_id + 1; inode < node_first_edge_.size(); ++inode) {
103-
node_first_edge_[RRNodeId(inode)] = RREdgeId(second_id);
153+
node_first_edge_[RRNodeId(inode)] = RREdgeId(second_edge_id);
104154
}
105155

106156
VTR_ASSERT_SAFE(verify_first_edges());

libs/librrgraph/src/base/rr_graph_storage.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@ class t_rr_graph_storage {
400400
return vtr::StrongIdRange<RREdgeId>(first_edge(id), last_edge(id));
401401
}
402402

403+
/** @brief Returns a range of all edges in the RR Graph.
404+
* This method does not depend on the edges being correctly
405+
* sorted and can be used before partition_edges is called.
406+
*/
407+
inline vtr::StrongIdRange<RREdgeId> all_edges() const {
408+
return vtr::StrongIdRange<RREdgeId>(RREdgeId(0), RREdgeId(edge_src_node_.size()));
409+
}
410+
403411
/** @brief Retrieve the RREdgeId for iedge'th edge in RRNodeId.
404412
*
405413
* This method should generally not be used, and instead first_edge and
@@ -776,6 +784,16 @@ class t_rr_graph_storage {
776784
/** @brief Adds a batch of edges.*/
777785
void alloc_and_load_edges(const t_rr_edge_info_set* rr_edges_to_create);
778786

787+
/** @brief Removes a given list of RREdgeIds from the RR Graph.
788+
* This method does not preserve the order of edges. If you're
789+
* calling it after partition_edges has been called, you will
790+
* need to call partition_edges again.
791+
* This operation is O(#RR Graph edges) and should not be called frequently.
792+
*
793+
* @param rr_edges_to_remove list of RREdgeIds to be removed
794+
*/
795+
void remove_edges(std::vector<RREdgeId>& rr_edges_to_remove);
796+
779797
/* Edge finalization methods */
780798

781799
/** @brief Counts the number of rr switches needed based on fan in to support mux
@@ -840,7 +858,7 @@ class t_rr_graph_storage {
840858
// Generic lambda that allocates a 'vec'-sized new vector with all elements set to default value,
841859
// then builds the new vector to have rearranged elements from 'vec' and finaly move the new vector
842860
// to replace vec. Essentially does a permutation on vec based on edge_indices.
843-
auto array_rearrage = [&edge_indices] (auto& vec, auto default_value) {
861+
auto array_rearrange = [&edge_indices] (auto& vec, auto default_value) {
844862

845863
// Since vec could have any type, we need to figure out it's type to allocate new_vec.
846864
// The scary std::remove_reference stuff does exactly that. This does nothing other than building a new 'vec' sized vector.
@@ -858,10 +876,10 @@ class t_rr_graph_storage {
858876
vec = std::move(new_vec);
859877
};
860878

861-
array_rearrage(edge_src_node_, RRNodeId::INVALID());
862-
array_rearrage(edge_dest_node_, RRNodeId::INVALID());
863-
array_rearrage(edge_switch_, LIBRRGRAPH_UNDEFINED_VAL);
864-
array_rearrage(edge_remapped_, false);
879+
array_rearrange(edge_src_node_, RRNodeId::INVALID());
880+
array_rearrange(edge_dest_node_, RRNodeId::INVALID());
881+
array_rearrange(edge_switch_, LIBRRGRAPH_UNDEFINED_VAL);
882+
array_rearrange(edge_remapped_, false);
865883
}
866884

867885
/******************

libs/librrgraph/src/base/rr_graph_view.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,5 +129,3 @@ bool RRGraphView::validate_in_edges() const {
129129
}
130130
return true;
131131
}
132-
133-

libs/librrgraph/src/base/rr_graph_view.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@
6565
#include "metadata_storage.h"
6666
#include "rr_node.h"
6767
#include "physical_types.h"
68+
#include "rr_node_types.h"
6869
#include "rr_spatial_lookup.h"
6970
#include "vtr_geometry.h"
7071
#include "rr_graph_utils.h"
72+
#include "vtr_range.h"
7173

7274
class RRGraphView {
7375
/* -- Constructors -- */
@@ -584,18 +586,29 @@ class RRGraphView {
584586
* @example
585587
* RRGraphView rr_graph; // A dummy rr_graph for a short example
586588
* RRNodeId node; // A dummy node for a short example
587-
* for (RREdgeId edge : rr_graph.edges(node)) {
589+
* for (t_edge_size edge : rr_graph.edges(node)) {
588590
* // Do something with the edge
589591
* }
592+
*
593+
* @note Iterating on the range returned by this function will not give you an RREdgeId, but instead gives you the index among a node's outgoing edges
590594
*/
591-
inline edge_idx_range edges(const RRNodeId& id) const {
595+
inline edge_idx_range edges(RRNodeId id) const {
592596
return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(num_edges(id)));
593597
}
594598

599+
/** @brief Returns a range of all edges in the RR Graph.
600+
* This method does not depend on the edges begin correctly
601+
* sorted and can be used before partition_edges is called.
602+
*/
603+
inline vtr::StrongIdRange<RREdgeId> all_edges() const {
604+
return node_storage_.all_edges();
605+
}
606+
607+
595608
/**
596609
* @brief Return ID range for outgoing edges.
597610
*/
598-
inline edge_idx_range node_out_edges(const RRNodeId& id) const {
611+
inline edge_idx_range node_out_edges(RRNodeId id) const {
599612
return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(num_edges(id)));
600613
}
601614

vpr/src/analytical_place/analytical_placement_flow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static void print_ap_netlist_stats(const APNetlist& netlist) {
7777
* @param flat_placement_info The flat placement information to be read.
7878
* @param ap_netlist The APNetlist that used to iterate over its blocks.
7979
* @param prepacker The Prepacker to get molecule of blocks in the ap_netlist.
80-
* @param p_placement The partial placement to be updated which is assumend
80+
* @param p_placement The partial placement to be updated which is assumed
8181
* to be generated on ap_netlist or have the same blocks.
8282
*/
8383
static void convert_flat_to_partial_placement(const FlatPlacementInfo& flat_placement_info, const APNetlist& ap_netlist, const Prepacker& prepacker, PartialPlacement& p_placement) {

0 commit comments

Comments
 (0)