Web Viewer#

The web viewer module in OpenROAD (web) provides a browser-based interface for exploring chip layouts and performing design analysis. It renders the design as PNG tiles served over WebSocket, enabling smooth zoom and pan of large designs without a native GUI.

Commands#

Note

  • Parameters in square brackets [-param param] are optional.

  • Parameters without square brackets -param2 param2 are required.

Web Server#

Start the web viewer server. This opens a WebSocket server and launches the viewer in the default browser. The command blocks until the server stops, so the design can be explored interactively; Tcl commands typed in the browser console run on the server.

web_server
    [-port port]
    [-stop]

Options#

Switch Name

Description

-port

TCP port to listen on. Default: 0, which picks a free port.

-stop

Stop a running server and return from the blocked web_server call.

-dir

Deprecated and ignored; the web assets are embedded in the binary.

Save Image#

Save the layout to a PNG file. By default, the command uses the GUI (Qt) renderer. Pass -web to use the web tile renderer instead, which runs entirely server-side without a display and is suitable for headless CI.

save_image
    [-web]
    [-area {x0 y0 x1 y1}]
    [-width width]
    [-resolution microns_per_pixel]
    [-display_option option]
    path

Options#

Switch Name

Description

-web

Use the web tile renderer instead of the GUI renderer. Does not require a display or a running web server.

-area

Bounding box in microns {x0 y0 x1 y1}. Default: die area (with 5% margin in -web mode).

-width

Output image width in pixels. Cannot be used with -resolution.

-resolution

Resolution in microns per pixel. Minimum: 1 DBU per pixel. Cannot be used with -width.

-display_option

Repeatable visibility overrides as {control value} pairs. See Display option keys below.

path

Output PNG file path.

When using -web, if neither -width nor -resolution is specified, the image defaults to 1024 pixels wide. The maximum image dimension is 16384 pixels; larger requests are clamped automatically.

Display option keys (web mode)#

Display options control which elements are rendered when using -web. Each option is a {key value} pair where the key matches a visibility field and the value is true or false.

Key

Default

Description

stdcells

true

Standard cells

macros

true

Macros

routing

true

Signal routing

special_nets

true

Power/ground straps

pins

true

Instance pins

pin_markers

true

IO pin direction markers

blockages

true

Blockages

net_signal

true

Signal nets

net_power

true

Power nets

net_clock

true

Clock nets

rows

false

Row outlines

tracks_pref

false

Preferred-direction tracks

rudy

false

Estimated congestion (RUDY) heatmap overlay

Examples#

# Save using the GUI renderer (default)
save_image layout.png

# Save using the web renderer (headless)
save_image -web layout.png

# Save at 1024px wide with the web renderer
save_image -web -width 1024 layout.png

# Save at 0.1 um per pixel
save_image -web -resolution 0.1 layout.png

# Save a specific region (in microns)
save_image -web -area {0 0 100 100} -width 2048 region.png

# Hide routing and power nets
save_image -web -display_option {routing false} \
                -display_option {net_power false} \
                layout.png

# Save with RUDY congestion heatmap overlay
save_image -web -display_option {rudy true} layout_rudy.png

Save Animated GIF#

Build an animated GIF from a sequence of layout snapshots, so an optimization loop can be watched frame by frame.

The command is a three-call state machine. -start opens a stream and returns an integer key; each -add captures the current state of the design as one frame; -end finalizes the file. Several streams can be open at once, told apart by their keys.

This is the same command the Qt GUI provides, and it dispatches to whichever viewer is up: the Qt GUI grabs its own window, while the web renderer composites the frame server-side, needing neither a display nor a running server — so it also covers a Qt build launched without -gui. -display_option is web-only, so on the Qt path it warns and is ignored.

save_animated_gif
    (-start|-add|-end)
    [-area {x0 y0 x1 y1}]
    [-width width]
    [-resolution microns_per_pixel]
    [-delay delay]
    [-key key]
    [-display_option option]
    [path]

Options#

Switch Name

