Skip to content

Commit ff6434e

Browse files
authored
Merge pull request #8715 from osamahammad21/3dblox-bmap-parser
ODB: Parser bump map
2 parents c5f09f2 + 52eae8a commit ff6434e

File tree

15 files changed

+303
-2
lines changed

15 files changed

+303
-2
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class Connection;
2222
class DesignDef;
2323
class dbChipRegionInst;
2424
class dbChipInst;
25+
class BumpMapEntry;
26+
class dbChipRegion;
2527

2628
class ThreeDBlox
2729
{
@@ -37,6 +39,7 @@ class ThreeDBlox
3739
dbChip* createDesignTopChiplet(const DesignDef& design);
3840
void createChipInst(const ChipletInst& chip_inst);
3941
void createConnection(const Connection& connection);
42+
void createBump(const BumpMapEntry& entry, dbChipRegion* chip_region);
4043
dbChipRegionInst* resolvePath(const std::string& path,
4144
std::vector<dbChipInst*>& path_insts);
4245
void readHeaderIncludes(const std::vector<std::string>& includes);

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

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <string>
1111
#include <vector>
1212

13+
#include "bmapParser.h"
1314
#include "dbvParser.h"
1415
#include "dbxParser.h"
1516
#include "objects.h"
@@ -206,6 +207,13 @@ void ThreeDBlox::createChiplet(const ChipletDef& chiplet)
206207

207208
chip->setOffset(Point(chiplet.offset.x * db_->getDbuPerMicron(),
208209
chiplet.offset.y * db_->getDbuPerMicron()));
210+
if (chip->getChipType() != dbChip::ChipType::HIER
211+
&& chip->getBlock() == nullptr) {
212+
// blackbox stage, create block
213+
auto block = odb::dbBlock::create(chip, chiplet.name.c_str());
214+
block->setDieArea(Rect(0, 0, chip->getWidth(), chip->getHeight()));
215+
block->setCoreArea(Rect(0, 0, chip->getWidth(), chip->getHeight()));
216+
}
209217
for (const auto& [_, region] : chiplet.regions) {
210218
createRegion(region, chip);
211219
}
@@ -244,7 +252,72 @@ void ThreeDBlox::createRegion(const ChipletRegion& region, dbChip* chip)
244252
box);
245253
}
246254
chip_region->setBox(box);
255+
// Read bump map file
256+
if (!region.bmap.empty()) {
257+
BmapParser parser(logger_);
258+
BumpMapData data = parser.parseFile(region.bmap);
259+
for (const auto& entry : data.entries) {
260+
createBump(entry, chip_region);
261+
}
262+
}
263+
}
264+
265+
void ThreeDBlox::createBump(const BumpMapEntry& entry,
266+
dbChipRegion* chip_region)
267+
{
268+
auto chip = chip_region->getChip();
269+
auto block = chip->getBlock();
270+
auto inst = block->findInst(entry.bump_inst_name.c_str());
271+
if (inst == nullptr) {
272+
// create inst
273+
auto master = db_->findMaster(entry.bump_cell_type.c_str());
274+
if (master == nullptr) {
275+
logger_->error(utl::ODB,
276+
531,
277+
"3DBV Parser Error: Bump cell type {} not found",
278+
entry.bump_cell_type);
279+
}
280+
if (master->getLib()->getTech() != chip->getTech()) {
281+
logger_->error(utl::ODB,
282+
532,
283+
"3DBV Parser Error: Bump cell type {} is not in the same "
284+
"tech as the chip region {}/{}",
285+
entry.bump_cell_type,
286+
chip->getName(),
287+
chip_region->getName());
288+
}
289+
inst = dbInst::create(block, master, entry.bump_inst_name.c_str());
290+
}
291+
auto bump = dbChipBump::create(chip_region, inst);
292+
inst->setOrigin(entry.x * db_->getDbuPerMicron(),
293+
entry.y * db_->getDbuPerMicron());
294+
inst->setPlacementStatus(dbPlacementStatus::FIRM);
295+
if (entry.net_name != "-") {
296+
auto net = block->findNet(entry.net_name.c_str());
297+
if (net == nullptr) {
298+
logger_->error(utl::ODB,
299+
534,
300+
"3DBV Parser Error: Bump net {} not found",
301+
entry.net_name);
302+
}
303+
bump->setNet(net);
304+
inst->getITerms().begin()->connect(net);
305+
}
306+
if (entry.port_name != "-") {
307+
auto bterm = block->findBTerm(entry.port_name.c_str());
308+
if (bterm == nullptr) {
309+
logger_->error(utl::ODB,
310+
533,
311+
"3DBV Parser Error: Bump port {} not found",
312+
entry.port_name);
313+
}
314+
bump->setBTerm(bterm);
315+
if (bump->getNet()) {
316+
bterm->connect(bump->getNet());
317+
}
318+
}
247319
}
320+
248321
dbChip* ThreeDBlox::createDesignTopChiplet(const DesignDef& design)
249322
{
250323
dbChip* chip

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ find_package(yaml-cpp REQUIRED)
55

66
add_library(3dblox
77
baseParser.cpp
8+
bmapParser.cpp
89
dbvParser.cpp
910
dbxParser.cpp
1011
3dblox.cpp

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

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
// Copyright (c) 2019-2025, The OpenROAD Authors
3+
4+
#include "bmapParser.h"
5+
6+
#include <exception>
7+
#include <fstream>
8+
#include <sstream>
9+
#include <string>
10+
#include <vector>
11+
12+
#include "objects.h"
13+
#include "utl/Logger.h"
14+
namespace odb {
15+
16+
BmapParser::BmapParser(utl::Logger* logger) : logger_(logger)
17+
{
18+
}
19+
20+
BumpMapData BmapParser::parseFile(const std::string& filename)
21+
{
22+
current_file_path_ = filename;
23+
std::ifstream file(filename);
24+
if (!file.is_open()) {
25+
logger_->error(
26+
utl::ODB, 535, "Bump Map Parser Error: Cannot open file: {}", filename);
27+
}
28+
29+
std::stringstream buffer;
30+
buffer << file.rdbuf();
31+
std::string content = buffer.str();
32+
file.close();
33+
34+
BumpMapData data;
35+
parseBumpMapContent(data, content);
36+
37+
return data;
38+
}
39+
40+
void BmapParser::parseBumpMapContent(BumpMapData& data,
41+
const std::string& content)
42+
{
43+
std::istringstream stream(content);
44+
std::string line;
45+
int line_number = 0;
46+
47+
while (std::getline(stream, line)) {
48+
line_number++;
49+
50+
// Skip empty lines and comments (lines starting with #)
51+
if (line.empty() || line[0] == '#') {
52+
continue;
53+
}
54+
55+
parseBumpMapLine(data, line, line_number);
56+
}
57+
}
58+
59+
void BmapParser::parseBumpMapLine(BumpMapData& data,
60+
const std::string& line,
61+
int line_number)
62+
{
63+
std::vector<std::string> tokens = splitLine(line);
64+
65+
// Check if we have exactly 6 columns
66+
if (tokens.size() != 6) {
67+
logger_->error(
68+
utl::ODB,
69+
536,
70+
"Bump Map Parser Error: file {} Line {} has {} columns, expected 6. "
71+
"Format: bumpInstName bumpCellType x y portName netName",
72+
current_file_path_,
73+
line_number,
74+
tokens.size());
75+
}
76+
77+
try {
78+
// Parse coordinates as doubles
79+
const double x = std::stod(tokens[2]);
80+
const double y = std::stod(tokens[3]);
81+
82+
// Create bump map entry
83+
BumpMapEntry entry(tokens[0], tokens[1], x, y, tokens[4], tokens[5]);
84+
data.entries.push_back(entry);
85+
86+
} catch (const std::exception& e) {
87+
logger_->error(utl::ODB,
88+
537,
89+
"Bump Map Parser Error: file {} Line {} - Invalid "
90+
"coordinate format: {}",
91+
current_file_path_,
92+
line_number,
93+
std::string(e.what()));
94+
}
95+
}
96+
97+
std::vector<std::string> BmapParser::splitLine(const std::string& line)
98+
{
99+
std::vector<std::string> tokens;
100+
std::istringstream stream(line);
101+
std::string token;
102+
103+
while (stream >> token) {
104+
tokens.push_back(token);
105+
}
106+
107+
return tokens;
108+
}
109+
110+
} // namespace odb

src/odb/src/3dblox/bmapParser.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
// Copyright (c) 2019-2025, The OpenROAD Authors
3+
4+
#pragma once
5+
6+
#include <string>
7+
#include <vector>
8+
9+
namespace utl {
10+
class Logger;
11+
}
12+
namespace odb {
13+
class BumpMapData;
14+
class BumpMapEntry;
15+
16+
class BmapParser
17+
{
18+
public:
19+
BmapParser(utl::Logger* logger);
20+
21+
BumpMapData parseFile(const std::string& filename);
22+
23+
private:
24+
void parseBumpMapContent(BumpMapData& data, const std::string& content);
25+
void parseBumpMapLine(BumpMapData& data,
26+
const std::string& line,
27+
int line_number);
28+
std::vector<std::string> splitLine(const std::string& line);
29+
30+
utl::Logger* logger_;
31+
std::string current_file_path_;
32+
};
33+
34+
} // namespace odb

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,12 @@ void DbvParser::parseRegion(ChipletRegion& region,
207207
{
208208
if (region_node["bmap"]) {
209209
extractValue(region_node, "bmap", region.bmap);
210+
region.bmap = resolvePath(region.bmap);
210211
}
211212

212213
if (region_node["pmap"]) {
213214
extractValue(region_node, "pmap", region.pmap);
215+
region.pmap = resolvePath(region.pmap);
214216
}
215217

216218
if (region_node["side"]) {

src/odb/src/3dblox/objects.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,35 @@ struct DbxData
122122
std::map<std::string, Connection> connections;
123123
};
124124

125+
struct BumpMapEntry
126+
{
127+
std::string bump_inst_name;
128+
std::string bump_cell_type;
129+
double x{0.0};
130+
double y{0.0};
131+
std::string port_name;
132+
std::string net_name;
133+
134+
BumpMapEntry() = default;
135+
BumpMapEntry(const std::string& inst_name,
136+
const std::string& cell_type,
137+
double x_coord,
138+
double y_coord,
139+
const std::string& port,
140+
const std::string& net)
141+
: bump_inst_name(inst_name),
142+
bump_cell_type(cell_type),
143+
x(x_coord),
144+
y(y_coord),
145+
port_name(port),
146+
net_name(net)
147+
{
148+
}
149+
};
150+
151+
struct BumpMapData
152+
{
153+
std::vector<BumpMapEntry> entries;
154+
};
155+
125156
} // namespace odb

src/odb/src/db/dbChipInst.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,11 @@ dbChipInst* dbChipInst::create(dbChip* parent_chip,
254254
bumpinst->region_next_ = regioninst->chip_bump_insts_;
255255
regioninst->chip_bump_insts_ = bumpinst->getOID();
256256
}
257+
// reverse the chip_bump_insts_ list
258+
((dbChipRegionInst*) regioninst)->getChipBumpInsts().reverse();
257259
}
260+
// reverse the chip_region_insts_ list
261+
((dbChipInst*) chipinst)->getRegions().reverse();
258262
return (dbChipInst*) chipinst;
259263
}
260264

src/odb/test/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ filegroup(
251251
"Nangate45/Nangate45_stdcell.lef",
252252
"Nangate45/Nangate45_tech.lef",
253253
"Nangate45/Nangate45_typ.lib",
254+
"Nangate45/fake_bumps.lef",
254255
"Nangate45/fake_macros.lef",
255256
"Nangate45/fake_macros.lib",
256257
"Nangate45/fakeram45.cfg",
@@ -276,6 +277,7 @@ filegroup(
276277
"data/design58.def",
277278
"data/example.3dbv",
278279
"data/example.3dbx",
280+
"data/example.bmap",
279281
"data/floorplan_initialize.def",
280282
"data/floorplan_initialize.v",
281283
"data/floorplan_initialize2.def",

src/odb/test/cpp/Test3DBloxParser.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,24 @@ TEST_F(DbvFixture, test_3dbx)
111111
EXPECT_EQ(connection->getThickness(), 0.0);
112112
}
113113

114+
TEST_F(DbvFixture, test_bump_map_parser)
115+
{
116+
auto region = db_->findChip("SoC")->findChipRegion("r1");
117+
EXPECT_EQ(region->getChipBumps().size(), 2);
118+
auto bump = *region->getChipBumps().begin();
119+
EXPECT_EQ(bump->getInst()->getName(), "bump1");
120+
EXPECT_EQ(bump->getInst()->getMaster()->getName(), "BUMP");
121+
EXPECT_EQ(bump->getInst()->getOrigin().x(), 100.0 * db_->getDbuPerMicron());
122+
EXPECT_EQ(bump->getInst()->getOrigin().y(), 200.0 * db_->getDbuPerMicron());
123+
EXPECT_EQ(bump->getNet(), nullptr);
124+
EXPECT_EQ(bump->getBTerm(), nullptr);
125+
auto soc_inst = db_->getChip()->findChipInst("soc_inst");
126+
auto region_inst = soc_inst->findChipRegionInst("r1");
127+
EXPECT_EQ(region_inst->getChipBumpInsts().size(), 2);
128+
auto bump_inst = *region_inst->getChipBumpInsts().begin();
129+
EXPECT_EQ(bump_inst->getChipBump(), bump);
130+
EXPECT_EQ(bump_inst->getChipRegionInst(), region_inst);
131+
}
132+
114133
} // namespace
115134
} // namespace odb

0 commit comments

Comments
 (0)