odb: impl 3dblox checker checkLogicalConnectivity#9585
odb: impl 3dblox checker checkLogicalConnectivity#9585ahmed532 wants to merge 4 commits intoThe-OpenROAD-Project:masterfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a logical connectivity checker in 3dblox and enhances the creation of nets from Verilog files. The implementation is comprehensive and includes a good set of tests for the new functionality. My review includes suggestions to improve path handling robustness by avoiding exceptions and adhering to repository guidelines regarding helper function definitions, optimize performance in an error-reporting path, and adopt modern C++ practices in the test code.
src/odb/src/3dblox/3dblox.cpp
Outdated
| std::string full_path | ||
| = std::filesystem::absolute(chiplet.external.verilog_file).string(); |
There was a problem hiding this comment.
The path handling here using std::filesystem::absolute can throw an exception on error. For more robust path resolution and for consistency with the new code in checker.cpp, consider using std::filesystem::weakly_canonical with an error_code to prevent exceptions and handle paths more gracefully. Note that helper logic should generally be defined as a free function in a namespace rather than as a local lambda within a function, as per repository guidelines. While a full free function might be overkill for this specific inline usage, avoid the lambda for simpler direct integration.
std::error_code ec;
auto path = std::filesystem::weakly_canonical(
chiplet.external.verilog_file, ec);
if (ec) {
path = std::filesystem::absolute(chiplet.external.verilog_file, ec);
}
std::string full_path = path.string();References
- Helper logic should be defined as a free function in a namespace rather than as a local lambda within a function.
src/odb/src/3dblox/checker.cpp
Outdated
| std::vector<std::string> available_nets; | ||
| available_nets.insert( | ||
| available_nets.end(), verilog_nets.begin(), verilog_nets.end()); | ||
| std::ranges::sort(available_nets); | ||
| if (available_nets.size() > 10) { | ||
| available_nets.resize(10); | ||
| available_nets.emplace_back("..."); | ||
| } |
There was a problem hiding this comment.
The available_nets vector is being constructed, sorted, and truncated inside the loop for each bump with a missing net. Since the set of Verilog nets is the same for all bumps within a single master chip, this work is redundant and can be inefficient if there are many violations.
To improve performance, this list should be prepared once per master chip, before iterating through the regions and bumps. You can then use the pre-computed list in your fmt::format call on line 455.
References
- When analyzing code within a loop, consider the entire loop structure. Operations at the beginning of the loop (e.g.,
journalBegin) can affect the logic within the loop body, potentially making similar calls inside the loop redundant.
|
|
||
| void TearDown() override { delete blox_; } | ||
|
|
||
| ThreeDBlox* blox_; |
There was a problem hiding this comment.
To follow modern C++ practices and improve safety, consider using std::unique_ptr for managing the blox_ object. This will handle memory deallocation automatically, removing the need for a manual delete in TearDown.
You would also need to update SetUp to use std::make_unique and remove the TearDown override completely:
// In SetUp()
blox_ = std::make_unique<ThreeDBlox>(&logger_, db_.get(), sta_.get());
// Remove TearDown()| ThreeDBlox* blox_; | |
| std::unique_ptr<ThreeDBlox> blox_; |
|
clang-tidy review says "All clean, LGTM! 👍" |
1 similar comment
|
clang-tidy review says "All clean, LGTM! 👍" |
src/odb/include/odb/3dblox.h
Outdated
| std::unordered_set<odb::dbTech*> written_techs_; | ||
| std::unordered_set<odb::dbLib*> written_libs_; | ||
| std::unordered_set<std::string> read_files_; | ||
| std::unordered_set<std::string> read_verilog_files_; |
There was a problem hiding this comment.
I don't think you should keep track of the read verilog files. It doesn't make any sense that 2 3dbx files reference the same verilog file, unlike lef and lib which can be referenced/shared by different chiplets.
src/odb/src/3dblox/3dblox.cpp
Outdated
| } | ||
| if (sta_ != nullptr) { | ||
| std::error_code ec; | ||
| auto path = std::filesystem::weakly_canonical( |
src/odb/src/3dblox/3dblox.cpp
Outdated
|
|
||
| if (cell) { |
There was a problem hiding this comment.
| if (cell) { | |
| else { |
src/odb/src/3dblox/3dblox.cpp
Outdated
| for (auto* net : chip->getChipNets()) { | ||
| existing_nets.insert(net->getName()); | ||
| } |
There was a problem hiding this comment.
How would it happen that any dbChipNet exist before reading the verilog?
src/odb/src/3dblox/3dblox.cpp
Outdated
| existing_nets.insert(net->getName()); | ||
| } | ||
| std::unique_ptr<sta::CellPortBitIterator> port_iter( | ||
| network->portBitIterator(cell)); |
There was a problem hiding this comment.
You should use netIterator not portBitIterator. dbChipNet should essentially reference the nets while the ports should reference the bumps. look at OpenRoad::linkDesign for reference
src/odb/src/3dblox/checker.cpp
Outdated
| "Reading Verilog file {} for design {}", | ||
| path.filename().string(), | ||
| master->getName()); | ||
| if (!sta->readVerilog(file.c_str())) { |
There was a problem hiding this comment.
why are you reading the verilog at the checker?
The checker should only check for correctness while the parser at 3dblox should read the verilog and populate the data.
Signed-off-by: Ahmed R. Mohamed <ahmed@precisioninno.com>
Performance imporvments and formatting Signed-off-by: Ahmed R. Mohamed <ahmed@precisioninno.com>
use NetIterator instead of PortBitIterator. Remove redundent code. Signed-off-by: Ahmed R. Mohamed <ahmed@precisioninno.com>
f7b06cb to
fd22b2e
Compare
|
clang-tidy review says "All clean, LGTM! 👍" |
Remvoe STA dependency from checker. Signed-off-by: Ahmed R. Mohamed <ahmed@precisioninno.com>
|
clang-tidy review says "All clean, LGTM! 👍" |
Now reading missing nets from verilog in 3dblox in
void ThreeDBlox::createChiplet(const ChipletDef& chiplet)