Skip to content

Commit f547bba

Browse files
committed
ord: add read_3dblox_bmap command to read a bmap and create bumps
Signed-off-by: Peter Gadfort <[email protected]>
1 parent 05492f9 commit f547bba

File tree

7 files changed

+185
-0
lines changed

7 files changed

+185
-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, bool create_bpins = false);
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, bool create_bpins)
501+
{
502+
odb::ThreeDBlox parser(logger_, db_);
503+
parser.readBMap(filename, create_bpins);
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, bool create_bpins)
374+
{
375+
OpenRoad *ord = getOpenRoad();
376+
ord->read3DBloxBMap(filename, create_bpins);
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" {[-create_pins] filename}
201+
202+
proc read_3dblox_bmap { args } {
203+
sta::parse_key_args "read_3dblox_bmap" args keys {} flags {-create_pins}
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 [info exists flags(-create_pins)]
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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,21 @@ 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 [-create_pins] filename
344+
```
345+
346+
##### Options
347+
348+
| Switch Name | Description |
349+
| ----- | ----- |
350+
| `-create_pins` | If specified, block pins will be created over each bump. |
351+
| `filename` | Path to the bump map. |
352+
338353
## TCL functions
339354

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

0 commit comments

Comments
 (0)