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
10 changes: 0 additions & 10 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,6 @@ <h3>Tensor Shape</h3>

<div class="controls" data-controls></div>

<div id="cell-info" class="cell-info">
<h3>Cell Info</h3>
<div id="cell-info-content"></div>
</div>
</aside>

<main class="visualization">
Expand Down Expand Up @@ -164,16 +160,10 @@ <h3>Operand</h3>

<div id="wmma-validation-errors" class="validation-errors"></div>
<div id="wmma-validation-warnings" class="validation-warnings"></div>

<button type="submit">Update Visualization</button>
</form>

<div class="controls" data-controls></div>

<div id="wmma-cell-info" class="cell-info">
<h3>Cell Info</h3>
<div id="wmma-cell-info-content"></div>
</div>
</aside>

<main class="visualization">
Expand Down
16 changes: 0 additions & 16 deletions src/main.tabs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,6 @@ const setupDom = () => {
controls.setAttribute('data-controls', '')
sidebar.appendChild(controls)

const cellInfo = document.createElement('div')
cellInfo.id = 'cell-info'
const cellInfoContent = document.createElement('div')
cellInfoContent.id = 'cell-info-content'
cellInfoContent.innerHTML = '<p>Hover over a cell to see details</p>'
cellInfo.appendChild(cellInfoContent)
sidebar.appendChild(cellInfo)

contentWrapper.appendChild(sidebar)
contentWrapper.appendChild(createVisualizationSection('canvas'))

Expand Down Expand Up @@ -239,14 +231,6 @@ const setupDom = () => {
controls.setAttribute('data-controls', '')
sidebar.appendChild(controls)

const cellInfo = document.createElement('div')
cellInfo.id = 'wmma-cell-info'
const cellInfoContent = document.createElement('div')
cellInfoContent.id = 'wmma-cell-info-content'
cellInfoContent.innerHTML = '<p>Hover over a cell to see details</p>'
cellInfo.appendChild(cellInfoContent)
sidebar.appendChild(cellInfo)

contentWrapper.appendChild(sidebar)
contentWrapper.appendChild(createVisualizationSection('wmma-canvas'))

Expand Down
17 changes: 0 additions & 17 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -146,23 +146,6 @@ button:active {
padding: 0.25rem 0;
}

.cell-info {
margin-top: 1.5rem;
padding-top: 1.5rem;
border-top: 1px solid #eee;
}

#cell-info-content {
padding: 1rem;
background-color: #f8f9fa;
border-radius: 4px;
font-size: 0.85rem;
}

#cell-info-content p {
margin: 0.25rem 0;
}