Description

-start

Open a new GIF stream and return its key. Requires path; the frame options are ignored.

-add

Capture the design’s current state as one frame. Takes no path.

-end

Finalize and close the GIF. Takes no path.

-area

Bounding box in microns {x0 y0 x1 y1}. The default is the die area with a 5% margin.

-width

Frame width in pixels. The type is int, and must be positive. Cannot be used with -resolution. The default is 1024.

-resolution

Resolution in microns per pixel. The type is float, and must be positive; it is raised to 1 DBU per pixel if finer. Cannot be used with -width.

-delay

Time each frame is shown, in hundredths of a second. The type is int, and must be positive. The default is 250, i.e. 2.5 seconds.

-key

Which open stream to act on, as returned by -start. The type is int. The default is the most recently opened stream.

-display_option

Repeatable visibility overrides as {control value} pairs, the same keys save_image -web accepts. See Display option keys above.

path

Output GIF file path. Required with -start, rejected otherwise.

The defaults above are the web renderer’s; on the Qt path the GUI’s own apply — -area defaults to what is visible on screen, and -resolution to the zoom the GUI is at.

On the web path, the first frame fixes the GIF’s dimensions; a later frame that comes out a different size — because the design’s bounding box grew, say — is rescaled to match rather than starting a second GIF. Area outside the design is left transparent, which most viewers show as black. Ending a stream that never received a frame writes no file and warns. The maximum frame dimension is 16384 pixels, as for save_image; larger requests are clamped.

Examples#

# One GIF, one frame per placement iteration
set gif [save_animated_gif -start placement.gif]
for {set i 0} {$i < 10} {incr i} {
  global_placement -incremental
  save_animated_gif -add -key $gif -width 800 -delay 50
}
save_animated_gif -end -key $gif

# A single stream needs no key
save_animated_gif -start route.gif
save_animated_gif -add -resolution 0.1
save_animated_gif -add -resolution 0.1
save_animated_gif -end

# Zoom in on a region and show only routing
save_animated_gif -add -area {0 0 100 100} \
                       -display_option {stdcells false} \
                       -display_option {routing true}

Save Report#

Generate a self-contained HTML timing report. The report uses the same JavaScript frontend as the live web viewer but serves all data from a cache embedded in the HTML file. No running server is required to view the report.

web_save_report
    [-setup_paths count]
    [-hold_paths count]
    path

Options#

Switch Name

Description

-setup_paths

Maximum number of setup timing paths to include. Default: 100.

-hold_paths

Maximum number of hold timing paths to include. Default: 100.

path

Output HTML file path.

The report includes:

  • Layout view with pre-rendered tiles at a fixed zoom level. Layer visibility can be toggled using the same display controls as the live viewer. Zoom is disabled; pan is allowed.

  • Timing table with setup and hold paths. Clicking a path highlights it on the layout via a pre-rendered overlay image.

  • Slack histogram with setup/hold tabs.

  • Display controls, hierarchy browser, clock tree, and other panels from the live viewer (features that require server interaction show empty states).

The report requires an internet connection to load Leaflet and GoldenLayout CSS/JS from CDN.

Examples#

# Generate a report with default settings
web_save_report timing.html

# Include more paths
web_save_report -setup_paths 200 -hold_paths 200 timing.html

Save Display Controls#

Write the display-controls state of the connected viewer to a JSON file, so a particular set of visibility, selectability, layer-pattern and theme choices can be reused later or shared.

save_display_controls
    filename

Options#

Switch Name

Description

filename

Output JSON file path.

The viewer pushes a snapshot of its state to the server whenever a control changes, and this command writes the most recent snapshot. It therefore requires a running server (web_server) with a viewer open; otherwise it errors, or warns if no snapshot has arrived yet. The server caches a single snapshot, so with several viewers connected the state saved is that of whichever one synced last.

Because Tcl commands typed into the browser console run on the server, this is normally invoked from the viewer’s own console after arranging the panel.

Restore Display Controls#

