Skip to content

Commit

Permalink
interactive: condense feature added and condense_pass list calculated…
Browse files Browse the repository at this point in the history
… dynamically! (3/7) (#1793)

Condense feature has been added. It is computed based on the
current_module (i.e. the output) and is recomputed every time a pass is
applied (i.e. the dynamic update we discussed).
  • Loading branch information
dshaaban01 authored Nov 17, 2023
1 parent f6a0f92 commit fb57655
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 19 deletions.
72 changes: 71 additions & 1 deletion tests/interactive/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import pytest

from xdsl.backend.riscv.lowering import convert_func_to_riscv_func
from xdsl.backend.riscv.lowering import (
convert_arith_to_riscv,
convert_func_to_riscv_func,
)
from xdsl.builder import ImplicitBuilder
from xdsl.dialects import arith, func, riscv, riscv_func
from xdsl.dialects.builtin import (
Expand All @@ -13,6 +16,14 @@
)
from xdsl.interactive.app import InputApp
from xdsl.ir import Block, Region
from xdsl.transforms import (
mlir_opt,
printf_to_llvm,
)
from xdsl.transforms.experimental import (
hls_convert_stencil_to_ll_mlir,
)
from xdsl.transforms.experimental.dmp import stencil_global_to_local
from xdsl.utils.exceptions import ParseError


Expand Down Expand Up @@ -136,6 +147,47 @@ async def test_buttons():
"""
)

await pilot.pause()
# assert that the Input and Output Text Area's have changed
assert (
app.input_text_area.text
== """
func.func @hello(%n : index) -> index {
%two = arith.constant 2 : index
%res = arith.muli %n, %two : index
func.return %res : index
}
"""
)
assert (
app.output_text_area.text
== """builtin.module {
func.func @hello(%n : index) -> index {
%two = arith.constant 2 : index
%res = arith.muli %n, %two : index
func.return %res : index
}
}
"""
)

# Test clicking the "clear input" button
await pilot.click("#clear_input_button")

# assert that the input text area has been cleared
await pilot.pause()
assert app.input_text_area.text == ""

app.input_text_area.insert(
"""
func.func @hello(%n : index) -> index {
%two = arith.constant 2 : index
%res = arith.muli %n, %two : index
func.return %res : index
}
"""
)

# Select a pass
app.pass_pipeline = tuple(
(*app.pass_pipeline, convert_func_to_riscv_func.ConvertFuncToRiscvFuncPass)
Expand Down Expand Up @@ -194,6 +246,24 @@ async def test_buttons():
assert isinstance(app.current_module, ModuleOp)
assert app.current_module.is_structurally_equivalent(expected_module)

# press "Condense" button
await pilot.click("#condense_button")

condensed_list = tuple(
(
convert_arith_to_riscv.ConvertArithToRiscvPass,
convert_func_to_riscv_func.ConvertFuncToRiscvFuncPass,
stencil_global_to_local.DistributeStencilPass,
hls_convert_stencil_to_ll_mlir.HLSConvertStencilToLLMLIRPass,
mlir_opt.MLIROptPass,
printf_to_llvm.PrintfToLLVM,
)
)

await pilot.pause()
assert app.condense_mode is True
assert app.available_pass_list == condensed_list


@pytest.mark.asyncio()
async def test_passes():
Expand Down
93 changes: 76 additions & 17 deletions xdsl/interactive/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from textual.reactive import reactive
from textual.widgets import Button, Footer, Label, ListItem, ListView, TextArea

from xdsl.dialects import builtin
from xdsl.dialects.builtin import ModuleOp
from xdsl.ir import MLContext
from xdsl.parser import Parser
Expand All @@ -28,6 +29,30 @@
"""Contains the list of xDSL passes."""


def condensed_pass_list(input: builtin.ModuleOp) -> tuple[type[ModulePass], ...]:
"""Returns a tuple of passes (pass name and pass instance) that modify the IR."""

ctx = MLContext(True)

for dialect in get_all_dialects():
ctx.load_dialect(dialect)

selections: tuple[type[ModulePass], ...] = ()
for _, value in ALL_PASSES:
try:
cloned_module = input.clone()
cloned_ctx = ctx.clone()
value().apply(cloned_ctx, cloned_module)

if not input.is_structurally_equivalent(cloned_module):
rhs = (*selections, value)
selections = tuple(rhs)
except Exception:
selections = tuple((*selections, value))

return selections


class OutputTextArea(TextArea):
"""Used to prevent users from being able to alter the Output TextArea."""

Expand Down Expand Up @@ -55,6 +80,11 @@ class InputApp(App[None]):
pass_pipeline = reactive(tuple[type[ModulePass], ...])
"""Reactive variable that saves the list of selected passes."""

condense_mode = reactive(False, always_update=True)
"""Reactive boolean."""
available_pass_list = reactive(tuple[type[ModulePass], ...])
"""Reactive variable that saves the list of passes that have an effect on current_module."""

input_text_area: TextArea
"""Input TextArea."""
output_text_area: OutputTextArea
Expand Down Expand Up @@ -83,6 +113,7 @@ def compose(self) -> ComposeResult:
with Vertical(id="buttons"):
yield Button("Copy Query", id="copy_query_button")
yield Button("Clear Passes", id="clear_passes_button")
yield Button("Condense", id="condense_button")
with ScrollableContainer(id="selected_passes"):
yield self.selected_query_label
with Horizontal(id="bottom_container"):
Expand All @@ -94,6 +125,47 @@ def compose(self) -> ComposeResult:
yield Button("Copy Output", id="copy_output_button")
yield Footer()

def on_mount(self) -> None:
"""Configure widgets in this application before it is first shown."""

# register's the theme for the Input/Output TextArea's
self.input_text_area.theme = "vscode_dark"
self.output_text_area.theme = "vscode_dark"

self.query_one("#input_container").border_title = "Input xDSL IR"
self.query_one("#output_container").border_title = "Output xDSL IR"
self.query_one(
"#passes_list_view"
).border_title = "Choose a pass or multiple passes to be applied."
self.query_one("#selected_passes").border_title = "Selected passes/query"

for n, _ in ALL_PASSES:
self.passes_list_view.append(ListItem(Label(n), name=n))

def compute_available_pass_list(self) -> tuple[type[ModulePass], ...]:
match self.current_module:
case None:
return tuple(p for _, p in ALL_PASSES)
case Exception():
return ()
case ModuleOp():
if self.condense_mode:
return condensed_pass_list(self.current_module)
else:
return tuple(p for _, p in ALL_PASSES)

def watch_available_pass_list(
self,
old_pass_list: tuple[type[ModulePass], ...],
new_pass_list: tuple[type[ModulePass], ...],
) -> None:
if old_pass_list != new_pass_list:
self.passes_list_view.clear()
for value in new_pass_list:
self.passes_list_view.append(
ListItem(Label(value.name), name=value.name)
)

@on(ListView.Selected)
def update_pass_pipeline(self, event: ListView.Selected) -> None:
"""
Expand Down Expand Up @@ -155,23 +227,6 @@ def watch_current_module(self):

self.output_text_area.load_text(output_text)

def on_mount(self) -> None:
"""Configure widgets in this application before it is first shown."""

# register's the theme for the Input/Output TextArea's
self.input_text_area.theme = "vscode_dark"
self.output_text_area.theme = "vscode_dark"

self.query_one("#input_container").border_title = "Input xDSL IR"
self.query_one("#output_container").border_title = "Output xDSL IR"
self.query_one(
"#passes_list_view"
).border_title = "Choose a pass or multiple passes to be applied."
self.query_one("#selected_passes").border_title = "Selected passes/query"

for n, _ in ALL_PASSES:
self.passes_list_view.append(ListItem(Label(n), name=n))

def action_toggle_dark(self) -> None:
"""An action to toggle dark mode."""
self.dark = not self.dark
Expand Down Expand Up @@ -202,6 +257,10 @@ def clear_passes(self, event: Button.Pressed) -> None:
"""Selected passes cleared when "Clear Passes" button is pressed."""
self.pass_pipeline = ()

@on(Button.Pressed, "#condense_button")
def condense(self, event: Button.Pressed) -> None:
self.condense_mode = True


def main():
return InputApp().run()
Expand Down
2 changes: 1 addition & 1 deletion xdsl/interactive/app.tcss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
height: 100%;
}

# Vertical(Button, Button)
# Vertical(Button, Button, Button)
#buttons{
layout: vertical;
width: auto;
Expand Down

0 comments on commit fb57655

Please sign in to comment.