.validation-errors,
.validation-warnings {
margin-bottom: 1rem;
Expand Down
19 changes: 3 additions & 16 deletions src/tabs/BlockLayoutTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,11 @@ export class BlockLayoutTab extends CanvasTab {
}
const resetButton = renderSharedControls(controlsContainer, { resetButtonId: 'reset' })

const cellInfoContent = tabContent.querySelector('#cell-info-content')
if (!(cellInfoContent instanceof HTMLElement)) {
throw new Error('BlockLayoutTab cell info content not found')
}

const elements: CanvasTabElements = {
root: tabContent,
canvas,
visualizationContainer,
resetButton,
cellInfoContent,
}

super(elements)
Expand Down Expand Up @@ -89,7 +83,7 @@ export class BlockLayoutTab extends CanvasTab {
protected handleHover(event: MouseEvent): void {
const renderer = this.getRenderer()
if (!renderer) {
this.resetCellInfoContent()
this.hideTooltip()
return
}

Expand All @@ -101,18 +95,11 @@ export class BlockLayoutTab extends CanvasTab {
const cellInfo = renderer.getCellInfo(gridPos.row, gridPos.col)

if (!cellInfo) {
this.resetCellInfoContent()
this.hideTooltip()
return
}

const warpColor = renderer.getWarpColor(cellInfo.warpId)
this.setCellInfoContent(`
<p><strong>Position:</strong> (${cellInfo.position[0]}, ${cellInfo.position[1]})</p>
<p><strong>Thread ID:</strong> ${cellInfo.threadId}</p>
<p><strong>Register ID:</strong> ${cellInfo.registerId}</p>
<p><strong>Warp ID:</strong> ${cellInfo.warpId}</p>
`)

const tooltipContent = `
<div><strong>Logical Index:</strong> (${cellInfo.position[0]}, ${cellInfo.position[1]})</div>
Expand All @@ -127,9 +114,9 @@ export class BlockLayoutTab extends CanvasTab {
}

/**
* Reset hover state to the default cell info message.
* Reset hover state when the pointer leaves the canvas.
*/
protected resetHover(): void {
this.resetCellInfoContent()
this.hideTooltip()
}
}
33 changes: 2 additions & 31 deletions src/tabs/CanvasTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ export interface CanvasTabElements {
canvas: HTMLCanvasElement
visualizationContainer: HTMLElement
resetButton: HTMLButtonElement
cellInfoContent: HTMLElement
defaultCellInfoMessage?: string
}

/**
Expand All @@ -19,19 +17,16 @@ export abstract class CanvasTab {
protected readonly tooltip = new Tooltip()

private readonly elements: CanvasTabElements
private readonly cellInfoDefaultMessage: string
private isDragging = false
private isActive = false
private keyboardListener: ((event: KeyboardEvent) => void) | null = null

protected constructor(elements: CanvasTabElements) {
this.elements = elements
this.cellInfoDefaultMessage = elements.defaultCellInfoMessage ?? 'Hover over a cell to see details'

this.validateElements()
this.setupResetButton()
this.setupCanvasInteractions()
this.resetCellInfoContent()
}

/**
Expand Down Expand Up @@ -86,13 +81,6 @@ export abstract class CanvasTab {
return this.elements.canvas
}

/**
* Provide subclasses with access to the cell info container element.
*/
protected get cellInfoContent(): HTMLElement {
return this.elements.cellInfoContent
}

/**
* Replace the current renderer instance.
*/
Expand All @@ -113,7 +101,7 @@ export abstract class CanvasTab {
protected abstract handleHover(event: MouseEvent): void

/**
* Reset hover state, clearing cell info/tooltips as needed.
* Reset hover state when the pointer leaves the canvas.
*/
protected abstract resetHover(): void

Expand Down Expand Up @@ -158,20 +146,6 @@ export abstract class CanvasTab {
this.canvas.height = height
}

/**
* Update the cell info pane with new HTML content.
*/
protected setCellInfoContent(content: string): void {
this.cellInfoContent.innerHTML = content
}

/**
* Reset the cell info pane to the default message.
*/
protected resetCellInfoContent(): void {
this.cellInfoContent.innerHTML = `<p>${this.cellInfoDefaultMessage}</p>`
}

/**
* Hide the shared tooltip.
*/
Expand All @@ -180,7 +154,7 @@ export abstract class CanvasTab {
}

private validateElements(): void {
const { root, canvas, visualizationContainer, resetButton, cellInfoContent } = this.elements
const { root, canvas, visualizationContainer, resetButton } = this.elements
if (!root) {
throw new Error('CanvasTab root element not provided')
}
Expand All @@ -193,9 +167,6 @@ export abstract class CanvasTab {
if (!resetButton) {
throw new Error('CanvasTab reset button not provided')
}
if (!cellInfoContent) {
throw new Error('CanvasTab cell info container not provided')
}
}

private setupResetButton(): void {
Expand Down
36 changes: 12 additions & 24 deletions src/tabs/WMMALayoutTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import { CanvasTab, type CanvasTabElements } from './CanvasTab'
* managing WMMA-specific form inputs and metadata.
*/
export class WMMALayoutTab extends CanvasTab {
private readonly form: HTMLFormElement
private readonly architectureSelect: HTMLSelectElement
private readonly instructionSelect: HTMLSelectElement
private readonly operandSelect: HTMLSelectElement
Expand Down Expand Up @@ -58,11 +57,6 @@ export class WMMALayoutTab extends CanvasTab {
}
const resetButton = renderSharedControls(controlsContainer, { resetButtonId: 'wmma-reset' })

const cellInfoContent = tabContent.querySelector('#wmma-cell-info-content')
if (!(cellInfoContent instanceof HTMLElement)) {
throw new Error('WMMALayoutTab cell info content not found')
}

const form = tabContent.querySelector('#wmmaForm')
if (!(form instanceof HTMLFormElement)) {
throw new Error('WMMALayoutTab form element not found')
Expand All @@ -88,29 +82,28 @@ export class WMMALayoutTab extends CanvasTab {
canvas,
visualizationContainer,
resetButton,
cellInfoContent,
}

super(elements)

this.form = form
this.architectureSelect = architectureSelect
this.instructionSelect = instructionSelect
this.operandSelect = operandSelect

this.setupEventListeners()
this.populateInstructionOptions()
this.updateVisualization()
}

/**
* WMMA tabs reuse the base keyboard shortcuts without modification.
*/

/**
* Ensure hover state resets to the default message on exit.
* Ensure hover state resets when the pointer leaves the canvas.
*/
protected resetHover(): void {
this.resetCellInfoContent()
this.hideTooltip()
}

/**
Expand All @@ -119,7 +112,7 @@ export class WMMALayoutTab extends CanvasTab {
protected handleHover(event: MouseEvent): void {
const renderer = this.getRenderer()
if (!renderer) {
this.resetCellInfoContent()
this.hideTooltip()
return
}

Expand All @@ -131,7 +124,6 @@ export class WMMALayoutTab extends CanvasTab {
const cellInfo = renderer.getCellInfo(gridPos.row, gridPos.col)

if (!cellInfo) {
this.resetCellInfoContent()
this.hideTooltip()
return
}
Expand All @@ -152,14 +144,6 @@ export class WMMALayoutTab extends CanvasTab {
elementLabel = elementIndex.toString()
}

const infoLines = [
`<p><strong>Logical Index:</strong> ${logicalIndex}</p>`,
`<p><strong>Thread:</strong> ${cellInfo.threadId}</p>`,
`<p><strong>Register:</strong> ${registerLabel}</p>`,
`<p><strong>Bit Range:</strong> ${bitRangeLabel}</p>`,
`<p><strong>Element:</strong> ${elementLabel}</p>`,
]

const tooltipLines = [
`<div><strong>Logical Index:</strong> ${logicalIndex}</div>`,
`<div><strong>Thread:</strong> ${cellInfo.threadId}</div>`,
Expand All @@ -168,19 +152,23 @@ export class WMMALayoutTab extends CanvasTab {
`<div><strong>Element:</strong> ${elementLabel}</div>`,
]

this.setCellInfoContent(infoLines.join(''))
this.tooltip.show(tooltipLines.join(''), event.clientX, event.clientY)
}

private setupEventListeners(): void {
this.architectureSelect.addEventListener('change', () => {
this.populateInstructionOptions()
this.updateVisualization()
})

this.instructionSelect.addEventListener('change', () => {
this.updateVisualization()
})

this.form.addEventListener('submit', (event) => {
event.preventDefault()
this.operandSelect.addEventListener('change', () => {
this.updateVisualization()
})

}

private populateInstructionOptions(): void {
Expand All @@ -199,7 +187,7 @@ export class WMMALayoutTab extends CanvasTab {
this.instructionSelect.appendChild(option)
})

this.updateVisualization()
this.instructionSelect.selectedIndex = 0
}

private getParams(): WMMALayoutParams {
Expand Down
30 changes: 16 additions & 14 deletions tests/visualization.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,25 +112,27 @@ test.describe('Triton Layout Visualizer', () => {
await page.locator('#reset').click()
})

test('should display cell info on hover', async ({ page }) => {
test('should show tooltip when hovering WMMA cells', async ({ page }) => {
await page.goto('/')

const canvas = page.locator('#canvas')
const cellInfo = page.locator('#cell-info-content')
// Switch to the WMMA layout tab
await page.locator('#tab-wmma-layout').click()

const canvas = page.locator('#wmma-canvas')
await expect(canvas).toBeVisible()

// Initially should show placeholder
await expect(cellInfo).toContainText('Hover over a cell')
// Allow the WMMA visualization to render before hovering
await page.waitForTimeout(200)

// Hover over canvas
// Hover near the center of the canvas to trigger the tooltip
const box = await canvas.boundingBox()
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2)
await page.waitForTimeout(100)

// Cell info should update
const text = await cellInfo.textContent()
expect(text).toBeTruthy()
}
expect(box).not.toBeNull()
await page.mouse.move(box!.x + box!.width / 2, box!.y + box!.height / 2)

// Tooltip should appear with WMMA metadata content
const tooltip = page.locator('.layout-tooltip').filter({ hasText: 'Logical Index:' })
await expect(tooltip).toBeVisible()
await expect(tooltip).toContainText('Thread:')
})

test('should take visual snapshot', async ({ page }) => {
Expand Down