Skip to content
Merged
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
33 changes: 33 additions & 0 deletions src/odb/include/odb/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class dbChipBumpInst;
class dbChipConn;
class dbChipInst;
class dbChipNet;
class dbChipPath;
class dbChipRegion;
class dbChipRegionInst;
class dbDatabase;
Expand Down Expand Up @@ -7265,6 +7266,10 @@ class dbChip : public dbObject

dbSet<dbMarkerCategory> getMarkerCategories() const;

dbSet<dbChipPath> getChipPaths() const;

dbChipPath* findChipPath(const char* name) const;

// User Code Begin dbChip

ChipType getChipType() const;
Expand Down Expand Up @@ -7441,6 +7446,34 @@ class dbChipNet : public dbObject
// User Code End dbChipNet
};

class dbChipPath : public dbObject
{
public:
const char* getName() const;

// User Code Begin dbChipPath
struct Entry
{
std::vector<dbChipInst*> chip_inst_path; // hierarchical path to the region
dbChipRegionInst* region;
bool negated; // do not touch this region, i.e., the path must be connected
// without crossing this region
};
Comment on lines +7455 to +7461
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.

This could be used in the dbChipConn as well. It should be defined outside the dbChipPath scope.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

How will it be used? I think keeping this private is better?


dbChip* getChip() const;

std::vector<Entry> getEntries() const;

void addEntry(const std::vector<dbChipInst*>& chip_inst_path,
dbChipRegionInst* region,
bool negated);

static dbChipPath* create(dbChip* chip, const char* name);

static void destroy(dbChipPath* path);
// User Code End dbChipPath
};

class dbChipRegion : public dbObject
{
public:
Expand Down
9 changes: 9 additions & 0 deletions src/odb/include/odb/dbCompare.inc
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,15 @@ struct less<odb::dbChipNet*>
}
};

template <>
struct less<odb::dbChipPath*>
{
bool operator()(const odb::dbChipPath* lhs, const odb::dbChipPath* rhs) const
{
return odb::compare_by_id(lhs, rhs);
}
};

template <>
struct less<odb::dbChipRegion*>
{
Expand Down
1 change: 1 addition & 0 deletions src/odb/include/odb/dbObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ enum dbObjectType
dbChipConnObj,
dbChipInstObj,
dbChipNetObj,
dbChipPathObj,
dbChipRegionObj,
dbChipRegionInstObj,
dbDatabaseObj,
Expand Down
9 changes: 9 additions & 0 deletions src/odb/src/3dblox/3dblox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,15 @@ void ThreeDBlox::readDbx(const std::string& dbx_file)
createConnection(connection);
}
calculateSize(chip);
for (const auto& [_, assertion] : data.path_assertions) {
dbChipPath* chip_path = dbChipPath::create(chip, assertion.name.c_str());
for (const auto& entry : assertion.entries) {
// Resolve the dotted path string to a live DB object
std::vector<dbChipInst*> path_insts;
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.

this should be used as per my previous comment.

dbChipRegionInst* region_inst = resolvePath(entry.region, path_insts);
chip_path->addEntry(path_insts, region_inst, entry.negated);
}
}
}

void ThreeDBlox::check()
Expand Down
12 changes: 12 additions & 0 deletions src/odb/src/3dblox/baseParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,19 @@ std::string BaseParser::trim(const std::string& str)
return str.substr(start, end - start + 1);
}

template <typename T>
void BaseParser::extractValue(const YAML::Node& node, T& value)
{
try {
value = node.as<T>();
} catch (const YAML::Exception& e) {
logError("Error parsing value: " + std::string(e.what()));
}
}

// Explicit template instantiations for common types
template void BaseParser::extractValue<std::string>(const YAML::Node& node,
std::string& value);
template void BaseParser::extractValue<std::string>(const YAML::Node& node,
const std::string& key,
std::string& value);
Expand Down
3 changes: 2 additions & 1 deletion src/odb/src/3dblox/baseParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#pragma once

#include <map>
#include <string>
#include <vector>

Expand All @@ -28,6 +27,8 @@ class BaseParser
// YAML helper methods
template <typename T>
void extractValue(const YAML::Node& node, const std::string& key, T& value);
template <typename T>
void extractValue(const YAML::Node& node, T& value);
void parseCoordinate(Coordinate& coord, const YAML::Node& coord_node);
void parseCoordinates(std::vector<Coordinate>& coords,
const YAML::Node& coords_node);
Expand Down
64 changes: 64 additions & 0 deletions src/odb/src/3dblox/dbxParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ void DbxParser::parseYamlContent(DbxData& data, const std::string& content)
if (root["Connection"]) {
parseConnections(data.connections, root["Connection"]);
}
if (root["Path"]) {
parsePaths(data.path_assertions, root["Path"]);
}

} catch (const YAML::Exception& e) {
logError("DBX YAML parsing error: " + std::string(e.what()));
Expand Down Expand Up @@ -233,4 +236,65 @@ void DbxParser::parseConnection(Connection& connection,
}
}

void DbxParser::parsePaths(std::map<std::string, PathAssertion>& paths,
const YAML::Node& paths_node)
{
paths.clear();
const std::string prefix = "Path";
for (const auto& path_pair : paths_node) {
PathAssertion path;
extractValue(path_pair.first, path.name);

// Validate name format: must be "PathN" where N is a positive integer.
if (path.name.size() <= prefix.size() || !path.name.starts_with(prefix)
|| path.name.find_first_not_of("0123456789", prefix.size())
!= std::string::npos
|| path.name[prefix.size()] == '0') {
Comment on lines +249 to +252
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The validation logic for the path assertion name allows names like Path01, which might be confusing. It would be better to disallow leading zeros to ensure a cleaner naming convention.

        || path.name[prefix.size()] == '0') {

logError("DBX Path assertion name '" + path.name
+ "' must follow the format 'PathN' (e.g. Path1, Path2)");
continue;
}

const YAML::Node& path_node = path_pair.second;
parsePath(path, path_node);
paths[path.name] = path;
}
}

