Skip to content

GUI: Handle display controls for multiple loaded technologies (Web GUI)#10348

Open
openroad-ci wants to merge 13 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:multiple-tech-display-control
Open

GUI: Handle display controls for multiple loaded technologies (Web GUI)#10348
openroad-ci wants to merge 13 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:multiple-tech-display-control

Conversation

@openroad-ci
Copy link
Copy Markdown
Collaborator

fix #10209

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements a hierarchical layer management system, enabling the web interface to display and control layers organized by chiplet instances. It includes backend serialization of the chip hierarchy and a recursive frontend implementation for the layer tree and visibility controls. Feedback highlights the need for stable layer IDs based on instance names, the removal of redundant visibility checks, and a more consistent ID construction scheme to simplify fragile matching logic in the inspector.

Comment thread src/web/src/display-controls.js Outdated

if (hierarchyNode.instances && hierarchyNode.instances.length > 0) {
hierarchyNode.instances.forEach((inst, idx) => {
const instId = `${parentId}_inst_${idx}`;
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.

high

Using an index-based ID (inst${idx}) makes the layer visibility state dependent on the order of instances in the JSON and breaks compatibility with the instance_path used by the inspector. It is better to use the instance name provided in the hierarchy node to ensure stable and predictable IDs.

Suggested change
const instId = `${parentId}_inst_${idx}`;
const instId = parentId + "/" + (inst.name || idx);

Comment thread src/web/src/inspector.js Outdated
if (app.layerModel && layer_id) {
const nodeId = instance_path ? `layers_parent_${instance_path}_${layer_id}` : layer_id;
// Check layerModel visibility
if (app.layerModel.isVisible && !app.layerModel.isVisible(nodeId) && !app.layerModel.isVisible(`layers_parent/${instance_path}/${layer_id}`) && !app.layerModel.isVisible(`layers_parent_${instance_path}/${layer_id}`) && !app.layerModel.isVisible(`layers_parent_${instance_path}/${layer_id}`) && !app.layerModel.isVisible(instance_path ? `${instance_path}/${layer_id}` : layer_id)) {
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.

high

This condition contains a duplicate check for layers_parent_${instance_path}/${layer_id}.

Additionally, the logic relies on multiple guesses for the layer ID format (using both _ and / as separators). This is fragile and suggests that the ID scheme is not unified across the application. It is recommended to use a consistent ID construction method (e.g., always using / as a separator) in both display-controls.js and inspector.js to avoid this complex and error-prone matching logic.

Comment thread src/web/src/display-controls.js Outdated
const id = name;
layer._nodeId = id;

const visible = !savedHiddenLayers.has(name) && !savedHiddenLayers.has(id);
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

This check is redundant because id is already assigned the value of name on line 140.

Suggested change
const visible = !savedHiddenLayers.has(name) && !savedHiddenLayers.has(id);
const visible = !savedHiddenLayers.has(id);

@openroad-ci openroad-ci force-pushed the multiple-tech-display-control branch from b2bf1ca to 756c2e2 Compare May 7, 2026 01:10
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

clang-tidy review says "All clean, LGTM! 👍"

@openroad-ci openroad-ci force-pushed the multiple-tech-display-control branch from 756c2e2 to 7e59f70 Compare May 14, 2026 00:06
@openroad-ci openroad-ci requested review from a team as code owners May 14, 2026 00:06
@github-actions github-actions Bot added size/XL and removed size/M labels May 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@openroad-ci openroad-ci force-pushed the multiple-tech-display-control branch from 7e59f70 to e982c5e Compare May 14, 2026 01:26
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

@jorge-ferreira-pii
Copy link
Copy Markdown
Contributor

jorge-ferreira-pii commented May 14, 2026

  1. Native Multi-Tech Support

    Simultaneous DB Support: The Web GUI backend now supports multiple technologies (db tech) concurrently, allowing for cross-platform integration within a single session.

  2. New Hierarchical Display Controls

    Session Chiplets: Introduced a dedicated control panel for design blocks. Users can now toggle the visibility of each chiplet independently to focus on specific areas of the design.

    Layer Hierarchy: Enhanced the "Layers" panel to logically group layers under their respective technology headers, featuring intuitive expand/collapse controls for better organization.

  3. Intelligent Highlight and Inspection (DRC)

    Visual Feedback: Improved highlight animations with a subtle "pulsing" effect. The highlight now fills the entire chiplet or cuboid (in 3D) with a distinct yellow fill for better visibility.

    Integrated 3D Visualization: DRC (violation) markers in the 3D viewer now feature active hitboxes. Double-clicking a violation in the 3D environment automatically:

    Sends the marker details to the Inspector panel.

    Populates the navigation history for quick backtracking.

  4. "True Z" Visualization in 3D

    Added the "True Z" graphical overlay, which positions layers based on their absolute Z-axis coordinates. This removes artificial stacking and provides a realistic view of how chiplets from different technologies physically interface.

@jorge-ferreira-pii
Copy link
Copy Markdown
Contributor

fix #10208

Resolves The-OpenROAD-Project#10208 by exposing a "Chiplets" section in the Web GUI's
Display Control panel.  When multiple chiplets are loaded (3DBX /
multi-die designs), each dbChip / dbChipInst node appears as a
checkbox; toggling propagates through CheckboxTreeModel (same pattern
as the Layers section) and refreshes the Leaflet tiles so the server
filters out hidden chiplets in renderTileBuffer.  Single-chip designs
do not show the section.

Frontend:
  - display-controls.js: buildChipletFlatNodes() + "Chiplets" group
    with tri-state header checkbox; hides are persisted per design in
    a cookie keyed by techData.block_name ({ block_name: [paths] }) so
    state does not leak across designs.
  - main.js: app.visibleChiplets Set forwarded to tile/select requests.
  - websocket-tile-layer.js: single buildTileRequest() includes
    visible_chiplets in every tile fetch and refresh.

Backend:
  - tile_generator.{h,cpp}: ChipletNode + collectChiplets() walks the
    dbChip → dbChipInst → masterChip tree depth-first, composing
    dbTransforms top-down via local.concat(parent_world_xfm); chiplet
    paths use "/" as separator (matches ODB hierarchical names);
    cached vector auto-invalidates on (root, total_chipinst_count)
    fingerprint change to catch Tcl-driven dbChipInst mutations that
    dbBlockCallBackObj does not surface.
  - TileVisibility::visible_chiplets + isChipletVisible() drive a
    server-side filter; tiles for hidden chiplets are skipped, not
    just hidden in CSS.
  - renderTileBuffer() loops per chiplet with an R0 fast-path and a
    reverse-mapping slow-path for non-R0 orientations.  selectAt()
    maps clicks through the inverse world transform so rotated /
    mirrored chiplet instances pick the right object.
  - serializeTechResponse emits a `chiplets` array with path, name,
    depth, parent, master, local/world bbox, world origin, orient.
  - getBounds() merges chiplet die areas in multi-die designs (single-
    chip designs stay on dbBlock BBox to preserve render scale).
  - getLayers() unions routing/cut layers from every reachable tech.
  - search.{h,cpp}: shared_mutex for child_block_data_ with double-
    checked locking in getData(); setTopChip() pre-populates every
    chiplet master block; shapesReady() now also checks chiplet master
    blocks so 3DBX/HIER top chips (no top block) no longer freeze the
    frontend on "Loading shapes…".
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
…ntrol

Bring in refinements from `feature-chiplets-section` (The-OpenROAD-Project#10208) on top of
the multi-tech display-controls work (The-OpenROAD-Project#10209).  Keeps the multi-tech
path semantics (e.g. dot-separated chiplet paths, layer_hierarchy,
PtrSet/PtrMap, getTech() wrapper, per-chiplet layer_colors) while
adopting:
  - cookie schema keyed by techData.block_name so hides do not leak
    across designs
  - countChipInsts() fingerprint to invalidate the chiplets() cache
    when Tcl creates/destroys dbChipInsts
  - improved comments on getLayers(), getBounds() and the chiplet
    visibility section

Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Three follow-ups to the multi-tech display-controls review:

- inspector.js: drop dead hover-rect filtering.  The unpacking of
  [x1,y1,x2,y2,layer_id,instance_path] never matched the backend
  payload (request_handler emits plain bboxes), so the layerModel
  visibility check was always skipped.  Replace with a TODO that
  documents what the backend has to emit before this filter can be
  reintroduced.

- display-controls.js fallback path: use the same layers_parent/<name>
  ID prefix as the modern layer_hierarchy path.  Cookies written under
  one path now round-trip cleanly through the other when the backend
  toggles between hierarchy and flat layer lists.

- display-controls.js / checkbox-tree-model.js: key chiplet nodes by
  their stable path string instead of an array index.  The intermediate
  pathToId Map and the parentId >= 0 sentinel disappear; tests with
  parentId:-1 still land in roots because _nodeMap.has(-1) is false.

- display-controls.js: skip cookie persistence entirely when
  techData.block_name is empty so anonymous designs do not collapse
  into a shared "" bucket and inherit each other's hidden state.

Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Three defensive fixes surfaced by the multi-tech audit:

- chiplets(): take chiplets_mutex_ before reading db_->getChip() and
  countChipInsts().  The previous arrangement computed the fingerprint
  outside the lock, opening a small TOCTOU window where the cached
  values could disagree with the live count.  Same critical section
  now covers both the check and the cache write.

- chiplets(): document the lifetime contract.  The returned reference
  is only valid while eagerInit() does not run; hot-path callers
  (renderTileBuffer, selectAt) must not trigger eagerInit while
  iterating, since the cache vector clear() in eagerInit() would
  invalidate their iterator.

- TileVisibility::parseFromJson(): clamp visible_layers and
  visible_chiplets to kMaxVisibilityEntries (10000) so a malformed or
  oversized client payload cannot pin unbounded memory or thrash
  later contains() checks.  Real designs come nowhere near the cap.

Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Two improvements for the 3D viewer DRC highlight path:

- highlightDRC(): replace the per-violation Mesh hitboxes with a single
  THREE.InstancedMesh backed by one shared unit BoxGeometry.  Per-rect
  width/height/depth are encoded in setMatrixAt(); a parallel
  _drcHitboxMarkerIds array maps instanceId back to violation.id for
  picking.  Edges/LineSegments stay per-rect for now — instancing
  EdgesGeometry under non-uniform scale would distort the outlines.

  Net effect: 1 draw call (was N) and 1 GPU geometry (was N) for the
  hit-test mesh, while the visual outline is unchanged.

- _pickDrcMarkerId(): switch from intersectObjects(hitbox children) to
  intersectObject(_drcHitboxMesh) and look up the markerId through the
  new instanceId map.

- onDestroy(): null out _lastSceneData so a destroyed widget does not
  hold the last scene payload alive in SPA-style design switches.

- clearHighlightDRC(): drop _drcHitboxMesh and _drcHitboxMarkerIds so
  a late pick after a clear cannot reach freed instance data.

Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
Drop a stray double blank line in renderTileBuffer() and rewrap the
getLayerColorMap declaration so it matches the project's clang-format
config.  Fixes the pre-commit Clang-Format check.

Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
@openroad-ci openroad-ci force-pushed the multiple-tech-display-control branch from e982c5e to 31acd9d Compare May 17, 2026 23:32
@github-actions
Copy link
Copy Markdown
Contributor

clang-tidy review says "All clean, LGTM! 👍"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GUI: Handle display controls for multiple loaded technologies

2 participants