Skip to content

Commit 9e4df73

Browse files
authored
Merge pull request #8774 from rafaelmoresco/dbvwriter
odb: add 3dbvWriter
2 parents 08bcc80 + 8097057 commit 9e4df73

File tree

16 files changed

+588
-2
lines changed

16 files changed

+588
-2
lines changed

include/ord/OpenRoad.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ class OpenRoad
224224

225225
void read3Dbv(const std::string& filename);
226226
void read3Dbx(const std::string& filename);
227+
void write3Dbv(const std::string& filename);
227228
void read3DBloxBMap(const std::string& filename);
228229

229230
void readDb(std::istream& stream);

src/OpenRoad.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,11 @@ void OpenRoad::read3DBloxBMap(const std::string& filename)
502502
odb::ThreeDBlox parser(logger_, db_);
503503
parser.readBMap(filename);
504504
}
505-
505+
void OpenRoad::write3Dbv(const std::string& filename)
506+
{
507+
odb::ThreeDBlox writer(logger_, db_, sta_);
508+
writer.writeDbv(filename, db_->getChip());
509+
}
506510
void OpenRoad::readDb(const char* filename, bool hierarchy)
507511
{
508512
try {

src/OpenRoad.i

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,13 @@ read_3dblox_bmap_cmd(const char *filename)
376376
ord->read3DBloxBMap(filename);
377377
}
378378

379+
void
380+
write_3dbv_cmd(const char *filename)
381+
{
382+
OpenRoad *ord = getOpenRoad();
383+
ord->write3Dbv(filename);
384+
}
385+
379386
void
380387
read_db_cmd(const char *filename, bool hierarchy)
381388
{

src/OpenRoad.tcl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ proc read_3dbv { args } {
182182
ord::read_3dbv_cmd $filename
183183
}
184184

185+
sta::define_cmd_args "write_3dbv" {filename}
186+
187+
proc write_3dbv { args } {
188+
sta::parse_key_args "write_3dbv" args keys {} flags {}
189+
sta::check_argc_eq1 "write_3dbv" $args
190+
set filename [file nativename [lindex $args 0]]
191+
ord::write_3dbv_cmd $filename
192+
}
193+
185194
sta::define_cmd_args "read_3dbx" {filename}
186195

187196
proc read_3dbx { args } {

src/odb/include/odb/3dblox.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55

66
#include <string>
7+
#include <unordered_set>
78
#include <vector>
89

910
namespace utl {
@@ -26,6 +27,8 @@ class BumpMapEntry;
2627
class dbChipRegion;
2728
class dbBlock;
2829
class dbInst;
30+
class dbTech;
31+
class dbLib;
2932

3033
class ThreeDBlox
3134
{
@@ -36,6 +39,8 @@ class ThreeDBlox
3639
void readDbx(const std::string& dbx_file);
3740
void readBMap(const std::string& bmap_file);
3841
void check();
42+
void writeDbv(const std::string& dbv_file, odb::dbChip* chip);
43+
void writeDbx(const std::string& dbx_file, odb::dbChip* chip);
3944

4045
private:
4146
void createChiplet(const ChipletDef& chiplet);
@@ -53,5 +58,7 @@ class ThreeDBlox
5358
utl::Logger* logger_ = nullptr;
5459
odb::dbDatabase* db_ = nullptr;
5560
sta::Sta* sta_ = nullptr;
61+
std::unordered_set<odb::dbTech*> written_techs_;
62+
std::unordered_set<odb::dbLib*> written_libs_;
5663
};
5764
} // namespace odb

src/odb/src/3dblox/3dblox.cpp

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,26 @@
99
#include <set>
1010
#include <sstream>
1111
#include <string>
12+
#include <unordered_set>
1213
#include <vector>
1314

1415
#include "bmapParser.h"
1516
#include "checker.h"
1617
#include "dbvParser.h"
18+
#include "dbvWriter.h"
1719
#include "dbxParser.h"
1820
#include "objects.h"
1921
#include "odb/db.h"
2022
#include "odb/dbTransform.h"
2123
#include "odb/dbTypes.h"
2224
#include "odb/defin.h"
25+
#include "odb/defout.h"
2326
#include "odb/geom.h"
2427
#include "odb/lefin.h"
28+
#include "odb/lefout.h"
2529
#include "sta/Sta.hh"
2630
#include "utl/Logger.h"
27-
31+
#include "utl/ScopedTemporaryFile.h"
2832
namespace odb {
2933

3034
static std::map<std::string, std::string> dup_orient_map
@@ -93,6 +97,93 @@ void ThreeDBlox::check()
9397
checker.check(db_->getChip());
9498
}
9599

100+
namespace {
101+
std::unordered_set<odb::dbTech*> getUsedTechs(odb::dbChip* chip)
102+
{
103+
std::unordered_set<odb::dbTech*> techs;
104+
for (auto inst : chip->getChipInsts()) {
105+
if (inst->getMasterChip()->getTech() != nullptr) {
106+
techs.insert(inst->getMasterChip()->getTech());
107+
}
108+
}
109+
return techs;
110+
}
111+
std::unordered_set<odb::dbLib*> getUsedLibs(odb::dbChip* chip)
112+
{
113+
std::unordered_set<odb::dbLib*> libs;
114+
for (auto inst : chip->getChipInsts()) {
115+
auto master_chip = inst->getMasterChip();
116+
if (master_chip->getBlock() != nullptr) {
117+
for (auto inst : master_chip->getBlock()->getInsts()) {
118+
libs.insert(inst->getMaster()->getLib());
119+
}
120+
}
121+
}
122+
return libs;
123+
}
124+
std::string getResultsDirectoryPath(const std::string& file_path)
125+
{
126+
std::string current_dir_path;
127+
auto path = std::filesystem::path(file_path);
128+
if (path.has_parent_path()) {
129+
current_dir_path = path.parent_path().string() + "/";
130+
}
131+
return current_dir_path;
132+
}
133+
} // namespace
134+
void ThreeDBlox::writeDbv(const std::string& dbv_file, odb::dbChip* chip)
135+
{
136+
if (chip == nullptr) {
137+
return;
138+
}
139+
///////////Results Directory Path ///////////
140+
std::string current_dir_path = getResultsDirectoryPath(dbv_file);
141+
////////////////////////////////////////////
142+
143+
for (auto inst : chip->getChipInsts()) {
144+
auto master_chip = inst->getMasterChip();
145+
if (master_chip->getChipType() == odb::dbChip::ChipType::HIER) {
146+
writeDbx(current_dir_path + master_chip->getName() + ".3dbx",
147+
master_chip);
148+
}
149+
}
150+
// write used techs
151+
for (auto tech : getUsedTechs(chip)) {
152+
if (written_techs_.find(tech) != written_techs_.end()) {
153+
continue;
154+
}
155+
written_techs_.insert(tech);
156+
std::string tech_file_path = current_dir_path + tech->getName() + ".lef";
157+
utl::OutStreamHandler stream_handler(tech_file_path.c_str());
158+
odb::lefout lef_writer(logger_, stream_handler.getStream());
159+
lef_writer.writeTech(tech);
160+
}
161+
// write used libs
162+
for (auto lib : getUsedLibs(chip)) {
163+
if (written_libs_.find(lib) != written_libs_.end()) {
164+
continue;
165+
}
166+
written_libs_.insert(lib);
167+
std::string lib_file_path = current_dir_path + lib->getName() + "_lib.lef";
168+
utl::OutStreamHandler stream_handler(lib_file_path.c_str());
169+
odb::lefout lef_writer(logger_, stream_handler.getStream());
170+
lef_writer.writeLib(lib);
171+
}
172+
173+
DbvWriter writer(logger_, db_);
174+
writer.writeChiplet(dbv_file, chip);
175+
}
176+
177+
void ThreeDBlox::writeDbx(const std::string& dbx_file, odb::dbChip* chip)
178+
{
179+
if (chip == nullptr) {
180+
return;
181+
}
182+
// TODO: implement
183+
std::string current_dir_path = getResultsDirectoryPath(dbx_file);
184+
writeDbv(current_dir_path + chip->getName() + ".3dbv", chip);
185+
}
186+
96187
void ThreeDBlox::calculateSize(dbChip* chip)
97188
{
98189
Rect box;
@@ -135,11 +226,13 @@ dbChip::ChipType getChipType(const std::string& type, utl::Logger* logger)
135226
logger->error(
136227
utl::ODB, 527, "3DBV Parser Error: Invalid chip type: {}", type);
137228
}
229+
138230
std::string getFileName(const std::string& tech_file_path)
139231
{
140232
std::filesystem::path tech_file_path_fs(tech_file_path);
141233
return tech_file_path_fs.stem().string();
142234
}
235+
143236
void ThreeDBlox::createChiplet(const ChipletDef& chiplet)
144237
{
145238
dbTech* tech = nullptr;
@@ -232,6 +325,7 @@ void ThreeDBlox::createChiplet(const ChipletDef& chiplet)
232325
createRegion(region, chip);
233326
}
234327
}
328+
235329
dbChipRegion::Side getChipRegionSide(const std::string& side,
236330
utl::Logger* logger)
237331
{
@@ -341,6 +435,7 @@ dbChip* ThreeDBlox::createDesignTopChiplet(const DesignDef& design)
341435
db_->setTopChip(chip);
342436
return chip;
343437
}
438+
344439
void ThreeDBlox::createChipInst(const ChipletInst& chip_inst)
345440
{
346441
auto chip = db_->findChip(chip_inst.reference.c_str());

src/odb/src/3dblox/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ add_library(3dblox
88
bmapParser.cpp
99
dbvParser.cpp
1010
dbxParser.cpp
11+
baseWriter.cpp
12+
dbvWriter.cpp
1113
3dblox.cpp
1214
checker.cpp
1315
)

src/odb/src/3dblox/baseWriter.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
// Copyright (c) 2019-2025, The OpenROAD Authors
3+
4+
#include "baseWriter.h"
5+
6+
#include <yaml-cpp/yaml.h>
7+
8+
#include <cstddef>
9+
#include <fstream>
10+
#include <string>
11+
12+
#include "odb/db.h"
13+
#include "utl/Logger.h"
14+
namespace odb {
15+
16+
BaseWriter::BaseWriter(utl::Logger* logger, odb::dbDatabase* db)
17+
: logger_(logger), dbu_per_micron_(db->getDbuPerMicron())
18+
{
19+
}
20+
21+
void BaseWriter::writeHeader(YAML::Node& header_node)
22+
{
23+
header_node["version"] = "3";
24+
header_node["unit"] = "micron";
25+
header_node["precision"] = dbu_per_micron_;
26+
}
27+
28+
void BaseWriter::writeYamlToFile(const std::string& filename,
29+
const YAML::Node& root)
30+
{
31+
std::ofstream out(filename);
32+
if (!out) {
33+
if (logger_ != nullptr) {
34+
logError("cannot open " + filename);
35+
}
36+
return;
37+
}
38+
39+
out << root;
40+
}
41+
42+
void BaseWriter::writeCoordinate(YAML::Node& coord_node,
43+
const odb::Point& point)
44+
{
45+
coord_node.SetStyle(YAML::EmitterStyle::Flow);
46+
coord_node.push_back(dbuToMicron(point.x()));
47+
coord_node.push_back(dbuToMicron(point.y()));
48+
}
49+
50+
void BaseWriter::writeCoordinates(YAML::Node& coords_node,
51+
const odb::Rect& rect)
52+
{
53+
YAML::Node c0, c1, c2, c3;
54+
writeCoordinate(c0, rect.ll());
55+
writeCoordinate(c1, rect.lr());
56+
writeCoordinate(c2, rect.ur());
57+
writeCoordinate(c3, rect.ul());
58+
coords_node.push_back(c0);
59+
coords_node.push_back(c1);
60+
coords_node.push_back(c2);
61+
coords_node.push_back(c3);
62+
}
63+
64+
void BaseWriter::logError(const std::string& message)
65+
{
66+
if (logger_ != nullptr) {
67+
logger_->error(utl::ODB, 540, "Writer Error: {}", message);
68+
}
69+
}
70+
71+
std::string BaseWriter::trim(const std::string& str)
72+
{
73+
std::size_t first = str.find_first_not_of(' ');
74+
if (first == std::string::npos) {
75+
return "";
76+
}
77+
std::size_t last = str.find_last_not_of(' ');
78+
return str.substr(first, (last - first + 1));
79+
}
80+
81+
template <typename IntType>
82+
std::string BaseWriter::dbuToMicron(IntType dbu) const
83+
{
84+
return fmt::format("{:.11g}", dbu / static_cast<double>(dbu_per_micron_));
85+
}
86+
87+
template std::string BaseWriter::dbuToMicron<int>(int dbu) const;
88+
} // namespace odb

src/odb/src/3dblox/baseWriter.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
// Copyright (c) 2019-2025, The OpenROAD Authors
3+
4+
#pragma once
5+
6+
#include <string>
7+
8+
namespace utl {
9+
class Logger;
10+
}
11+
12+
namespace YAML {
13+
class Node;
14+
}
15+
namespace odb {
16+
class dbDatabase;
17+
class Rect;
18+
class Point;
19+
20+
class BaseWriter
21+
{
22+
public:
23+
BaseWriter(utl::Logger* logger, odb::dbDatabase* db);
24+
virtual ~BaseWriter() = default;
25+
26+
protected:
27+
// Common YAML content writing
28+
void writeHeader(YAML::Node& header_node);
29+
void writeCoordinates(YAML::Node& coords_node, const odb::Rect& rect);
30+
void writeCoordinate(YAML::Node& coord_node, const odb::Point& point);
31+
void logError(const std::string& message);
32+
std::string trim(const std::string& str);
33+
void writeYamlToFile(const std::string& filename, const YAML::Node& root);
34+
template <typename IntType>
35+
std::string dbuToMicron(IntType dbu) const;
36+
37+
// Member variables
38+
utl::Logger* logger_ = nullptr;
39+
std::string current_dir_path_;
40+
unsigned int dbu_per_micron_ = 0;
41+
};
42+
43+
} // namespace odb

0 commit comments

Comments
 (0)