Skip to content

Conversation

@arthurjolo
Copy link
Contributor

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.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a 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.

Comment on lines 135 to 136
void setCurrWl(unsigned wl) { curr_Wl_ = wl; }
unsigned getCurrWl() const { return curr_Wl_; }
Copy link
Contributor

Choose a reason for hiding this comment

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

high

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.

Suggested change
void setCurrWl(unsigned wl) { curr_Wl_ = wl; }
unsigned getCurrWl() const { return curr_Wl_; }
void setCurrWl(int wl) { currWl_ = wl; }
int getCurrWl() const { return currWl_; }

unsigned outputSlew_ = 0;
unsigned outputCap_ = 0;
unsigned remainingLength_ = 0;
unsigned curr_Wl_ = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The member variable curr_Wl_ should be of type int to match its usage in HTreeBuilder.cpp and avoid signed/unsigned conversion issues. The name should also be currWl_ for consistency with other members like outputSlew_.

Suggested change
unsigned curr_Wl_ = 0;
int currWl_ = 0;

Comment on lines +1570 to +1579
if (seg.isBuffered()
&& (currWl + seg.getWl2FisrtBuffer() > wirelengthThreshold)) {
return;
}

if (!seg.isBuffered()
&& (currWl + seg.getWl2FisrtBuffer()
> wirelengthThreshold - techChar_->getMinSegmentLength())) {
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

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;
              }
            }

@github-actions
Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@github-actions
Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@arthurjolo arthurjolo requested a review from maliberty December 31, 2025 18:03
@maliberty
Copy link
Member

secure-ci?

const unsigned SLEW_THRESHOLD = options_->getMaxSlew();
const unsigned INIT_TOLERANCE = 1;

int WIRELENGTH_THRESHOLD;
Copy link
Member

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.

Comment on lines 1422 to 1423
const unsigned SLEW_THRESHOLD = options_->getMaxSlew();
const unsigned INIT_TOLERANCE = 1;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
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)) {
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants