-
Notifications
You must be signed in to change notification settings - Fork 415
RR Graph Overlay Creation and Deploy new node_type() API of Overlay #1693
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
RR Graph Overlay Creation and Deploy new node_type() API of Overlay #1693
Conversation
…this overlay aims to provide full featured RRGraph APIs.
…rilog-to-routing into rr_graph_node_type_overlay
…iles with minor code format fix
…nsion RRGraphBuilderView (mutable)
@vaughnbetz @litghost
|
* - This is the only data structre allowed to modify a routing resource graph | ||
* | ||
*/ | ||
class RRGraphBuilderView : public RRGraphView { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No inheritance of classes with non-abstract methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second that.
Inheritance is reaaaally rarely used in real world code as it has all kinds of issues (fragile base class, hard to figure out what is going on in a stack of classes.
In the early days of object oriented programming, everyone thought that was a good idea, but, turns out composition is what is mostly reflecting what we want and inheritance is only really useful to describe abstract things and their implementation (meaning: the concept of interface and implementation)).
Base classes are typically only done with interfaces; that is when the base class defines an API of sorts, but with all abstract virtual methods; then there are implementations that implement that (this is what Keith said with the comment above: unless we use the concept of implementing an interface, don't use inheritance).
April 1 discussion:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, let me introduce myself: I am Henner, working with @litghost on Symbiflow FPGA stuff. Since Keith is going to work on other interesting things and can't be as much involved, I'll be helping with guidance and reviews on this project.
I'll be in the next meetings, so then I'll say hello in person :)
WRT to this project, I still have to go through all the docs; in general we probably want to go in small steps, abstracting one aspect at a time, providing accessors instead of direct access to members etc. Small pull requests (100-250 lines max) are probably good stepping stones to transform the code-base into the right direction. Starting from transforming the 'consumer' part of the RR-graph to have more abstract ways to access it, then allows in further steps to address the builder to provide things we need.
Once I get into the project I can help guide towards a robust and future-compatible API.
So below, the comments are mostly directly the C++ specific comments that come to mind immediately and that are somewhat independent of wherever the project goes. I hope they can be valuable feedback even if the scope will change. Not using inheritance unless for interface implementations, initializing things as much as possible in the constructor initializer list, sorting headers, IWUY etc. are universal good practices that can be applied right away.
* Mutators | ||
****************************/ | ||
void RRGraphBuilderView::add_node_to_fast_lookup(const RRNodeId& node, | ||
const int& x, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using references for simple integer types is not very useful. Only use references when you have to.
(problem is not only that there is a pointer instead of a shorter immediate type to be passed (and thus not only have to transfer 64 bits instead of 32 in this case, but if you invoke it with a number, the compiler has to generate an intermediate object that has an address), but also, that the compiler needs to often generate special code to make sure not to run into aliasing issues, which you don't have if you just copy things).
So integral values (int, char, int64_t, size_t, ...) always should be passed by value if you just have it as an in-parameter. Also for things such as std::string_view
things are faster and better by value not const reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Updated the codes
@@ -9,6 +9,7 @@ | |||
#include "vtr_vector.h" | |||
#include "atom_netlist.h" | |||
#include "clustered_netlist.h" | |||
#include "rr_graph_view.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest to always sort all headers alphabetically.
That way it is harder possible to create merge conflicts if everyone does the same.
(I realize that this is not how the practice was in this file, but I suggest to adopt that practice. It also sometimes helps finding hidden dependencies in which header files only work when included in a particular sequence)
So in emacs that would be: mark the block with all includes then M-x sort-lines
; other editors have a similar feature.
In general it is adivsable to follow the practices like in this style guide: grouping blocks of c-headers, c++ headers and project headers.
(Might be worth-while to have a separate cleanup-run of this, not necessarily in this pull request. So consider this an FYI with future influence)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sense to me. I will avoid modifying the vpr_context.h
because it is not the focus of this PR. But I will force the alphabetical order of header files in newly created files in this PR.
* Constructors | ||
****************************/ | ||
RRGraphBuilderView::RRGraphBuilderView(t_rr_graph_storage* node_storage, | ||
t_rr_node_indices* rr_node_indices) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always use constructor initializer list for simple assigning of things wherelver possible. The constructor body should only really be used if we have some work that needs to be done (which, incidently, we want to avoid as much as possible in constructors, because we don't have a way to fail in a constructor - except exceptions of course, which we of course want to avoid).
So
RRGraphBuilderView::RRGraphBuilderView(t_rr_graph_storage* node_storage,
t_rr_node_indices* rr_node_indices)
: node_storage(node_storage), rr_node_indices_(rr_node_indices) {
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, and I see, in this case you're actually initializing values from a base class. Never do that, only access the base class through its constructor.
So the base-class should have RRGraphView::RRGraphView(... these nodes ...) : node_storage(...), rr_node_indeices(...) {}
.
And then here, you initialize it with
RRGraphBuilderView::RRGraphBuilderView(t_rr_graph_storage* node_storage,
t_rr_node_indices* rr_node_indices)
: RRGraphView(node_storage, rr_node_indices) {
}
... but see also other comments about inheritance. This is probably not what you want anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comment. I was looking for something like this and failed to find related tutorials. I have updated the codes.
RRGraphBuilderView(t_rr_graph_storage* node_storage, | ||
t_rr_node_indices* rr_node_indices); | ||
|
||
/**************** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd avoid the comments such as /* constructors ... */
/*mutators ...*/
that don't provide additional useful information the reader wouldn't already notice: it just adds more vertical space someone has to scroll through to get to the interesting parts (also in other files in this pull request).
Instead, focus on comments on each constructor or method. What are the parameters for these, how are these important, what does or provide the method. These are the relevant parts for someone later using the API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The organization was actually suggested when prototyping the data structure RRGraphObject. We want to guide developers quickly to the constructors and accessors, which the developers care most. I am open to discussion still. This is mainly due to the suggested organization is not clear to me yet. We can have more discussion.
* Mutators | ||
****************/ | ||
public: | ||
/* Register a node in the fast look-up */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each of the parameters need to be explained. This is a public interface, so that is what users of this API will look at to know what to do. Use Doxygen-style commenting style, in which the paramter is in quotes.
Something like
Add "node" at position ("x","y"). The "type" is .. blabla whatever needs to be described here
The name of the function looks like it mixes intent ("add_node()") and implementation detail : to_fast_lookup
- this is something that is up to the implementation in which way it will add the nodes (one would hope for always fast look-up I presume :)).
This is a good name for a private method name as there you have more of the implementation details that are important. The public interface should only contain names that describe what we expect from something this class should do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. I will see what comments to added.
vpr/src/device/rr_graph_view.h
Outdated
/**************** | ||
* internal data storage, can be accessed by parent class RRGraphBuilderView | ||
****************/ | ||
protected: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected
on data members is what we rarely should have to do. If the derived classes need to have access to the raw members, make protected getters, but keep the members private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Changed to private now.
@@ -1534,6 +1537,10 @@ class RrGraphSerializer final : public uxsd::RrGraphBase<RrGraphContextTypes> { | |||
VTR_ASSERT(read_rr_graph_name_ != nullptr); | |||
read_rr_graph_filename_->assign(read_rr_graph_name_); | |||
|
|||
/* Update RRGraph viewer with new data pointers */ | |||
rr_graph_->set_internal_data(rr_nodes_, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above, but this sounds like we want to avoid that and consider making a fresh rr_graph_
with pointers that are only assigned once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Removed.
@@ -0,0 +1,53 @@ | |||
#ifndef _RR_GRAPH_BUILDER_VIEW_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid leading undrescores in the include-guards as they are reserved for c/c++ compiler internals.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Updated.
#ifndef _RR_GRAPH_BUILDER_VIEW_ | ||
#define _RR_GRAPH_BUILDER_VIEW_ | ||
|
||
#include <exception> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you include <exception>
? I don't see that needed anywhere below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Removed all the unused headers.
#include "vtr_strong_id_range.h" | ||
#include "vtr_array_view.h" | ||
#include "rr_graph_storage.h" | ||
#include "rr_graph_view.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Below, the types rr_graph_storage
, rr_node_indices
, RRNodeId
, t_rr_type
and e_side
are used. Do we have to include all the above to get access to these ?
IWYU, but not more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Removed all the unused headers.
…_lookup as a sub data structure under rr_graph_view and rr_graph_builder
****************/ | ||
private: | ||
/* node-level storage including edge storages */ | ||
t_rr_graph_storage& node_storage_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only use references if they are const. If you have a modifiable object, use pointers instead (essentially like you did before).
Using non-const references creates a lot of confusion, in particular if used as instance variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fully agree this convention. This rule can improve code readability and help developers to know what they are doing easily. However, as you see in the figure I showed (copied to this PR as well), the builder function will be the owner of the data storages. That is why I temporarily use the reference here. It can avoid a lot of code changes once the refactoring is finished (there is no function get data directly through the node_storage
in DeviceContext
). My concern is that if I use pointers, it may cause many codes in client functions or inside the data structures to be changed later.
Here are my concerns and I am open to discussion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK with me. Eventually the ability to get the node_storage will be removed (best) or if necessary re-written to use pointers.
Hi @hzeller @litghost @vaughnbetz Just a summary what we talked and what we agreed today:
From my point of view, we can plan the refactoring in this way:
After that, we have achieved the milestone where the builder has been improved to avoid direct write/read on the lookup data structure. Looking forward to your feedbacks. |
That makes sense to me.
|
…GraphBuilder/RRSpatialLookup
…ifan/vtr-verilog-to-routing into rr_graph_node_type_overlay
Hi @vaughnbetz @hzeller
This PR showcased the use of the new data structures in both builder and client functions |
* Accessors | ||
****************/ | ||
public: | ||
/* Get the type of a routing resource node */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably good to add a TODO comment saying that the goal is to have these accessors private at some point totally replaced with the 'questioin' kind of methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The TODO comment is useful. But not every API will be converted to the questionin
methods. But the questionin
style is preferred.
…redundant codes to short the code view
@hzeller I have applied your comments on the code comments. @kmurray If you have time to review this PR, feel free to comment.
|
****************/ | ||
private: | ||
/* node-level storage including edge storages */ | ||
t_rr_graph_storage& node_storage_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK with me. Eventually the ability to get the node_storage will be removed (best) or if necessary re-written to use pointers.
vpr/src/device/rr_spatial_lookup.cpp
Outdated
if (type == IPIN || type == OPIN) { | ||
VTR_ASSERT_MSG(side != NUM_SIDES, "IPIN/OPIN must specify desired side (can not be default NUM_SIDES)"); | ||
} else { | ||
VTR_ASSERT(type != IPIN && type != OPIN); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't really need this assert, as the prior if guarantees it is true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. The assertation is just a safety check. Currently, I prefer to changing it to VTR_ASSERT_SAFE, which will not be considered unless in debug mode (no runtime cost in release mode). I am also o.k. to remove it. Please let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, your call. I'm OK with VTR_ASSERT_SAFE if you prefer, although I personally don't put asserts right in an if-chain where it is obvious the assert can't fire based on the if/else condition.
VTR_ASSERT_MSG(side != NUM_SIDES, "IPIN/OPIN must specify desired side (can not be default NUM_SIDES)"); | ||
} else { | ||
VTR_ASSERT(type != IPIN && type != OPIN); | ||
node_side = SIDES[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment why this is done. Node side not relevant for nodes that aren't IPINs or OPINS; set to an arbitrary side?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Added comments to clarify this.
* registering a CHANX node in the look-up | ||
* TODO: Once the builders is reworked for use consistent (x, y) convention, | ||
* the following swapping can be removed | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I did this years ago to allow re-use of the same data structure; it is ugly!
|
||
if (node_side >= rr_node_indices_[type].dim_size(2)) { | ||
return RRNodeId::INVALID(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should add the same code to return RRNodeID::INVALID for node_x, node_y, node_side, ptc being < 0 too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. However, the node_x
, node_y
are already in the size_t
data type, they cannot be less than 0 (converted from x
, y
which are int
). If x
is negative, when converted to size_t
, it will be a huge number and out-of-range in the fast look-up. But it is really tricky. So, I added a pre-check on the x
, y
, node_side
and ptc
to return invalid ids when one of them is negative.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I didn't think of that. In that case I'm OK with just a comment noting that will happen. If you've added the pre-check for < 0 already that's fine too.
vpr/src/device/rr_spatial_lookup.h
Outdated
* Note that for segments (CHANX and CHANY) of length > 1, the segment is | ||
* given an rr_index based on the (x,y) location at which it starts (i.e. | ||
* lowest (x,y) location at which this segment exists). | ||
* This routine also performs error checking to make sure the node in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd move this comment "This routine also " to the end of the comment block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment applied.
vpr/src/device/rr_spatial_lookup.h
Outdated
* 2. track index in a routing channel when type is CHANX/CHANY | ||
* - side is the side of node on the tile, applicable to OPIN/IPIN | ||
* | ||
* Note that the add node here will not create a node in the node list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that a node added with this call will not create a node in the rr_graph_storage node list ..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment applied.
vpr/src/device/rr_spatial_lookup.h
Outdated
/* Register a node in the fast look-up | ||
* - You must have a node id | ||
* 1. a valid one is to register a node in the lookup | ||
* 2. an invalid id means the removal of a node from the lookup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"2. an invalid id means the removal of a node from the lookup"
I don't think the .cpp file code actually does that, and it would be a strange convention. I think this part of the comment should be removed. If the comment is correct, I think we should change the convention and instead make a remove_node function.
Or perhaps this comment is intended for the data storage itself and means we can store an invalid node ID in rr_node_indices to indicate that node does not exist. That would be OK, but that comment should go with the storage declaration, not in front of the add_node function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. The use of invalid id is very tricky. It just unregisters a node from the lookup.
Actually, I should not state it because we should not promote such use of the API.
Therefore, I removed this line. We should add an API remove_node()
. I put this TODO item in the comment.
* The 'side' argument only applies to IPIN/OPIN types, and specifies which | ||
* side of the grid tile the node should be located on. The value is ignored | ||
* for non-IPIN/OPIN types | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should mention that RR_NODE_INVALID is returned if the node does not exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Comment applied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the comment is in the wrong spot (add_node, but should be in find_node).
@@ -970,8 +971,12 @@ static void load_chan_rr_indices(const int max_chan_width, | |||
} | |||
} | |||
|
|||
static void load_block_rr_indices(const DeviceGrid& grid, | |||
/* As the rr_indices builders modify a local copy of indices, use the local copy in the builder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite understand this. There is both a local couple of the rr_indices data structure and another copy in the RRGraphBuilder. It looks like some data is put in the version in the builder (with add_node) and some is in the local copy (with direct data structure access). I'm not sure where the local copy is copied back to the RRGraphBuilder copy.
It would be good to clean this up sooner rather than later. The circular dependency in the header files (rr_graph2.h etc.) should be resolvable by refactoring the header files / making other headers. Ideally we'd just use the builder functions when adding nodes to the rr_indices data structure, and would have only one copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is indeed confusing. We actually share the data pointers between the rr_indices
and RRGraphBuilder
when initializing the DeviceContext
. So the two data structures are always synchronized.
Currently, the data ownership remains in the rr_indices
because I avoid to modify many codes in rr_graph2.cpp which will make this PR tedious. I just modify a very small part to showcase that the new data structure is working fine.
And you are right. This code should be cleaned up ASAP. I also stated in the TODO of the comment in LINE 975. I will start massively deployment of the RRGraphBuilder
in the function alloc_and_load_rr_indices()
in next PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I think you should comment the pointer aliasing right now though, so it's understandable how it works at this point. I didn't figure out that you'd aliased the pointers (both point at the same storage) and that's why the code worked.
@tangxifan : just finished reviewing this. Most of my feedback is minor (requests for comments or clarification), but I think there's one substantive thing: I'm not sure how the two copies of rr_indices (one in builder, one local) are synced up, and I think it would be good to get down to just one copy (in the RRGraphBuilder) sooner rather than later. |
@vaughnbetz Thanks a lot for the constructive comments. I have updated the PR and clarify as much as I can. Feel free to bug if you see anything confusing. |
vpr/src/device/rr_spatial_lookup.h
Outdated
* - track index in a routing channel when type is CHANX/CHANY | ||
* - side is the side of node on the tile, applicable to OPIN/IPIN | ||
* | ||
* An invalid id will be returned if the node does not exist |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this comment (an invalid id will be returned if the node does not exist) is in the wrong spot. It should be with find_node, not add_node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. I moved to the find_node() API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good Xifan, thanks. I added a few follow-up comments (one comment is in the wrong spot, think pointer aliasing of rr_node_indices should be commented even though it's a temporary fix). Other than that looks good to go.
Spoke too soon: looks like CI also caught a bug in an assert: |
…enabled later when remove_node() API is available in rr_spatial_lookup)
@vaughnbetz I have patched the comment and clarify the dirty sync between I will keep watching the CI and fix anything red. |
@vaughnbetz CI is green now. The pull request is ready for your review again. |
Updating branch (pretty sure no related changes went in, so this should be fine). I'll merge as soon as the fast running tests pass and show no compile or basic errors; no need to wait for vtr_reg_nightly I think. |
Everything passed except vtr nightly was in progress; updated again due to other changes. really will merge once the fast running tests are done. |
The Odin-II failure is unrelated; due to moving some runs onto kokoro (in progress). This has passed vtr_nightly before so merging it now (it's been rebased twice already). |
This PR kicks off the refactoring effort of the routing resource graph -related data structures.
A detailed technical plan can be found at link
The overall refactoring effort aims to
RRGraphView
as a centralized storage for all the routing resource graph -related information. See Fig. 1RRGraph
for client functions, which are suitable forrr_graph builder
,placer
,router
,GUI
,timing analyzer
etc. See Fig. 2.Fig. 1 Illustration of the relationship between data structures
Fig. 2 Different levels of frame views of routing resource graphs to satisfy various needs from client functions.
The result/benefits of the refactoring efforts is
RRGraph
. A routing resource graph builder can be a library, decoupled from VPR's core engine. Many checking codes can be efficiently merged into the data structure and developers can save a lot of efforts in writing the atom-level sanity checks.RRGraphView
. In other words, routing resource graph will be read-only and only accessors are exposed to client functions. Developers have no worries on developing their own placer/router etc.Description
This PR adds:
RRGraphBuilder
as the writable data structure modeling a routing resource graph. It will encapsulaterr_nodes
andrr_node_indices
. (To keep this PR small, currently just bringrr_node_indices
in. ThisRRGraphBuilder
will be the one and only one interface for routing resource graph builder functions.RRGraphView
as the read-only data structure modeling a routing resource graph. It shares the data storage as theRRGraphBuilder
. ThisRRGraphView
is designed to be a full featured frame-view for client functions. A few variants may be introduced in later pull requests, such as reduced frame-views for client functions.RRGraphBuilder
andRRGraphView
are added toDeviceContext
and updated each time a routing resource graph is builtRRGraphBuilder
for updating therr_node_indices
.RRGraphBuilder
andRRGraphView
for data queries onrr_node_indices
.Related Issue
Motivation and Context
How Has This Been Tested?
Types of changes
Checklist: