This is the official API for Vaporview. This will remain stable for all future releases. Anything listed as a proposed API is subject to change. If you would like to see anything added to the API, please file an issue, or add it to the github discussions.
If you need help implementing an API feature into your extension, feel free to reach out to me directly or hop on matrix chat.
Planned updates to the API
- More commands
- Custom name translations
- Custom transactions
- URI schema for netlist elements
One point of caution is that the instance path can vary depending on tools used to elaborate the RTL, so there may be small changes made to how instance paths are listed. Please let me know if you run into any issues reconciling instance paths!
Vaporview is designed with the VSCode IDE experience in mind, so this document serves to help enable extension interoperability. This document outlines vaporview command subscriptions, and commands that are emitted.
- Custom context [right click] menu items
- Adding, removing, and selecting variables
- Placing markers
- Signal Value Links
- Drag and drop into viewer (proposed API)
Custom context [right click] menu commands can be added to vaporview components such as the netlist viewer and and waveform viewer, and those context menu items can call commands to other extensions.
Custom context menu items can be added to the waveform viewer webview. All attributes listed below are usable by when clause statements
- viewType: vaporview.waveformViewer
- package.json path: contributes.menus.webview/context
- when: activeCustomEditorId == 'vaporview.waveformViewer'
- 1_default
- Submenu vaporview.timeUnit
- Show Ruler Lines
- Hide Ruler Lines
- 1_waveform_settings
- Submenu vaporview.valueFormat - Value Format
- Submenu vaporview.valueColor - Render Type
- Submenu vaporview.renderType - Color
- 2_variables
- Show In Netlist View
- Remove Variable
- Copy Name
- Copy Value
- 3_groups
- New Group
- Rename Group
- 4_saveLoad
- Save Viewer Settings
- Load Viewer Settings
- 5_waveDrom
- Submenu vaporview.waveDrom - WaveDrom
All signals in the webview will emit the following attributes when right clicked on
- webviewSection - "signal"
- scopePath - Instance path (delimited by "." characters) without the variable name
- signalName - Variable or Scope Name
- type - this.rowItems[netlistId].variableType,
- width - BitVector Bit Width of Variable, will be 0 for Strings and Reals
- preventDefaultContextMenuItems - always true
- netlistId - Variable ID in waveform dump file
Context menu items can be added to the netlist view and displayed signals view. View IDs are listed below. Tree Item [netlist element] attributes are also outlined. However, keep in mind that for constructing a conditional menu, keep in mind that only the contextValue can be used for when clause statements. However, when a command is called, all attributes are visible in an event object if passed into the first argument of the command handler function.
See Tree Item API docs for details
- ID: waveformViewerNetlistView
- package.json path: contributes.menus.view/item/context
- when: view == 'waveformViewerNetlistView'
- 1_default
- Add Selected
- Remove Selected
- Add all in Scope
- Add all in Scope (Recursive)
- Remove all in Scope
- Show in Viewer
- Copy Name
- 2_addVariable
- Add Variable By Name
- 3_saveLoad
- Save Viewer Settings
- Load Viewer Settings
- 4_reload
- Reload File
Note: Tree items in both the Netlist View and the Displayed Signals View have the same set of attributes.
- contextValue - "netlistVar" | "netlistScope" - see Tree Item API docs and scroll down to the contextValue section.
- collapsibleState - VScode Tree Item Collapsible State
- children - Child Netlist Elements
- iconPath - VScode Tree Item Icon Path
- tooltip - Tooltip Text
- label - VScode Tree Item Label
- name - Variable or Scope Name
- scopePath - Instance path without the variable name (delimited by "." characters)
- type - Variable Type or Scope Type.
- encoding - "BitVector" | "Real" | "String" | "none"
- width - (BitVector only) Bit Width of Variable
- msb - (BitVector only) Most Significant Bit
- lsb - (BitVector only) Least Significant Bit
- numberFormat - (BitVector only) Bit Vector Number format
- netlistId - Variable ID in waveform dump file
- signalId - Value Change Data index in waveform dump file
- fsdbVarLoaded - FSDB only attribute
- scopeOffsetIdx - FSDB only attribute
In an attempt to future proof and maintain compatibility with any potential future waveform viewers, most public commands will be prefixed with the "waveformViewer" prefix instead of "vaporview". Commands listed in this API may take in arguments, which will usually be an object with the arguments named. This is to maintain compatibility with any context menu items.
Note that this is not an exhaustive list of input commands in Vaporview, however once the API is finalized for 1.4, these commands come with a guarantee that nothing will be removed from the schema. In other words, there will be no changes to these commands that might otherwise break another extension.
Opens a file with vaporview
- uri - Document URI
- loadAll - true | false - if set to true, will load all variables into the viewport
- maxSignals - abort loading all variables if netlist contains more than this number of variables. This value will be limited to 64. If this value is not specified, it will default to 64.
This command takes the URI to a waveform dump file.
Add a variable to the viewer. If a scope is specified, it will add all of the scope children to the viewer.
- uri - (Optional) Document URI - if not defined, this function will use the currently active, or last active document
- netlistId - (Optional*) Waveform Dump File Variable ID
- instancePath - (Optional*) Full instance path for variable
- scopePath - (Optional*) - Variable module math without variable name
- name - (Optional*) - Variable name
- msb - (Optional) - Most Significant Bit
- lsb - (Optional) - Least Significant Bit
- recursive - (optional) - If a path to a scope is specified, it will recursively add all of the children if set to true
- reveal - (Optional) - If the variable is already displayed, it will select it instead of adding another instance. Note that this only applies to netlist variables.
Note that a variable must be specified with at least of the following set of keys, and priority is as follows:
- netlistId
- instancePath
- scopePath AND name
Remove a variable from the viewer
- uri - (Optional) Document URI - if not defined, this function will use the currently active, or last active document
- netlistId - (Optional*) Waveform Dump File Variable ID
- instancePath - (Optional*) Full instance path for variable
- scopePath - (Optional*) - Variable module math without variable name
- name - (Optional*) - Variable name
- msb - (Optional) - Most Significant Bit
- lsb - (Optional) - Least Significant Bit
Note that a variable must be specified with at least of the following set of keys, and priority is as follows:
- netlistId
- instancePath
- scopePath AND name
Reveal a variable or scope in the netlist view
- uri - (Optional) Document URI - if not defined, this function will use the currently active, or last active document
- netlistId - (Optional*) Waveform Dump File Variable ID
- instancePath - (Optional*) Full instance path for variable or scope
- scopePath - (Optional*) - Variable module math without target variable or scope name
- name - (Optional*) - Variable or Scope name
Note that a variable or scope must be specified with at least of the following set of keys, and priority is as follows:
- netlistId
- instancePath
- scopePath AND name
Set the marker or alt marker to a time in the viewer
- uri - (Optional) Document URI - if not defined, this function will use the currently active, or last active document
- time - Target Time
- units - (Optional) Time Unit - If not specified, will default to waveform dump format time units "fs" | "ps" | "ns" | "us" | "µs" | "ms" | "s" | "ks"
- markerType - (Optional) Marker Type - 0: Main Marker, 1: Alt Marker
Returns a list of open waveform viewer documents
Remember that to get a valid return value, all vscode commands must be called with an await keyword!
- documents - List of URIs corresponding to open documents
- lastActiveDocument - URI of last active or currently active waveform viewer document
Returns the viewer settings in the same schema as the save file
- uri - (Optional) Document URI - if not defined, this function will use the currently active, or last active document
- uri - (Optional) Document URI - if not defined, this function will use the currently active, or last active document
- time - (optional) if not defined, will use marker time for the document
- instancePaths - Array of instance path strings
- instancePath - Instance path string
- value - Array of values length 1 or 2 [current value] or [previous value, current value]
Note that if an instance path input is not found in the netlist, the result will not return a value for it.
Vaporview emits events when users perform actions in the viewer. If there's anything you wish to see added to this list, please comment on the github issues page.
All events are emitted regardless of their source action - click, key press, or external action.
Emitted when the marker changes value in the viewer.
- uri - uri
- time - number
- units - string
Emitted when a signal is selected by either the user, or externally
- uri - uri
- instancePath - string[]
- netlistId - number[]
- source - "netlistView" | "viewer"
Emitted when a variable is added to the viewer
- uri - uri
- instancePath - string[]
- netlistId - number[]
Emitted when a variable is removed from the viewer
- uri - uri
- instancePath - string[]
- netlistId - number[]
Emitted when an unknown tree item is dragged into the viewer. The resourceUriList will contain all unknown URIs of tree items. This event is only emitted if the dataTransfer contains more than one unknown URI, and all known URIs (netlist items, and eventually config files) will be filtered out of the resourceUriList to prevent erroneous events from being emitted. The event also emits the location (group path and index) of where in the viewport the item was dropped, so that if the dropped item refers to a variable item, it can be placed accordingly.
- uri - string
- resourceUriList - uri[]
- groupPath - string[]
- index - number
This would likely go in your activate() function
// Check if Vaporview extension is installed
const vaporviewExtension = vscode.extensions.getExtension('lramseyer.vaporview');
if (!vaporviewExtension) {
console.log('Vaporview extension not found - integration disabled');
return;
}
// Wait for Vaporview to activate (if not already)
if (!vaporviewExtension.isActive) {
await vaporviewExtension.activate();
}
// Get the Vaporview API
const vaporviewApi = vaporviewExtension.exports;
if (!vaporviewApi) {
console.log('Vaporview API not available - onDidSelectSignal not found');
return;
}
// Event handler subscription
const subscription = vaporviewApi.onDidSelectSignal(async (event: any) => {
const uri = event.uri
const instancePath = event.instancePath;
const source = event.source;
// Your handler code would go here
});
context.subscriptions.push(subscription);Something that has been in my roadmap for a while is the ability to "Allow users to link .objdump files to a program counter value for a more integrated debug experience" This was something I wanted when I first created vaporview (because I was debugging a CPU with no GDB or ETM tracing.) How cool would it be to debug a CPU with a waveform dump and actually connect it back to the line of code it's running? In brainstorming how to implement it, I have a proposed solution, but it's actually a more general solution.
Signals will have the ability to have links added to them such that when a user clicks on a value, it will emit a custom command that other extension developers can call. Any command can be attached to a Signal. When that command is emitted, it will include an argument, which will be an object with the attributes listed below.
A submenu or menu group will be added for Signal Item context menu, and it will be up to the extension developer to contribute a menu item to add their custom command
- netlistId - Variable ID in waveform dump file
- scopePath - Instance path (delimited by "." characters) without the variable name
- signalName - Variable or Scope Name
- type - this.rowItems[netlistId].variableType,
- width - BitVector Bit Width of Variable, will be 0 for Strings and Reals
- encoding - "BitVector" | "Real" | "String" | "none"
- numberFormat - Number format
- value - Value as Bit Vector
- formattedValue - Encoded value
- time - Time of value change
- uri - (Optional) Document URI - if not defined, this function will use the currently active, or last active document
- command - custom command that will be called when clicked
- netlistId - (Optional*) Waveform Dump File Variable ID - note that this will be emitted by the context menu command, so developers will have this value
- instancePath - (Optional*) Full instance path for variable
- scopePath - (Optional*) - Variable module math without variable name
- name - (Optional*) - Variable name
- msb - (Optional) - Most Significant Bit
- lsb - (Optional) - Least Significant Bit
Note that a variable must be specified with at least of the following set of keys, and priority is as follows:
- netlistId
- instancePath
- scopePath AND name
package.json
"contributes": {
"menus": {
...
"webview/context": [
...
{
"command": "myExtension.addLinkForValues",
"when": "viewItem == 'netlistVar'",
"group": "0_links"
},
...
]
},
...
{
"commands": [
{
"command": "myExtension.addLinkForValues",
"Title": "Link Signal Values"
}
]
}
}extension.ts
// Register command for the context menu item
const disposable_1 = vscode.commands.registerCommand(
'myExtension.addLinkForValues',
(e) => {
const args = {
netlistId: e.netlistId
e.command: 'myExtension.clickSignalValueLink'
}
vscode.commands.executeCommand('waveformViewer.addSignalValueLink', args);
}
);
// Register custom command that will be emitted by Signal Value Link
const disposable_2 = vscode.commands.registerCommand(
'myExtension.clickSignalValueLink',
(e) => {onDidClickSignalValueLink(e)}
)Vaporview will start supporting URIs to navigate within the viewer. It will use the scheme waveform to denote that it is a waveform document. Much like how VScode supports fragments to select lines and ranges of lines, vaporview schemes will support time values, time ranges, and instance paths of signals. All tree items in the netlist view will contain their respective URIs as the resourceUri field, and support drag and drop. This way, if you want your extension to support dragging and dropping netlist items, you can.
The fragment of the URI can contain an instance path, time value, or time range, and will be delimited by an "&"
Time and Time ranges will be encoded as t:5000 or t:4000ns (units are optional) for a time range, use a dash to delimit
Instance Path is encoded as net:top.scope.signal
Note tha this is a proposal, which does not reflect the actual file format. I plan to coordinate with the Surfer team to standardize on a format, and this outlines the things I would want for vaporview.
- Nested set of dividers
- Main Marker
- Alt Marker
- Item type - Signal | Group | Transaction | Other?
- Type - Signal
- Instance Path
- Number Format - ie hex, decimal, binary
- Text justify - Left | right | center
- Render type - binary | multi-bit | linear | stepped | etc
- Pin location - top | bottom
- Color (preferably an index to adapt to color themes)
- Background Color
- Value Link Command
- Type - Group
- Array of items
- Type - Transaction
- Transaction Type
- Arguments - Array of Signals