|
6 | 6 | #include <cstddef> |
7 | 7 | #include <filesystem> |
8 | 8 | #include <map> |
| 9 | +#include <set> |
9 | 10 | #include <sstream> |
10 | 11 | #include <string> |
11 | 12 | #include <vector> |
|
15 | 16 | #include "dbxParser.h" |
16 | 17 | #include "objects.h" |
17 | 18 | #include "odb/db.h" |
| 19 | +#include "odb/dbTransform.h" |
18 | 20 | #include "odb/dbTypes.h" |
19 | 21 | #include "odb/defin.h" |
20 | 22 | #include "odb/geom.h" |
@@ -444,4 +446,141 @@ void ThreeDBlox::createConnection(const Connection& connection) |
444 | 446 | bottom_region); |
445 | 447 | conn->setThickness(connection.thickness * db_->getDbuPerMicron()); |
446 | 448 | } |
| 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 | + |
447 | 586 | } // namespace odb |
0 commit comments