Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/odb/include/odb/3dblox.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ struct Connection;
struct DesignDef;
struct BumpMapEntry;
struct DbxData;

class ThreeDBlox
{
public:
Expand Down
4 changes: 4 additions & 0 deletions src/odb/include/odb/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -7262,6 +7262,10 @@ class dbChip : public dbObject

bool isTsv() const;

void setBlackbox(bool blackbox);

bool isBlackbox() const;

Comment on lines +7265 to +7268
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that the blackbox state should be user defined. It should be inferred from the current state of the chiplet. From looking at the code, I can see that you set it once and never change it again even if the netlist is added later with routing.
For now let's remove it and assume that the path assertions are in the scope of the blockbox state only.

dbSet<dbChipRegion> getChipRegions() const;

dbSet<dbMarkerCategory> getMarkerCategories() const;
Expand Down
5 changes: 5 additions & 0 deletions src/odb/include/odb/unfoldedModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ struct UnfoldedChip
Cuboid cuboid;
dbTransform transform;

// True when the master chip has no detailed routing (blackbox stage).
// The routing graph adds a complete clique across all regions of a blackbox
// chip so they are treated as mutually reachable.
bool is_blackbox = false;

std::deque<UnfoldedRegion> regions;

std::unordered_map<dbChipRegionInst*, UnfoldedRegion*> region_map;
Expand Down
140 changes: 85 additions & 55 deletions src/odb/src/3dblox/3dblox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,61 @@ void ThreeDBlox::readDbx(const std::string& dbx_file)
}
}

static std::vector<std::string> splitPath(const std::string& path)
{
std::vector<std::string> parts;
std::istringstream stream(path);
std::string part;

while (std::getline(stream, part, '/')) {
if (!part.empty()) {
parts.push_back(part);
}
}

return parts;
}
Comment on lines +203 to +216
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use boost::split


// Resolves a path string of the form "inst1/inst2.regions.regionName" into a
// dbChipRegionInst* by walking the chip hierarchy starting from root_chip.
// If path_insts is non-null, each visited dbChipInst* is appended to it.
// Returns nullptr if any component of the path is not found; does not log.
static dbChipRegionInst* walkRegionPath(const std::string& path,
dbChip* root_chip,
std::vector<dbChipInst*>* path_insts)
{
auto path_parts = splitPath(path);
if (path_parts.empty()) {
return nullptr;
}
const size_t regions_pos = path_parts.back().find(".regions.");
if (regions_pos == std::string::npos) {
return nullptr;
}
const std::string region_name = path_parts.back().substr(regions_pos + 9);
path_parts.back() = path_parts.back().substr(0, regions_pos);

if (path_insts) {
path_insts->reserve(path_parts.size());
}
dbChip* curr_chip = root_chip;
dbChipInst* curr_inst = nullptr;
for (const auto& inst_name : path_parts) {
curr_inst = curr_chip->findChipInst(inst_name);
if (!curr_inst) {
return nullptr;
}
if (path_insts) {
path_insts->push_back(curr_inst);
}
curr_chip = curr_inst->getMasterChip();
}
if (!curr_inst) {
return nullptr;
}
return curr_inst->findChipRegionInst(region_name);
}

void ThreeDBlox::check()
{
Checker checker(logger_, db_);
Expand Down Expand Up @@ -503,6 +558,7 @@ void ThreeDBlox::createChiplet(const ChipletDef& chiplet)
if (chip->getChipType() != dbChip::ChipType::HIER
&& chip->getBlock() == nullptr) {
// blackbox stage, create block
chip->setBlackbox(true);
auto block = odb::dbBlock::create(chip, chiplet.name.c_str());
const int x_min = chip->getScribeLineWest() + chip->getSealRingWest();
const int y_min = chip->getScribeLineSouth() + chip->getSealRingSouth();
Expand Down Expand Up @@ -698,67 +754,41 @@ void ThreeDBlox::createChipInst(const ChipletInst& chip_inst)
static_cast<int>(std::round(chip_inst.z * dbu_per_micron)),
});
}
static std::vector<std::string> splitPath(const std::string& path)
{
std::vector<std::string> parts;
std::istringstream stream(path);
std::string part;

while (std::getline(stream, part, '/')) {
if (!part.empty()) {
parts.push_back(part);
}
}

return parts;
}

dbChipRegionInst* ThreeDBlox::resolvePath(const std::string& path,
std::vector<dbChipInst*>& path_insts)
{
if (path == "~") {
if (path == "~" || path == "null") {
return nullptr;
}
// Split the path by '/'
std::vector<std::string> path_parts = splitPath(path);

if (path_parts.empty()) {
logger_->error(utl::ODB, 524, "3DBX Parser Error: Invalid path {}", path);
}

// The last part should contain ".regions.regionName"
std::string last_part = path_parts.back();
size_t regions_pos = last_part.find(".regions.");
if (regions_pos == std::string::npos) {
return nullptr; // Invalid format
}

// Extract chip instance name and region name from last part
std::string last_chip_inst = last_part.substr(0, regions_pos);
std::string region_name = last_part.substr(regions_pos + 9);

// Replace the last part with just the chip instance name
path_parts.back() = last_chip_inst;

// Traverse hierarchy and find region
path_insts.reserve(path_parts.size());
dbChip* curr_chip = db_->getChip();
dbChipInst* curr_chip_inst = nullptr;

for (const auto& inst_name : path_parts) {
curr_chip_inst = curr_chip->findChipInst(inst_name);
if (curr_chip_inst == nullptr) {
logger_->error(utl::ODB,
522,
"3DBX Parser Error: Chip instance {} not found in path {}",
inst_name,
path);
auto* region = walkRegionPath(path, db_->getChip(), &path_insts);
if (!region) {
// Determine which component failed for a specific error message.
// Re-walk without collecting path_insts to find the failing step.
auto path_parts = splitPath(path);
if (path_parts.empty()) {
logger_->error(utl::ODB, 524, "3DBX Parser Error: Invalid path {}", path);
}
// Check if the path has ".regions." at all
const std::string& last = path_parts.back();
size_t rpos = last.find(".regions.");
if (rpos == std::string::npos) {
return nullptr; // Invalid format
}
std::string region_name = last.substr(rpos + 9);
path_parts.back() = last.substr(0, rpos);

dbChip* curr_chip = db_->getChip();
for (const auto& inst_name : path_parts) {
if (!curr_chip->findChipInst(inst_name)) {
logger_->error(
utl::ODB,
522,
"3DBX Parser Error: Chip instance {} not found in path {}",
inst_name,
path);
}
curr_chip = curr_chip->findChipInst(inst_name)->getMasterChip();
}
path_insts.push_back(curr_chip_inst);
curr_chip = curr_chip_inst->getMasterChip();
}
auto region = curr_chip_inst->findChipRegionInst(region_name);
if (region == nullptr) {
logger_->error(utl::ODB,
523,
"3DBX Parser Error: Chip region {} not found in path {}",
Expand Down
1 change: 1 addition & 0 deletions src/odb/src/3dblox/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ add_library(3dblox
dbxWriter.cpp
verilogWriter.cpp
3dblox.cpp
routingGraph.cpp
checker.cpp
)

Expand Down
Loading
Loading