-
Notifications
You must be signed in to change notification settings - Fork 844
odb: impl 3dblox verilog writer #9813
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -198,6 +198,15 @@ proc write_3dbx { args } { | |
| ord::write_3dbx_cmd $filename | ||
| } | ||
|
|
||
| sta::define_cmd_args "write_3dblox_verilog" {filename} | ||
|
|
||
| proc write_3dblox_verilog { args } { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @maliberty @precisionmoon Do you think we need to expose this command? |
||
| sta::parse_key_args "write_3dblox_verilog" args keys {} flags {} | ||
| sta::check_argc_eq1 "write_3dblox_verilog" $args | ||
| set filename [file nativename [lindex $args 0]] | ||
| ord::write_3dblox_verilog_cmd $filename | ||
| } | ||
|
|
||
| sta::define_cmd_args "read_3dbx" {filename} | ||
|
|
||
| proc read_3dbx { args } { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,7 @@ | |
| #include "sta/VerilogReader.hh" | ||
| #include "utl/Logger.h" | ||
| #include "utl/ScopedTemporaryFile.h" | ||
| #include "verilogWriter.h" | ||
| namespace odb { | ||
|
|
||
| static std::map<std::string, std::string> dup_orient_map | ||
|
|
@@ -301,10 +302,23 @@ void ThreeDBlox::writeDbx(const std::string& dbx_file, odb::dbChip* chip) | |
|
|
||
| writeDbv(current_dir_path + chip->getName() + ".3dbv", chip); | ||
|
|
||
| // Write the Verilog connectivity file for this HIER chiplet. | ||
| writeVerilog(current_dir_path + chip->getName() + ".v", chip); | ||
|
Comment on lines
+305
to
+306
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
|
||
| DbxWriter writer(logger_, db_); | ||
| writer.writeChiplet(dbx_file, chip); | ||
| } | ||
|
|
||
| void ThreeDBlox::writeVerilog(const std::string& verilog_file, | ||
| odb::dbChip* chip) | ||
| { | ||
| if (chip == nullptr) { | ||
| return; | ||
| } | ||
| VerilogWriter writer(logger_); | ||
| writer.writeChiplet(verilog_file, chip); | ||
| } | ||
|
|
||
| void ThreeDBlox::writeBMap(const std::string& bmap_file, | ||
| odb::dbChipRegion* region) | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| // SPDX-License-Identifier: BSD-3-Clause | ||
| // Copyright (c) 2019-2025, The OpenROAD Authors | ||
|
|
||
| #include "verilogWriter.h" | ||
|
|
||
| #include <algorithm> | ||
| #include <cstddef> | ||
| #include <cstdint> | ||
| #include <fstream> | ||
| #include <map> | ||
| #include <string> | ||
| #include <utility> | ||
| #include <vector> | ||
|
|
||
| #include "odb/db.h" | ||
| #include "utl/Logger.h" | ||
|
|
||
| namespace odb { | ||
|
|
||
| VerilogWriter::VerilogWriter(utl::Logger* logger) : logger_(logger) | ||
| { | ||
| } | ||
|
|
||
| void VerilogWriter::writeChiplet(const std::string& filename, odb::dbChip* chip) | ||
| { | ||
| std::ofstream verilog_file(filename); | ||
| if (!verilog_file.is_open()) { | ||
| logger_->error( | ||
| utl::ODB, 563, "Unable to open Verilog file for writing: {}", filename); | ||
osamahammad21 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return; | ||
| } | ||
|
|
||
| // chip_inst -> list of (port_name, net_name) | ||
| std::map<dbChipInst*, std::vector<std::pair<std::string, std::string>>> | ||
| inst_connections; | ||
|
|
||
| for (dbChipNet* net : chip->getChipNets()) { | ||
| const std::string net_name = net->getName(); | ||
| const uint32_t num_bumps = net->getNumBumpInsts(); | ||
| for (uint32_t i = 0; i < num_bumps; i++) { | ||
| std::vector<dbChipInst*> path; | ||
| dbChipBumpInst* bump_inst = net->getBumpInst(i, path); | ||
| if (bump_inst == nullptr || path.size() != 1) { | ||
| continue; | ||
| } | ||
| // Only handle direct children (path length 1) — "single bump | ||
| // connections". | ||
| dbChipInst* chip_inst = path[0]; | ||
| dbChipBump* bump = bump_inst->getChipBump(); | ||
| if (bump == nullptr) { | ||
| continue; | ||
| } | ||
| dbBTerm* bterm = bump->getBTerm(); | ||
| if (bterm == nullptr) { | ||
| continue; | ||
| } | ||
| inst_connections[chip_inst].emplace_back(bterm->getName(), net_name); | ||
| } | ||
| } | ||
|
|
||
| // Sort each instance's port connections alphabetically by port name. | ||
| for (std::pair<dbChipInst* const, | ||
| std::vector<std::pair<std::string, std::string>>>& entry : | ||
| inst_connections) { | ||
| std::ranges::sort(entry.second); | ||
| } | ||
|
|
||
| // Write module header. | ||
| fmt::print(verilog_file, "module {} ();\n", chip->getName()); | ||
|
|
||
| // Collect and sort net names alphabetically for deterministic wire order. | ||
| std::vector<std::string> net_names; | ||
| for (dbChipNet* net : chip->getChipNets()) { | ||
| net_names.push_back(net->getName()); | ||
| } | ||
| std::ranges::sort(net_names); | ||
|
|
||
| // Write wire declarations in sorted order. | ||
| for (const std::string& name : net_names) { | ||
| fmt::print(verilog_file, " wire {};\n", name); | ||
| } | ||
|
|
||
| // Collect and sort instances alphabetically by instance name. | ||
| std::vector<dbChipInst*> chip_insts; | ||
| for (dbChipInst* chip_inst : chip->getChipInsts()) { | ||
| chip_insts.push_back(chip_inst); | ||
| } | ||
| std::ranges::sort(chip_insts, [](dbChipInst* a, dbChipInst* b) { | ||
| return a->getName() < b->getName(); | ||
| }); | ||
|
|
||
| // Write instance declarations in sorted order. | ||
| for (dbChipInst* chip_inst : chip_insts) { | ||
| fmt::print(verilog_file, | ||
| " {} {} (\n", | ||
| chip_inst->getMasterChip()->getName(), | ||
| chip_inst->getName()); | ||
| const std::map< | ||
| dbChipInst*, | ||
| std::vector<std::pair<std::string, std::string>>>::const_iterator it | ||
| = inst_connections.find(chip_inst); | ||
|
Comment on lines
+98
to
+101
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| if (it != inst_connections.end()) { | ||
| const std::vector<std::pair<std::string, std::string>>& conns | ||
| = it->second; | ||
| for (size_t j = 0; j < conns.size(); j++) { | ||
| const bool is_last = (j + 1 == conns.size()); | ||
| fmt::print(verilog_file, | ||
| " .{}({}){}\n", | ||
| conns[j].first, | ||
| conns[j].second, | ||
| is_last ? "" : ","); | ||
|
Comment on lines
+105
to
+111
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
| } | ||
| fmt::print(verilog_file, " );\n"); | ||
| } | ||
|
|
||
| fmt::print(verilog_file, "endmodule\n"); | ||
| verilog_file.close(); | ||
| } | ||
|
|
||
| } // namespace odb | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // SPDX-License-Identifier: BSD-3-Clause | ||
| // Copyright (c) 2019-2025, The OpenROAD Authors | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <string> | ||
|
|
||
| namespace utl { | ||
| class Logger; | ||
| } | ||
| namespace odb { | ||
| class dbChip; | ||
|
|
||
| class VerilogWriter | ||
| { | ||
| public: | ||
| VerilogWriter(utl::Logger* logger); | ||
| void writeChiplet(const std::string& filename, odb::dbChip* chip); | ||
|
|
||
| private: | ||
| utl::Logger* logger_ = nullptr; | ||
| }; | ||
|
|
||
| } // namespace odb |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -257,6 +257,7 @@ cc_test( | |
| name = "Test3DBloxParser", | ||
| srcs = [ | ||
| "Test3DBloxParser.cpp", | ||
| "Test3DBloxVerilogWriter.cpp", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding |
||
| ], | ||
| data = [ | ||
| "//src/odb/test:regression_resources", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,7 +35,7 @@ add_executable(TestNetTrack TestNetTrack.cpp) | |
| add_executable(TestMaster TestMaster.cpp) | ||
| add_executable(TestGDSIn TestGDSIn.cpp) | ||
| add_executable(TestChips TestChips.cpp) | ||
| add_executable(Test3DBloxParser Test3DBloxParser.cpp) | ||
| add_executable(Test3DBloxParser Test3DBloxParser.cpp Test3DBloxVerilogWriter.cpp) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please address. It needs a separate executable IMO. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. |
||
| add_executable(Test3DBloxChecker Test3DBloxChecker.cpp Test3DBloxCheckerLogicalConn.cpp Test3DBloxCheckerBumps.cpp) | ||
| add_executable(TestSwapMaster TestSwapMaster.cpp) | ||
| add_executable(TestSwapMasterUnusedPort TestSwapMasterUnusedPort.cpp) | ||
|
|
||
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
<iostream>header is typically used forstd::cin,std::cout,std::cerr, etc. If these are only used in the corresponding.ccimplementation file, it's generally better to include<iostream>there instead of in the header file. This helps to minimize compilation dependencies for files that includeOpenRoad.hh.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.
@ahmed532 iostream not needed. mistake?
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 weird! I do not remember adding it myself. I thought it was in the file from the beginning. I'll remove it.