Apply a previously saved display-controls file to every connected viewer.

restore_display_controls
    filename

Options#

Switch Name

Description

filename

Input JSON file path, as written by save_display_controls.

The state is broadcast to all connected clients, each of which re-applies it and reloads, preserving the current camera position. A key absent from the file is reset to its default rather than left as-is. The file is validated before it is broadcast; a malformed or unexpectedly shaped file is rejected with an error and nothing is applied.

Like save_display_controls, this requires a running server.

Examples#

# In the viewer's Tcl console, after setting up the panel
save_display_controls my_view.json

# Later, in another session with the viewer open
restore_display_controls my_view.json

Create Toolbar Button#

Add a button to the viewer’s toolbar that runs a Tcl script when clicked.

Returns the button’s key, either name or buttonN.

This is the same command the Qt GUI provides, and it dispatches to whichever viewer is up: the Qt GUI when its window is running, the web viewer otherwise — including in a Qt build launched without -gui.

create_toolbar_button
    [-name name]
    -text button_text
    -script tcl_script
    [-icon icon]
    [-tooltip tooltip]
    [-toggle]
    [-script_off tcl_script_off]
    [-echo]

Options#

Switch Name

Description

-name

Key used to remove the button later. The type is string. The default is a generated buttonN. Re-using a registered name is an error.

-text

Label to put on the button. The type is string. Required.

-script

Tcl script to evaluate when the button is clicked, or — with -toggle — when it is switched on. The type is string. Required.

-icon

Icon to show before the label: either literal text (an emoji, say) or an image referenced by data: URI, http(s): URL or a path starting with / or ./. The type is string. The default is no icon.

-tooltip

Hover text. The type is string. The default is no tooltip.

-toggle

Make the button a two-state switch: clicking it runs -script when turning it on and -script_off when turning it off.

-script_off

Tcl script to evaluate when a -toggle button is switched off. The type is string. Ignored without -toggle.

-echo

Echo the script into the browser’s Tcl console before running it.

-icon, -tooltip, -toggle and -script_off are web-only: the Qt GUI’s buttons are text-only and stateless, so when the dispatch lands on Qt these warn and are ignored rather than erroring, letting one script drive either viewer.

Remove Toolbar Button#

Remove a button added by create_toolbar_button. Removing a name that is not registered does nothing.

remove_toolbar_button
    name

Options#

Switch Name

Description

name

Key of the button to remove, as returned by create_toolbar_button. The type is string.

Create Menu Item#

Add an item to the viewer’s menu bar that runs a Tcl script when chosen.

Returns the item’s key, either name or actionN.

This is the same command the Qt GUI provides, and it dispatches to whichever viewer is up: the Qt GUI when its window is running, the web viewer otherwise — including in a Qt build launched without -gui.

create_menu_item
    [-name name]
    [-path menu_path]
    -text item_text
    -script tcl_script
    [-shortcut shortcut]
    [-echo]

Options#

Switch Name

Description

-name

Key used to remove the item later. The type is string. The default is a generated actionN. Re-using a registered name is an error.

-path

Menu to place the item in, as a /-separated hierarchy. The first segment is a top-level menu, created if it does not exist; deeper segments nest as submenus. The type is string. The default is Custom Scripts.

-text

Text to put on the item. The type is string. Required.

-script

Tcl script to evaluate when the item is chosen. The type is string. Required.

-shortcut

Key shortcut that triggers the item, e.g. Ctrl+H. Displayed beside the label. The type is string. The default is none.

-echo

Echo the script into the browser’s Tcl console before running it.

-shortcut is written the way Qt writes it: modifiers (Ctrl, Shift, Alt, MetaCmd is accepted for Meta) joined to a key with +, in any order. On the web path the key is matched as the browser reports it, so name non-printing keys accordingly: Escape, ArrowUp, F5. A spec naming no key (Ctrl+) or an unrecognized modifier is ignored rather than bound to something the script did not ask for, and a shortcut is not delivered while a text field has focus. A custom shortcut that claims a key the viewer already uses takes it over, rather than triggering both.

