diff --git a/docs/Design.md b/docs/Design.md index 9ac288d6..153aa7d2 100644 --- a/docs/Design.md +++ b/docs/Design.md @@ -17,9 +17,9 @@ One of the main ideas behind Exo is **exocompilation**, which allows users to de - The cost of adding support for new hardware is significantly reduced. - Proprietary details of hardware can be protected. -Users can model custom memories, instructions, and configuration state in libraries to target a specific accelerator. These hardware abstractions can then be used to write hand-optimized code or as building blocks for higher-level scheduling transformations. +Users can model custom [memories](./memories.md), [instructions](./instructions.md), and configuration state in libraries to target a specific accelerator. These hardware abstractions can then be used to write hand-optimized code or as building blocks for higher-level scheduling transformations. -More info can be found in the [PLDI paper](https://people.csail.mit.edu/yuka/pdf/exo_pldi2022_full.pdf) and [instructions.md](./instructions.md) and [memories.md](./memories.md). +More info can be found in the [PLDI paper](https://people.csail.mit.edu/yuka/pdf/exo_pldi2022_full.pdf), [instructions.md](./instructions.md), and [memories.md](./memories.md). ## Fine-Grained Primitives for Performance Control @@ -45,7 +45,8 @@ The rewrite-based approach offers several advantages: While the flexibility of fine-grained primitives is necessary for achieving peak performance, directly using them can be verbose and laborious. To address this, Exo allows users to define new higher-level scheduling operations by composing the core primitives. -These user-defined scheduling operations can encapsulate common optimization patterns and hardware-specific transformations, greatly improving productivity. They can be put together in reusable libraries, further enabling modularity and portability. +These user-defined scheduling operations can encapsulate common optimization patterns and hardware-specific transformations such as auto-vectorize, tiling, and even simulate scheduling operations from other USLs (like Halide's `compute_at`). +They can be put together in reusable libraries, further enabling modularity and portability. More infomation can be found in the [ASPLOS paper](.) and [Cursor.md](./Cursor.md). @@ -53,8 +54,8 @@ More infomation can be found in the [ASPLOS paper](.) and [Cursor.md](./Cursor.m We identified that Action, Inspection, and Reference are the key scheduling language design mechanisms that enable user-defined scheduling operations. -- **Actions** are the scheduling primitives that transform the code (e.g., `divide_loop`, `reorder`). -- **Inspections** query properties of the code (e.g., loop bounds, memory access patterns). +- **[Actions](./primitives)** are scheduling operations that transform the code. This could be compiler-provided *primitive actions* (e.g., `divide_loop`, `reorder`), or *user-defined* (e.g., tile2D in the ASPLOS paper). +- **[Inspections](./inspection.md)** query properties of the code (e.g., loop bounds, memory access patterns). - **References** point to specific parts of the code to apply actions to. Together, AIR allows scheduling operations to be defined as composable rewrites on the code. The language implementation guarantees the correctness of these primitive rewrites with a set of effect analyses. diff --git a/docs/Imports.md b/docs/Imports.md index 81cbd65c..f5385c8f 100644 --- a/docs/Imports.md +++ b/docs/Imports.md @@ -2,6 +2,9 @@ This document provides an overview of the imports used when writing Exo. +Exo's parser only resolves names in the local and global namespaces, and Exo reserves the attribute syntax (foo.bar) for configurations. +Therefore, if users wish to utilize Exo constructs, they must import them into their local namespace. + ## Table of Contents 1. [Standard Python Future Import](#1-standard-python-future-import) diff --git a/docs/README.md b/docs/README.md index 64e4fa60..b7d4c537 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,7 +5,8 @@ This directory provides detailed documentation about Exo's interface and interna - To learn about the design principles of Exo, read [Design.md](Design.md). - To understand how the Exo system is implemented, read [System.md](System.md). - For information on writing Exo object code, APIs, and imports, refer to [Procedures.md](Procedures.md), [object_code.md](object_code.md), and [Imports.md](Imports.md). -- To learn how to define memory, instructions, and externs externally to the compiler in the user code, refer to [externs.md](externs.md), [instructions.md](instructions.md), and [memories.md](memories.md). +- To learn how to define **hardware targets externally to the compiler**, refer to [externs.md](externs.md), [instructions.md](instructions.md), and [memories.md](memories.md). +- To learn how to define **new scheduling operations externally to the compiler**, refer to [Cursors.md](./Cursors.md) and [inspection.md](./inspection.md). - To understand the available scheduling primitives and how to use them, look into the primitives/ directory. The scheduling primitives are classified into six categories: diff --git a/docs/inspection.md b/docs/inspection.md new file mode 100644 index 00000000..8760ede4 --- /dev/null +++ b/docs/inspection.md @@ -0,0 +1,50 @@ +# External Inspection Functions + +Inspection is a metaprogramming feature that enables metaprograms (like schedules) to dynamically examine the properties of object code. Exo provides inspection through [Cursors](./Cursors.md), allowing users to examine standard AST properties such as variable names, literal expression values, and annotations (e.g., memory spaces and precisions) at scheduling time. Cursors also support local AST navigation, for example, accessing loop bounds (`loop.hi()`) and bodies (`loop.body()`). Inspection functions can be written externally from the Exo compiler, giving users the ability to customize them according to their needs. +For convinience, standard library inspection functions are provided as `exo.stdlib.inspection` module. + +Cursor types (such as `ForCursor` and `IfCursor`) are defined in `exo.API_cursors`, so you should import it when writing inspection functions: + +```python +from exo.API_cursors import * +``` + +Here are some simple inspection functions: + +```python +def is_loop(proc, loop): + loop = proc.forward(loop) + return isinstance(loop, ForCursor) + +def get_top_level_stmt(proc, c): + c = proc.forward(c) + + while not isinstance(c.parent(), InvalidCursor): + c = c.parent() + return c +``` + +Explanation: +- The `is_loop` function takes a `proc` object and a `loop` cursor as input. It forwards the `loop` cursor using `proc.forward(loop)` and checks if the resulting cursor is an instance of `ForCursor`. This function determines whether the given cursor points to a loop statement. +- The `get_top_level_stmt` function takes a `proc` object and a cursor `c` as input. It forwards the cursor `c` using `proc.forward(c)` and then iteratively moves the cursor to its parent using `c.parent()` until it reaches an `InvalidCursor`, which means the cursor reached the outer-most level of the procedure. This function finds the top-level statement that wraps the given cursor. + +Exo also exposes `ExoType` for expression types (defined in `src/exo/API_types.py`), which users can access using constructs like `ExoType.F16` and branch on it. + +```python +class ExoType(Enum): + F16 = auto() + F32 = auto() + F64 = auto() + UI8 = auto() + I8 = auto() + UI16 = auto() + I32 = auto() + R = auto() + Index = auto() + Bool = auto() + Size = auto() + Int = auto() + Stride = auto() +``` + +All the Cursor types and the kind of navigation you can perform on them are documented in [Cursors.md](./Cursors.md).