Skip to content

Commit b4d7822

Browse files
authored
Merge pull request #10625 from The-OpenROAD-Project-staging/web-backside-layer-category
web: group backside layers under a Backside category in the layer tree
2 parents 3f91f71 + 60928d6 commit b4d7822

3 files changed

Lines changed: 81 additions & 6 deletions

File tree

src/web/src/display-controls.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,18 @@ export function populateDisplayControls(app, visibility, selectability,
154154
});
155155
}
156156

157+
const nodeData = { name: hierarchyNode.name, isInstance: true };
158+
// chipletPath is the canonical "top.wrapper_1.MEM_2" string the
159+
// backend emits in layer_hierarchy; it matches ChipletNode::path
160+
// exactly so toggling this node can drive app.visibleChiplets.
161+
// Category nodes (e.g. "Backside") are pure UI folders — they have
162+
// no chiplet path and must not participate in chiplet sync.
163+
if (hierarchyNode.type !== 'category') {
164+
nodeData.chipletPath = hierarchyNode.path;
165+
}
157166
return {
158167
id: parentId,
159-
// chipletPath is the canonical "top.wrapper_1.MEM_2" string the
160-
// backend emits in layer_hierarchy; it matches ChipletNode::path
161-
// exactly so toggling this node can drive app.visibleChiplets.
162-
data: { name: hierarchyNode.name, isInstance: true,
163-
chipletPath: hierarchyNode.path },
168+
data: nodeData,
164169
children: children,
165170
};
166171
}

src/web/src/tile_generator.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3949,6 +3949,7 @@ boost::json::object buildLayerHierarchy(
39493949
json_node["path"] = node.path;
39503950

39513951
boost::json::array layers_arr;
3952+
boost::json::array backside_layers_arr;
39523953
if (node.chip) {
39533954
if (odb::dbTech* tech = node.chip->getTech()) {
39543955
const auto& layer_colors = gen.getLayerColorMap(tech);
@@ -3965,7 +3966,11 @@ boost::json::object buildLayerHierarchy(
39653966
layer_obj["color"] = boost::json::array{static_cast<int>(c.r),
39663967
static_cast<int>(c.g),
39673968
static_cast<int>(c.b)};
3968-
layers_arr.emplace_back(std::move(layer_obj));
3969+
if (layer->isBackside()) {
3970+
backside_layers_arr.emplace_back(std::move(layer_obj));
3971+
} else {
3972+
layers_arr.emplace_back(std::move(layer_obj));
3973+
}
39693974
}
39703975
}
39713976
}
@@ -3980,6 +3985,14 @@ boost::json::object buildLayerHierarchy(
39803985
buildLayerHierarchy(*child, children_by_parent, gen));
39813986
}
39823987
}
3988+
if (!backside_layers_arr.empty()) {
3989+
boost::json::object backside_node;
3990+
backside_node["name"] = "Backside";
3991+
backside_node["type"] = "category";
3992+
backside_node["layers"] = std::move(backside_layers_arr);
3993+
backside_node["instances"] = boost::json::array{};
3994+
instances_arr.emplace_back(std::move(backside_node));
3995+
}
39833996
json_node["instances"] = std::move(instances_arr);
39843997

39853998
return json_node;

src/web/test/cpp/TestTileGenerator.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,5 +1219,62 @@ TEST_F(TileGeneratorTest, SerializeTechResponseContainsBlockName)
12191219
<< "tech response missing block name value \"top\"; got: " << json;
12201220
}
12211221

1222+
TEST_F(TileGeneratorTest, LayerHierarchyBacksideCategory)
1223+
{
1224+
odb::dbTech* tech = getDb()->getTech();
1225+
1226+
// Mark metal1 and via1 as backside.
1227+
tech->findLayer("metal1")->setBackside(true);
1228+
tech->findLayer("via1")->setBackside(true);
1229+
1230+
makeTileGen();
1231+
const auto resp = serializeTechResponse(*tile_gen_);
1232+
ASSERT_TRUE(resp.contains("layer_hierarchy"));
1233+
const auto& hier = resp.at("layer_hierarchy").as_object();
1234+
1235+
// Top-level layers should NOT contain the backside layers.
1236+
const auto& top_layers = hier.at("layers").as_array();
1237+
for (const auto& l : top_layers) {
1238+
const auto& name = l.as_object().at("name").as_string();
1239+
EXPECT_NE(name, "metal1") << "backside metal1 should not be at top level";
1240+
EXPECT_NE(name, "via1") << "backside via1 should not be at top level";
1241+
}
1242+
1243+
// A "Backside" category node should exist in instances.
1244+
const auto& instances = hier.at("instances").as_array();
1245+
const boost::json::object* backside_node = nullptr;
1246+
for (const auto& inst : instances) {
1247+
const auto& obj = inst.as_object();
1248+
if (obj.at("name").as_string() == "Backside") {
1249+
backside_node = &obj;
1250+
break;
1251+
}
1252+
}
1253+
ASSERT_NE(backside_node, nullptr)
1254+
<< "layer_hierarchy missing Backside category node";
1255+
EXPECT_EQ(backside_node->at("type").as_string(), "category");
1256+
1257+
// The backside node should contain exactly metal1 and via1.
1258+
const auto& bs_layers = backside_node->at("layers").as_array();
1259+
std::set<std::string> bs_names;
1260+
for (const auto& l : bs_layers) {
1261+
bs_names.insert(std::string(l.as_object().at("name").as_string()));
1262+
}
1263+
EXPECT_EQ(bs_names, (std::set<std::string>{"metal1", "via1"}));
1264+
}
1265+
1266+
TEST_F(TileGeneratorTest, LayerHierarchyNoBacksideCategory)
1267+
{
1268+
// No layers marked backside — there should be no Backside category.
1269+
makeTileGen();
1270+
const auto resp = serializeTechResponse(*tile_gen_);
1271+
const auto& hier = resp.at("layer_hierarchy").as_object();
1272+
const auto& instances = hier.at("instances").as_array();
1273+
for (const auto& inst : instances) {
1274+
EXPECT_NE(inst.as_object().at("name").as_string(), "Backside")
1275+
<< "Backside category should not appear when no layers are backside";
1276+
}
1277+
}
1278+
12221279
} // namespace
12231280
} // namespace web

0 commit comments

Comments
 (0)