void DbxParser::parsePath(PathAssertion& path, const YAML::Node& path_node)
{
if (!path_node.IsSequence()) {
logError("DBX Path assertion '" + path.name + "' must be a YAML sequence");
}

const std::string prefix = "NOT ";
for (const auto& entry_node : path_node) {
std::string raw;
extractValue(entry_node, raw);

raw = trim(raw);
if (raw.empty()) {
continue;
}

PathAssertionEntry entry;
if (raw.substr(0, prefix.size()) == prefix) {
entry.negated = true;
raw = trim(raw.substr(prefix.size()));
}

if (raw.find(".regions.") == std::string::npos) {
logError("DBX Path assertion entry '" + raw + "' in '" + path.name
+ "' must contain '.regions.' (e.g. HBM_1.regions.r1)");
}

entry.region = raw;
path.entries.push_back(entry);
}

if (path.entries.empty()) {
logError("DBX Path assertion '" + path.name + "' has no valid entries");
}
}

} // namespace odb
3 changes: 3 additions & 0 deletions src/odb/src/3dblox/dbxParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class DbxParser : public BaseParser
const YAML::Node& connections_node);
void parseConnection(Connection& connection,
const YAML::Node& connection_node);
void parsePaths(std::map<std::string, PathAssertion>& paths,
const YAML::Node& paths_node);
void parsePath(PathAssertion& path, const YAML::Node& path_node);
};

} // namespace odb
13 changes: 13 additions & 0 deletions src/odb/src/3dblox/objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@

namespace odb {

struct PathAssertionEntry
{
std::string region; // e.g. "HBM_1.regions.r1"
bool negated = false; // true when prefixed with "NOT"
};

struct PathAssertion
{
std::string name; // e.g. "Path1"
std::vector<PathAssertionEntry> entries;
};

struct Coordinate
{
double x, y;
Expand Down Expand Up @@ -121,6 +133,7 @@ struct DbxData
DesignDef design;
std::map<std::string, ChipletInst> chiplet_instances;
std::map<std::string, Connection> connections;
std::map<std::string, PathAssertion> path_assertions;
};

struct BumpMapEntry
Expand Down
1 change: 1 addition & 0 deletions src/odb/src/codeGenerator/gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ def add_field_attributes(
and not template_class_name.isdigit()
and template_class_name not in {"true", "false"}
and "no-template" not in field.flags
and template_class_name.startswith("_")
and klass.name != template_class_name[1:]
and klass.name + "::" != template_class_name[: len(klass.name) + 2]
)
Expand Down
30 changes: 25 additions & 5 deletions src/odb/src/codeGenerator/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,36 @@ def is_template_type(type_name: str) -> bool:
return closed_bracket >= open_bracket


def _is_comma_divided(type_name: str) -> bool:
return "," in type_name
def _split_top_level_commas(type_name: str) -> List[str]:
"""Split by commas at angle-bracket depth 0."""
parts = []
depth = 0
start = 0
for i, ch in enumerate(type_name):
if ch == "<":
depth += 1
elif ch == ">":
depth -= 1
elif ch == "," and depth == 0:
parts.append(type_name[start:i].strip())
start = i + 1
parts.append(type_name[start:].strip())
return [p for p in parts if p]


def get_template_types(type_name: str) -> List[str]:
# Check for top-level commas first (bracket-aware)
parts = _split_top_level_commas(type_name)
if len(parts) > 1:
result = []
for part in parts:
if part.isdigit() or part in {"true", "false"}:
continue
result.extend(get_template_types(part))
return result
# Single type — if it is a template, peel the outer layer
if is_template_type(type_name):
return get_template_types(get_template_type(type_name))
if _is_comma_divided(type_name):
types = [t.strip() for t in type_name.split(",")]
return [t for t in types if not (t.isdigit() or t in {"true", "false"})]
return [type_name]


Expand Down
9 changes: 9 additions & 0 deletions src/odb/src/codeGenerator/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,15 @@
"tbl_name":"chip_net_tbl_",
"schema":"kSchemaChipRegion",
"flags": ["no-serial"]
},
{
"parent":"dbChip",
"child":"dbChipPath",
"type":"1_n",
"tbl_name":"chip_path_tbl_",
"schema":"kSchemaChipPath",
"hash": true,
"flags": ["no-serial"]
}
]
}
30 changes: 30 additions & 0 deletions src/odb/src/codeGenerator/schema/chip/dbChipPath.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "dbChipPath",
"type": "dbObject",
"fields": [
{
"name": "name_",
"type": "char *",
"default": "nullptr",
"flags": [
"no-set"
]
},
{
"name": "entries_",
"type": "std::vector<std::tuple<std::vector<dbId<_dbChipInst>>, dbId<_dbChipRegionInst>, bool>>",
"flags": [
"private",
"no-cmp"
Comment thread
maliberty marked this conversation as resolved.
]
}
],
"h_includes": [
"odb/dbId.h"
],
"cpp_includes": [
"dbChip.h",
"dbChipRegionInst.h",
"dbChipInst.h"
]
}
1 change: 1 addition & 0 deletions src/odb/src/db/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ add_library(db
dbChipConn.cpp
dbChipInst.cpp
dbChipNet.cpp
dbChipPath.cpp
dbChipRegion.cpp
dbChipRegionInst.cpp
dbDatabase.cpp
Expand Down
Loading
Loading