|
1 | 1 | #include <exception> |
| 2 | +#include <filesystem> |
| 3 | +#include <fstream> |
| 4 | +#include <ios> |
2 | 5 | #include <set> |
3 | 6 | #include <vector> |
4 | 7 |
|
@@ -343,10 +346,14 @@ TEST_F(ChipHierarchyFixture, test_chip_bumps) |
343 | 346 | EXPECT_EQ(io_bump->getBTerm(), nullptr); |
344 | 347 | dbNet* net = dbNet::create(io_chip->getBlock(), "net1"); |
345 | 348 | dbBTerm* bterm = dbBTerm::create(net, "bterm1"); |
| 349 | + // Before setBTerm, getChipBump returns nullptr |
| 350 | + EXPECT_EQ(bterm->getChipBump(), nullptr); |
346 | 351 | io_bump->setNet(net); |
347 | 352 | io_bump->setBTerm(bterm); |
348 | 353 | EXPECT_EQ(io_bump->getNet(), net); |
349 | 354 | EXPECT_EQ(io_bump->getBTerm(), bterm); |
| 355 | + // After setBTerm, getChipBump returns the bump (back-reference) |
| 356 | + EXPECT_EQ(bterm->getChipBump(), io_bump); |
350 | 357 |
|
351 | 358 | EXPECT_EQ(io_chip_region_r1->getChipBumps().size(), 1); |
352 | 359 | EXPECT_EQ(*io_chip_region_r1->getChipBumps().begin(), io_bump); |
@@ -389,5 +396,67 @@ TEST_F(ChipHierarchyFixture, test_chip_bumps) |
389 | 396 | EXPECT_THROW(dbChipBump::create(io_chip_region_r1, io_cell), std::exception); |
390 | 397 | } |
391 | 398 |
|
| 399 | +TEST_F(SimpleDbFixture, test_chip_bump_bterm_serialization) |
| 400 | +{ |
| 401 | + createSimpleDB(); |
| 402 | + |
| 403 | + dbChip* chip = db_->getChip(); |
| 404 | + dbBlock* block = chip->getBlock(); |
| 405 | + |
| 406 | + // Create a chip region and a bump backed by an inst |
| 407 | + dbChipRegion* region = dbChipRegion::create( |
| 408 | + chip, "bump_region", dbChipRegion::Side::BACK, nullptr); |
| 409 | + dbLib* lib = db_->findLib("lib1"); |
| 410 | + dbMaster* bump_master = dbMaster::create(lib, "BUMP_CELL"); |
| 411 | + bump_master->setType(dbMasterType::COVER_BUMP); |
| 412 | + bump_master->setFrozen(); |
| 413 | + dbInst* bump_inst = dbInst::create(block, bump_master, "bump1"); |
| 414 | + dbChipBump* bump = dbChipBump::create(region, bump_inst); |
| 415 | + ASSERT_NE(bump, nullptr); |
| 416 | + |
| 417 | + // Associate a bterm with the bump |
| 418 | + dbBTerm* bterm = dbBTerm::create(dbNet::create(block, "SIG1"), "SIG1"); |
| 419 | + bump->setBTerm(bterm); |
| 420 | + ASSERT_EQ(bterm->getChipBump(), bump); |
| 421 | + |
| 422 | + // Write the database to a temp file |
| 423 | + std::filesystem::create_directory("results"); |
| 424 | + const std::string tmp_path = "results/test_chip_bump_bterm_serialization.odb"; |
| 425 | + { |
| 426 | + std::ofstream out; |
| 427 | + out.exceptions(std::ifstream::failbit | std::ifstream::badbit |
| 428 | + | std::ios::eofbit); |
| 429 | + out.open(tmp_path, std::ios::binary); |
| 430 | + db_->write(out); |
| 431 | + } |
| 432 | + |
| 433 | + // Read it back into a fresh database |
| 434 | + dbDatabase* db2 = dbDatabase::create(); |
| 435 | + { |
| 436 | + std::ifstream in; |
| 437 | + in.exceptions(std::ifstream::failbit | std::ifstream::badbit |
| 438 | + | std::ios::eofbit); |
| 439 | + in.open(tmp_path, std::ios::binary); |
| 440 | + db2->read(in); |
| 441 | + } |
| 442 | + |
| 443 | + // Locate the deserialized objects |
| 444 | + dbBlock* block2 = db2->getChip()->getBlock(); |
| 445 | + ASSERT_NE(block2, nullptr); |
| 446 | + |
| 447 | + dbBTerm* bterm2 = block2->findBTerm("SIG1"); |
| 448 | + ASSERT_NE(bterm2, nullptr); |
| 449 | + |
| 450 | + dbChipRegion* region2 = db2->getChip()->findChipRegion("bump_region"); |
| 451 | + ASSERT_NE(region2, nullptr); |
| 452 | + ASSERT_EQ(region2->getChipBumps().size(), 1); |
| 453 | + dbChipBump* bump2 = *region2->getChipBumps().begin(); |
| 454 | + ASSERT_NE(bump2, nullptr); |
| 455 | + |
| 456 | + // Verify the back-reference survived serialization |
| 457 | + EXPECT_EQ(bterm2->getChipBump(), bump2); |
| 458 | + EXPECT_EQ(bump2->getBTerm(), bterm2); |
| 459 | +} |
| 460 | + |
392 | 461 | } // namespace |
393 | 462 | } // namespace odb |
0 commit comments