Remove Menu Item#

Remove an item added by create_menu_item. Removing a name that is not registered does nothing.

remove_menu_item
    name

Options#

Switch Name

Description

name

Key of the item to remove, as returned by create_menu_item. The type is string.

Examples#

# A button that reports the current worst slack
create_toolbar_button -text "Worst slack" \
                      -script {report_worst_slack} \
                      -icon "⏱" \
                      -tooltip "Report the worst setup slack" \
                      -echo

# A two-state button, running one script when switched on and another off
create_toolbar_button -name drt_debug -text "DRT maze" -toggle \
                      -script {set_debug_level DRT maze 1} \
                      -script_off {set_debug_level DRT maze 0}
remove_toolbar_button drt_debug

# A menu item under a submenu of its own
create_menu_item -name checkpoint -path "Flow/Checkpoints" \
                 -text "Write DB..." -shortcut "Ctrl+S" \
                 -script {write_db checkpoint.odb}
remove_menu_item checkpoint

On the web path these can be run before web_server, from a startup script: the registry lives on the server, so it survives page reloads and is served to clients that connect later. Each change is also pushed to every connected client, so a button created in one browser’s Tcl console appears in all of them — something the single-window Qt GUI cannot do.

Features#

  • Tile-based rendering — The server renders 256x256 PNG tiles on demand, supporting smooth zoom and pan of designs with millions of instances.

  • Object inspection — Click on instances, nets, pins, or other objects to view their properties in an inspector panel. Hover highlights are rendered server-side in tiles.

  • Timing analysis — View timing paths with slack, delay, and arrival time metrics. Highlight critical paths on the layout. Slack histogram charts with filtering by path group and clock domain.

  • Clock tree visualization — Browse clock tree hierarchy, highlight clock paths, and view per-level statistics.

  • Hierarchy browser — Navigate the module tree with instance counts and area statistics. Toggle visibility and assign colors per module using a 31-color palette.

  • Display controls — Toggle visibility of cell types (stdcells, macros, pads), net types (signal, power, clock), and shapes (routing, pins, blockages, rows, tracks). The panel state can be saved to and restored from a file with save_display_controls / restore_display_controls.

  • Focus nets — Isolate specific nets for inspection, dimming all other routing.

  • Tcl console — Execute Tcl commands interactively from the browser.

  • Custom menu items and toolbar buttons — Bind Tcl scripts to the viewer’s menu bar, toolbar and keyboard with create_menu_item / create_toolbar_button. The registry lives on the server, so it is shared by every connected browser.

  • Image export — Save the layout as a PNG with save_image -web or as an animated GIF with save_animated_gif, both headless. Panels export themselves client-side, from a button in the panel rather than a Tcl command: the schematic as SVG or PNG, the 3D view as PNG, the charts as CSV or PNG, and the clock tree as PNG.

  • Editing utilities — Inspect, delete and re-apply global-connect rules, and insert a buffer on a net, from dialogs in the Tools menu and the inspector.

Architecture#

The module has two parts:

  • C++ server (src/web.cpp, src/request_handler.cpp, src/tile_generator.cpp) — A Boost Beast WebSocket server that handles tile rendering, object selection, timing/clock-tree queries, and Tcl evaluation. Tiles are rendered from ODB geometry and encoded as PNG using lodepng.

  • JavaScript frontend (src/main.js, src/index.html, src/style.css) — A single-page application using Leaflet.js for the map and GoldenLayout for resizable panels. Communicates with the server over a binary WebSocket protocol.

Server API#

The browser↔server protocol (WebSocket message types, request fields, response shapes, error contract) is documented in docs/server-api.md.

Example scripts#

# Start the web viewer on an OS-assigned port
web_server

# Start on a fixed port
web_server -port 8080

Regression tests#

There are a set of regression tests in ./test.

bazel test //src/web/test/...

License#

BSD 3-Clause License. See LICENSE file.