Skip to content

Debug or runtime fix#9543

Open
openroad-ci wants to merge 8 commits intoThe-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:debug_or_runtime_fix
Open

Debug or runtime fix#9543
openroad-ci wants to merge 8 commits intoThe-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:debug_or_runtime_fix

Conversation

@openroad-ci
Copy link
Collaborator

changes in dbNetwork

maliberty and others added 2 commits February 24, 2026 23:57
Cache the mterms on the dbInstHeader.  Intended to help sta performance.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…only

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
@dsengupta0628
Copy link
Contributor

Details in attached ppt
ascenium_design_runtime_debug.pptx

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 significant performance optimization by caching _dbMTerm pointers in _dbInstHdr, which speeds up getMTerm() lookups. The implementation of this caching mechanism appears to be thorough, with updates to object creation, serialization, and copy logic. Additionally, there's a fix in dbNetwork::libertyPort to correctly resolve liberty ports for pins, and an attempted optimization in getDbNwkObjectId. My review focuses on a potential issue with the optimization in getDbNwkObjectId where a bounds check is bypassed for common object types, which could lead to data corruption. Please see the specific comment for details.

Comment on lines 203 to 217
// Optimize for most common types to avoid switch overhead
if (typ == dbInstObj) {
return ((db_id << DBIDTAG_WIDTH) | DBINST_ID);
}
if (typ == dbNetObj) {
return ((db_id << DBIDTAG_WIDTH) | DBNET_ID);
}
if (typ == dbITermObj) {
return ((db_id << DBIDTAG_WIDTH) | DBITERM_ID);
}

// Bounds check only for debug/rare cases
if (db_id > (std::numeric_limits<ObjectId>::max() >> DBIDTAG_WIDTH)) {
logger_->error(ORD, 2019, "Database id exceeds capacity");
}
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 bounds check for db_id has been moved after the early returns for common object types (dbInstObj, dbNetObj, dbITermObj). This means that for these common types, the check is now skipped. If a large db_id is encountered for one of these types, it could lead to a silently corrupted ObjectId due to the left shift operation.

While the comment suggests this is intentional ("Bounds check only for debug/rare cases"), it introduces a risk of data corruption that was prevented by the original code. The performance gain from skipping this single if statement is likely minimal, while the risk is significant.

It is recommended to move the bounds check back to before the type-specific handling to ensure all db_id values are validated.

  if (db_id > (std::numeric_limits<ObjectId>::max() >> DBIDTAG_WIDTH)) {
    logger_->error(ORD, 2019, "Database id exceeds capacity");
  }

  // Optimize for most common types to avoid switch overhead
  if (typ == dbInstObj) {
    return ((db_id << DBIDTAG_WIDTH) | DBINST_ID);
  }
  if (typ == dbNetObj) {
    return ((db_id << DBIDTAG_WIDTH) | DBNET_ID);
  }
  if (typ == dbITermObj) {
    return ((db_id << DBIDTAG_WIDTH) | DBITERM_ID);
  }

Copy link
Contributor

Choose a reason for hiding this comment

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

Resolved in new version

@github-actions
Copy link
Contributor

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

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
@github-actions
Copy link
Contributor

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

Comment on lines 207 to 224
// Optimize for most common types to avoid switch overhead
if (typ == dbInstObj) {
return ((db_id << DBIDTAG_WIDTH) | DBINST_ID);
}
if (typ == dbNetObj) {
return ((db_id << DBIDTAG_WIDTH) | DBNET_ID);
}
if (typ == dbITermObj) {
return ((db_id << DBIDTAG_WIDTH) | DBITERM_ID);
}

switch (typ) {
case dbITermObj: {
return ((db_id << DBIDTAG_WIDTH) | DBITERM_ID);
} break;
case dbBTermObj: {
return ((db_id << DBIDTAG_WIDTH) | DBBTERM_ID);
} break;
case dbInstObj: {
return ((db_id << DBIDTAG_WIDTH) | DBINST_ID);
} break;
case dbNetObj: {
return ((db_id << DBIDTAG_WIDTH) | DBNET_ID);
} break;
case dbModITermObj: {
return ((db_id << DBIDTAG_WIDTH) | DBMODITERM_ID);
} break;
Copy link
Collaborator

@QuantamHD QuantamHD Feb 25, 2026

Choose a reason for hiding this comment

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

Since we're using c++20 you might want to give [[likely]]/[[unlikely]] a try to see if we can preserve the case switch statement to get the compiler errors in case we add a new enum.

https://en.cppreference.com/w/cpp/language/attributes/likely

 switch (typ) {
   [[likely]] case dbITermObj: {
      return ((db_id << DBIDTAG_WIDTH) | DBITERM_ID);
    } break;
    [[unlikely]]case dbBTermObj: {
      return ((db_id << DBIDTAG_WIDTH) | DBBTERM_ID);
    } break;
    case dbInstObj: {
      return ((db_id << DBIDTAG_WIDTH) | DBINST_ID);
    } break;
    [[likely]]case dbNetObj: {
      return ((db_id << DBIDTAG_WIDTH) | DBNET_ID);
    } break;
    case dbModITermObj: {
      return ((db_id << DBIDTAG_WIDTH) | DBMODITERM_ID);
    } break;

dsengupta0628 and others added 5 commits March 2, 2026 14:50
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
…ROAD into debug_or_runtime_fix

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
This reverts commit 3db5ed3 for getMTerm speedup as we have better option now.
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
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.

4 participants