Skip to content

Commit 795facf

Browse files
authored
Merge pull request #8845 from gadfort/bmap
odb: add read_3dblox_bmap command
2 parents 6a20c2a + caf2561 commit 795facf

File tree

11 files changed

+259
-0
lines changed

11 files changed

+259
-0
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 read3DBloxBMap(const std::string& filename);
227228

228229
void readDb(std::istream& stream);
229230
void readDb(const char* filename, bool hierarchy = false);

src/OpenRoad.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,12 @@ void OpenRoad::read3Dbx(const std::string& filename)
497497
parser.readDbx(filename);
498498
}
499499

500+
void OpenRoad::read3DBloxBMap(const std::string& filename)
501+
{
502+
odb::ThreeDBlox parser(logger_, db_);
503+
parser.readBMap(filename);
504+
}
505+
500506
void OpenRoad::readDb(const char* filename, bool hierarchy)
501507
{
502508
try {

src/OpenRoad.i

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,13 @@ read_3dbx_cmd(const char *filename)
369369
ord->read3Dbx(filename);
370370
}
371371

372+
void
373+
read_3dblox_bmap_cmd(const char *filename)
374+
{
375+
OpenRoad *ord = getOpenRoad();
376+
ord->read3DBloxBMap(filename);
377+
}
378+
372379
void
373380
read_db_cmd(const char *filename, bool hierarchy)
374381
{

src/OpenRoad.tcl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,21 @@ proc read_3dbx { args } {
197197
ord::read_3dbx_cmd $filename
198198
}
199199

200+
sta::define_cmd_args "read_3dblox_bmap" {filename}
201+
202+
proc read_3dblox_bmap { args } {
203+
sta::parse_key_args "read_3dblox_bmap" args keys {} flags {}
204+
sta::check_argc_eq1 "read_3dblox_bmap" $args
205+
set filename [file nativename [lindex $args 0]]
206+
if { ![file exists $filename] } {
207+
utl::error "ORD" 74 "$filename does not exist."
208+
}
209+
if { ![file readable $filename] } {
210+
utl::error "ORD" 75 "$filename is not readable."
211+
}
212+
ord::read_3dblox_bmap_cmd $filename
213+
}
214+
200215
sta::define_cmd_args "write_db" {filename}
201216

202217
sta::define_cmd_args "read_db" {[-hier] filename}

src/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,20 @@ report_logic_depth_histogram [-num_bins num_bins] [-exclude_buffers] [-exclude_i
335335
| `-exclude_buffers` | Exclude buffers when counting critical path length. |
336336
| `-exclude_inverters` | Exclude inverters when counting critical path length. |
337337

338+
#### 3D Blox
339+
340+
The `read_3dblox_bmap` command will read the bump map and place the bumps into the current design.
341+
342+
```tcl
343+
read_3dblox_bmap filename
344+
```
345+
346+
##### Options
347+
348+
| Switch Name | Description |
349+
| ----- | ----- |
350+
| `filename` | Path to the bump map. |
351+
338352
## TCL functions
339353

340354
Get the die and core areas as a list in microns: `llx lly urx ury`

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class dbChipRegionInst;
2424
class dbChipInst;
2525
class BumpMapEntry;
2626
class dbChipRegion;
27+
class dbBlock;
28+
class dbInst;
2729

2830
class ThreeDBlox
2931
{
@@ -32,6 +34,7 @@ class ThreeDBlox
3234
~ThreeDBlox() = default;
3335
void readDbv(const std::string& dbv_file);
3436
void readDbx(const std::string& dbx_file);
37+
void readBMap(const std::string& bmap_file);
3538

3639
private:
3740
void createChiplet(const ChipletDef& chiplet);
@@ -40,6 +43,7 @@ class ThreeDBlox
4043
void createChipInst(const ChipletInst& chip_inst);
4144
void createConnection(const Connection& connection);
4245
void createBump(const BumpMapEntry& entry, dbChipRegion* chip_region);
46+
dbInst* createBump(const BumpMapEntry& entry, dbBlock* block);
4347
dbChipRegionInst* resolvePath(const std::string& path,
4448
std::vector<dbChipInst*>& path_insts);
4549
void readHeaderIncludes(const std::vector<std::string>& includes);

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

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <cstddef>
77
#include <filesystem>
88
#include <map>
9+
#include <set>
910
#include <sstream>
1011
#include <string>
1112
#include <vector>
@@ -15,6 +16,7 @@
1516
#include "dbxParser.h"
1617
#include "objects.h"
1718
#include "odb/db.h"
19+
#include "odb/dbTransform.h"
1820
#include "odb/dbTypes.h"
1921
#include "odb/defin.h"
2022
#include "odb/geom.h"
@@ -444,4 +446,141 @@ void ThreeDBlox::createConnection(const Connection& connection)
444446
bottom_region);
445447
conn->setThickness(connection.thickness * db_->getDbuPerMicron());
446448
}
449+
450+
void ThreeDBlox::readBMap(const std::string& bmap_file)
451+
{
452+
dbBlock* block = db_->getChip()->getBlock();
453+
454+
BmapParser parser(logger_);
455+
BumpMapData data = parser.parseFile(bmap_file);
456+
std::vector<odb::dbInst*> bumps;
457+
bumps.reserve(data.entries.size());
458+
for (const auto& entry : data.entries) {
459+
bumps.push_back(createBump(entry, block));
460+
}
461+
462+
struct BPinInfo
463+
{
464+
dbTechLayer* layer = nullptr;
465+
odb::Rect rect;
466+
};
467+
468+
// Populate where the bpins should be made
469+
std::map<odb::dbMaster*, BPinInfo> bpininfo;
470+
for (dbInst* inst : bumps) {
471+
dbMaster* master = inst->getMaster();
472+
if (bpininfo.find(master) != bpininfo.end()) {
473+
continue;
474+
}
475+
476+
odb::dbTechLayer* max_layer = nullptr;
477+
std::set<odb::Rect> top_shapes;
478+
479+
for (dbMTerm* mterm : master->getMTerms()) {
480+
for (dbMPin* mpin : mterm->getMPins()) {
481+
for (dbBox* geom : mpin->getGeometry()) {
482+
auto* layer = geom->getTechLayer();
483+
if (layer == nullptr) {
484+
continue;
485+
}
486+
if (max_layer == nullptr) {
487+
max_layer = layer;
488+
top_shapes.insert(geom->getBox());
489+
} else if (max_layer->getRoutingLevel() <= layer->getRoutingLevel()) {
490+
if (max_layer->getRoutingLevel() < layer->getRoutingLevel()) {
491+
top_shapes.clear();
492+
}
493+
max_layer = layer;
494+
top_shapes.insert(geom->getBox());
495+
}
496+
}
497+
}
498+
}
499+
500+
if (max_layer != nullptr) {
501+
odb::Rect master_box;
502+
master->getPlacementBoundary(master_box);
503+
const odb::Point center = master_box.center();
504+
const odb::Rect* top_shape_ptr = nullptr;
505+
for (const odb::Rect& shape : top_shapes) {
506+
if (shape.intersects(center)) {
507+
top_shape_ptr = &shape;
508+
}
509+
}
510+
511+
if (top_shape_ptr == nullptr) {
512+
top_shape_ptr = &(*top_shapes.begin());
513+
}
514+
515+
bpininfo.emplace(master, BPinInfo{max_layer, *top_shape_ptr});
516+
}
517+
}
518+
519+
// create bpins
520+
for (dbInst* inst : bumps) {
521+
auto masterbpin = bpininfo.find(inst->getMaster());
522+
if (masterbpin == bpininfo.end()) {
523+
continue;
524+
}
525+
526+
const BPinInfo& pin_info = masterbpin->second;
527+
528+
const dbTransform xform = inst->getTransform();
529+
for (dbITerm* iterm : inst->getITerms()) {
530+
dbNet* net = iterm->getNet();
531+
if (net == nullptr) {
532+
continue;
533+
}
534+
dbBTerm* bterm = net->get1stBTerm();
535+
dbBPin* pin = dbBPin::create(bterm);
536+
Rect shape = pin_info.rect;
537+
xform.apply(shape);
538+
dbBox::create(pin,
539+
pin_info.layer,
540+
shape.xMin(),
541+
shape.yMin(),
542+
shape.xMax(),
543+
shape.yMax());
544+
pin->setPlacementStatus(odb::dbPlacementStatus::FIRM);
545+
break;
546+
}
547+
}
548+
}
549+
550+
dbInst* ThreeDBlox::createBump(const BumpMapEntry& entry, dbBlock* block)
551+
{
552+
const int dbus = db_->getDbuPerMicron();
553+
dbInst* inst = block->findInst(entry.bump_inst_name.c_str());
554+
if (inst == nullptr) {
555+
// create inst
556+
dbMaster* master = db_->findMaster(entry.bump_cell_type.c_str());
557+
if (master == nullptr) {
558+
logger_->error(utl::ODB,
559+
538,
560+
"3DBV Parser Error: Bump cell type {} not found",
561+
entry.bump_cell_type);
562+
}
563+
inst = dbInst::create(block, master, entry.bump_inst_name.c_str());
564+
}
565+
inst->setOrigin(entry.x * dbus, entry.y * dbus);
566+
inst->setPlacementStatus(dbPlacementStatus::FIRM);
567+
568+
// Net entry doesn't make sense
569+
if (entry.net_name != "-") {
570+
dbNet* net = block->findNet(entry.net_name.c_str());
571+
if (net == nullptr) {
572+
logger_->error(utl::ODB,
573+
539,
574+
"3DBV Parser Error: Bump net {} not found",
575+
entry.net_name);
576+
}
577+
for (odb::dbITerm* iterm : inst->getITerms()) {
578+
iterm->connect(net);
579+
}
580+
}
581+
// Port already on the net, so skip
582+
583+
return inst;
584+
}
585+
447586
} // namespace odb

src/odb/test/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ filegroup(
279279
"data/example.3dbv",
280280
"data/example.3dbx",
281281
"data/example.bmap",
282+
"data/example1.bmap",
282283
"data/floorplan_initialize.def",
283284
"data/floorplan_initialize.v",
284285
"data/floorplan_initialize2.def",

src/odb/test/cpp/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ cc_test(
224224
],
225225
deps = [
226226
"//src/odb",
227+
"//src/odb/test/cpp/helper",
227228
"//src/tst",
228229
"//src/tst:nangate45_fixture",
229230
"//src/utl",

src/odb/test/cpp/Test3DBloxParser.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <string>
33

44
#include "gtest/gtest.h"
5+
#include "helper.h"
56
#include "odb/3dblox.h"
67
#include "odb/db.h"
78
#include "odb/geom.h"
@@ -133,5 +134,72 @@ TEST_F(DbvFixture, test_bump_map_parser)
133134
EXPECT_EQ(bump_inst->getChipRegionInst(), region_inst);
134135
}
135136

137+
TEST_F(SimpleDbFixture, test_bump_map_reader)
138+
{
139+
createSimpleDB();
140+
141+
db_->setDbuPerMicron(1000);
142+
143+
// Create BUMP master
144+
dbLib* lib = db_->findLib("lib1");
145+
dbTechLayer* bot_layer
146+
= dbTechLayer::create(lib->getTech(), "BOT", dbTechLayerType::ROUTING);
147+
dbTechLayer* layer
148+
= dbTechLayer::create(lib->getTech(), "TOP", dbTechLayerType::ROUTING);
149+
dbMaster* master = dbMaster::create(lib, "BUMP");
150+
master->setWidth(10000);
151+
master->setHeight(10000);
152+
master->setOrigin(5000, 5000);
153+
master->setType(dbMasterType::COVER_BUMP);
154+
dbMTerm* term
155+
= dbMTerm::create(master, "PAD", dbIoType::INOUT, dbSigType::SIGNAL);
156+
dbMPin* bot_pin = dbMPin::create(term);
157+
dbBox::create(bot_pin, bot_layer, -1000, -1000, 1000, 1000);
158+
dbMPin* pin = dbMPin::create(term);
159+
dbBox::create(pin, layer, -2000, -2000, 2000, 2000);
160+
master->setFrozen();
161+
162+
// Create BTerms
163+
dbBlock* block = db_->getChip()->getBlock();
164+
dbBTerm* SIG1 = dbBTerm::create(dbNet::create(block, "SIG1"), "SIG1");
165+
dbBTerm* SIG2 = dbBTerm::create(dbNet::create(block, "SIG2"), "SIG2");
166+
block->setDieArea(Rect(0, 0, 500, 500));
167+
168+
EXPECT_EQ(block->getInsts().size(), 0);
169+
170+
ThreeDBlox parser(&logger_, db_.get());
171+
std::string path = getFilePath(prefix + "data/example1.bmap");
172+
parser.readBMap(path);
173+
174+
// Check bumps were created
175+
EXPECT_EQ(block->getInsts().size(), 2);
176+
dbInst* inst1 = block->findInst("bump1");
177+
EXPECT_EQ(inst1->getBBox()->getBox().xCenter(), 100 * 1000);
178+
EXPECT_EQ(inst1->getBBox()->getBox().yCenter(), 200 * 1000);
179+
dbInst* inst2 = block->findInst("bump2");
180+
EXPECT_EQ(inst2->getBBox()->getBox().xCenter(), 150 * 1000);
181+
EXPECT_EQ(inst2->getBBox()->getBox().yCenter(), 200 * 1000);
182+
183+
// Check that BPins where added
184+
EXPECT_EQ(SIG1->getBPins().size(), 1);
185+
EXPECT_EQ(SIG2->getBPins().size(), 1);
186+
EXPECT_EQ(SIG1->getBPins().begin()->getBoxes().size(), 1);
187+
EXPECT_EQ(SIG2->getBPins().begin()->getBoxes().size(), 1);
188+
189+
// Check bPin shape and layer
190+
dbBox* sig1_box = *SIG1->getBPins().begin()->getBoxes().begin();
191+
dbBox* sig2_box = *SIG2->getBPins().begin()->getBoxes().begin();
192+
EXPECT_EQ(sig1_box->getTechLayer(), layer);
193+
EXPECT_EQ(sig1_box->getBox().xMin(), 98000);
194+
EXPECT_EQ(sig1_box->getBox().yMin(), 198000);
195+
EXPECT_EQ(sig1_box->getBox().xMax(), 102000);
196+
EXPECT_EQ(sig1_box->getBox().yMax(), 202000);
197+
EXPECT_EQ(sig2_box->getTechLayer(), layer);
198+
EXPECT_EQ(sig2_box->getBox().xMin(), 148000);
199+
EXPECT_EQ(sig2_box->getBox().yMin(), 198000);
200+
EXPECT_EQ(sig2_box->getBox().xMax(), 152000);
201+
EXPECT_EQ(sig2_box->getBox().yMax(), 202000);
202+
}
203+
136204
} // namespace
137205
} // namespace odb

0 commit comments

Comments
 (0)