-
Notifications
You must be signed in to change notification settings - Fork 755
CTS techChar: add max wl constraint #9145
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
base: master
Are you sure you want to change the base?
CTS techChar: add max wl constraint #9145
Conversation
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.
Code Review
This pull request introduces a maximum wirelength constraint in techChar to prevent Clock Tree Synthesis (CTS) from favoring long pure wire segments over buffered topologies. This is a good strategy to improve timing by guiding the tool. The implementation is mostly sound, involving a new option that is propagated to the HTreeBuilder for pruning wire segments. However, I've identified a few issues: a potential bug if the wirelength threshold isn't set, a type mismatch that could lead to subtle errors, and some typos. Addressing these points will enhance the robustness and maintainability of the new feature.
src/cts/src/HTreeBuilder.h
Outdated
| void setCurrWl(unsigned wl) { curr_Wl_ = wl; } | ||
| unsigned getCurrWl() const { return curr_Wl_; } |
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 type for currWl should be int to match its usage throughout HTreeBuilder.cpp, where it is used as an int. Using unsigned here can lead to signed/unsigned conversion issues. Also, for consistency with other member variables, the member variable should be named currWl_ and its accessors updated accordingly.
| void setCurrWl(unsigned wl) { curr_Wl_ = wl; } | |
| unsigned getCurrWl() const { return curr_Wl_; } | |
| void setCurrWl(int wl) { currWl_ = wl; } | |
| int getCurrWl() const { return currWl_; } |
src/cts/src/HTreeBuilder.h
Outdated
| unsigned outputSlew_ = 0; | ||
| unsigned outputCap_ = 0; | ||
| unsigned remainingLength_ = 0; | ||
| unsigned curr_Wl_ = 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.
| if (seg.isBuffered() | ||
| && (currWl + seg.getWl2FisrtBuffer() > wirelengthThreshold)) { | ||
| return; | ||
| } | ||
|
|
||
| if (!seg.isBuffered() | ||
| && (currWl + seg.getWl2FisrtBuffer() | ||
| > wirelengthThreshold - techChar_->getMinSegmentLength())) { | ||
| return; | ||
| } |
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.
If options_->getMaxWl() is not set, wirelengthThreshold will be 0. In this case, currWl + seg.getWl2FisrtBuffer() > wirelengthThreshold will likely be true for any segment, causing all segments to be pruned. This would prevent CTS from finding a solution. The wirelength constraint should only be applied when wirelengthThreshold is positive.
if (wirelengthThreshold > 0) {
if (seg.isBuffered()
&& (currWl + seg.getWl2FisrtBuffer() > wirelengthThreshold)) {
return;
}
if (!seg.isBuffered()
&& (currWl + seg.getWl2FisrtBuffer()
> wirelengthThreshold - techChar_->getMinSegmentLength())) {
return;
}
}|
clang-tidy review says "All clean, LGTM! 👍" |
|
clang-tidy review says "All clean, LGTM! 👍" |
|
secure-ci? |
| const unsigned SLEW_THRESHOLD = options_->getMaxSlew(); | ||
| const unsigned INIT_TOLERANCE = 1; | ||
|
|
||
| int WIRELENGTH_THRESHOLD; |
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 an ordinary variable so use lower case naming.
| const unsigned SLEW_THRESHOLD = options_->getMaxSlew(); | ||
| const unsigned INIT_TOLERANCE = 1; |
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.
| const unsigned SLEW_THRESHOLD = options_->getMaxSlew(); | |
| const unsigned INIT_TOLERANCE = 1; | |
| const unsigned kSlewThreshold = options_->getMaxSlew(); | |
| const unsigned kInitTolerance = 1; |
| } | ||
|
|
||
| if (seg.isBuffered() | ||
| && (currWl + seg.getWl2FisrtBuffer() > wirelengthThreshold)) { |
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.
Please fix the typo in getWl2FisrtBuffer -> getWl2FirstBuffer
Problem
During the HTree building process CTS chooses wire topologies made by techChar. The decision on which topology to use is made by the delay and output slew of the topology, choosing the one with that respects the output slew threshold and has the minimum delay.
This approach ends up causing CTS to always choose pure wire topologies, that are usually faster than buffered ones, only choosing a buffered topology when it violates to the slew threshold. For some designs we use too many pure wire topologies in seqeunce that a buffered topology would be faster but techChar doesn't notices that.
Fix
To fix this issue, this PR adds a max wirelength threshold that is applied the same way as the slew threshold, preventing CTS from adding long wires in the middle of the tree. The value for this threshold is the
resizer max_wirelength.Disclamer
Although this PR is able to fix this issue, techChar should be able to understand that choosing too many wired topology in sequence is slower that adding a buffered topology without a threshold to prevent this. TechChar needs some more investigation regarding this issue.