mirror of
https://github.com/tinygrad/tinygrad.git
synced 2026-08-18 05:58:28 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19c0e4a11d |
@@ -225,12 +225,14 @@ runs:
|
||||
if: inputs.amd == 'true' && runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: |
|
||||
cargo build --release --manifest-path ./extra/remu/Cargo.toml
|
||||
sudo ln -sf ${{ github.workspace }}/extra/remu/target/release/libremu.so /usr/local/lib/libremu.so
|
||||
sudo tee --append /etc/ld.so.conf.d/rocm.conf <<'EOF'
|
||||
/opt/rocm/lib
|
||||
/opt/rocm/lib64
|
||||
EOF
|
||||
sudo ldconfig
|
||||
- name: Setup AMD comgr (macOS)
|
||||
- name: Setup AMD comgr+remu (macOS)
|
||||
if: inputs.amd == 'true' && runner.os == 'macOS'
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -238,6 +240,7 @@ runs:
|
||||
curl -s -H "Authorization: token $GH_TOKEN" curl -s https://api.github.com/repos/tinygrad/amdcomgr_dylib/releases/latest | \
|
||||
jq -r '.assets[] | select(.name == "libamd_comgr.dylib").browser_download_url' | \
|
||||
sudo xargs curl -fL -o /usr/local/lib/libamd_comgr.dylib
|
||||
cargo build --release --manifest-path ./extra/remu/Cargo.toml
|
||||
|
||||
# **** gpuocelot ****
|
||||
|
||||
|
||||
@@ -71,6 +71,10 @@ jobs:
|
||||
uv venv /tmp/tinygrad_pytest_ci
|
||||
source /tmp/tinygrad_pytest_ci/bin/activate
|
||||
uv pip install .[testing]
|
||||
- name: setup other stuff
|
||||
run: |
|
||||
mkdir -p extra/remu/target/release/
|
||||
ln -s ~/tinygrad/extra/remu/target/release/libremu.so extra/remu/target/release/libremu.so
|
||||
- name: setup staging db
|
||||
run: |
|
||||
echo "CACHEDB=/tmp/pytest-db-ci.db" >> $GITHUB_ENV
|
||||
|
||||
@@ -644,6 +644,7 @@ jobs:
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
DEV: AMD
|
||||
PYTHON_REMU: 1
|
||||
MOCKGPU: 1
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
|
||||
@@ -38,7 +38,7 @@ optim.schedule_step() # this will step the optimizer without running realize
|
||||
# The weight Tensors have been assigned to, but not yet realized. Everything is still lazy at this point
|
||||
# l1.uop and l2.uop define a computation graph
|
||||
|
||||
from tinygrad.schedule import ExecItem
|
||||
from tinygrad.engine.schedule import ExecItem
|
||||
schedule: List[ExecItem] = Tensor.schedule(l1, l2)
|
||||
|
||||
print(f"The schedule contains {len(schedule)} items.")
|
||||
|
||||
@@ -16,13 +16,12 @@ def eval_harness(name, tensor, fxn, check=None):
|
||||
print(f"computed in {GlobalCounters.time_sum_s*1000:.2f} ms, {(a.nbytes()/1e9)/GlobalCounters.time_sum_s:.2f} GB/s")
|
||||
return out
|
||||
|
||||
SZ = 256*1024 if getenv("MOCKGPU") else 1024*1024*1024
|
||||
SZ = 32*1024 if getenv("MOCKGPU") else 1024*1024*1024
|
||||
|
||||
def example_2_hip(a:Tensor, correct):
|
||||
GLOBALS = 1024
|
||||
THREADS = 256
|
||||
def hip_reduce_sum(out:UOp, buf:UOp) -> UOp:
|
||||
assert SZ % (GLOBALS * THREADS) == 0
|
||||
CHUNK = SZ // (GLOBALS * THREADS)
|
||||
# NOTE: tinygrad doesn't populate HIP hidden kernargs, so blockDim.x/gridDim.x read as 0.
|
||||
# We hardcode block/grid sizes as constexpr to avoid any dependency on those builtins.
|
||||
|
||||
@@ -17,9 +17,9 @@ The `UOp` graph specifies the compute in terms of low level tinygrad ops. Not al
|
||||
|
||||
## Scheduling
|
||||
|
||||
The [scheduler](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/schedule/__init__.py) converts the graph of UOps into a list of `ExecItem`. One `ExecItem` is one kernel on the GPU, and the scheduler is responsible for breaking the large compute graph into subgraphs that can fit in a kernel. `ast` specifies what compute to run, and `bufs` specifies what buffers to run it on.
|
||||
The [scheduler](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/engine/schedule.py) converts the graph of UOps into a list of `ExecItem`. One `ExecItem` is one kernel on the GPU, and the scheduler is responsible for breaking the large compute graph into subgraphs that can fit in a kernel. `ast` specifies what compute to run, and `bufs` specifies what buffers to run it on.
|
||||
|
||||
::: tinygrad.schedule.ExecItem
|
||||
::: tinygrad.engine.schedule.ExecItem
|
||||
|
||||
## Lowering
|
||||
|
||||
|
||||
+4
-3
@@ -34,8 +34,9 @@ DEBUG | [1-7] | enable debugging output (operations, timings,
|
||||
DEV | [AMD, NV, ...] | enable a specific backend, see [below](#dev-variable)
|
||||
BEAM | [#] | number of beams in kernel beam search
|
||||
DEFAULT_FLOAT | [HALF, ...]| specify the default float dtype (FLOAT32, HALF, BFLOAT16, FLOAT64, ...), default to FLOAT32
|
||||
IMAGE | [1] | enable 2d specific optimizations
|
||||
IMAGE | [1-2] | enable 2d specific optimizations
|
||||
FLOAT16 | [1] | use float16 for images instead of float32
|
||||
HCQ_VISIBLE_DEVICES | [list[int]]| restricts the HCQ devices that are available. The format is a comma-separated list of identifiers (indexing starts with 0).
|
||||
JIT | [0-2] | 0=disabled, 1=[jit enabled](quickstart.md#jit) (default), 2=jit enabled, but graphs are disabled
|
||||
VIZ | [1] | 0=disabled, 1=[viz enabled](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/viz)
|
||||
ALLOW_TF32 | [1] | enable TensorFloat-32 tensor cores on Ampere or newer GPUs.
|
||||
@@ -64,8 +65,8 @@ Variable | Value | Description
|
||||
---|---|---
|
||||
DEBUG | >= 1 | Enables debugging and lists devices being used
|
||||
DEBUG | >= 2 | Provides performance metrics for operations, including timing, memory usage, bandwidth for each kernel execution
|
||||
DEBUG | >= 3 | Outputs the applied optimizations at a kernel level
|
||||
DEBUG | >= 3 | Outputs buffers used for each kernel (shape, dtype and strides) and the applied optimizations at a kernel level
|
||||
DEBUG | >= 4 | Outputs the generated kernel code
|
||||
DEBUG | >= 5 | Displays the intermediate representation of the computation UOps
|
||||
DEBUG | >= 5 | Displays the intermediate representation of the computation UOps (AST)
|
||||
DEBUG | >= 6 | Displays the intermediate representation of the computation UOps in a linearized manner, detailing the operation sequence
|
||||
DEBUG | >= 7 | Outputs the assembly code generated for the target hardware
|
||||
|
||||
+1
-1
@@ -445,7 +445,7 @@ After you are done speaking, output [EOS]. You are not Chad.
|
||||
print(f"using LLaMA{LLAMA_SUFFIX}-{args.size} model")
|
||||
device = tuple(f"{Device.DEFAULT}:{i}" for i in range(args.shard)) if args.shard > 1 else Device.DEFAULT
|
||||
llama = LLaMa.build(MODEL_PATH, TOKENIZER_PATH, model_gen=args.gen, model_size=args.size, quantize=args.quantize, device=device)
|
||||
param_bytes = sum(x.nbytes() for x in get_parameters(llama.model))
|
||||
param_bytes = sum(x.uop.size * x.dtype.itemsize for x in get_parameters(llama.model))
|
||||
|
||||
outputted = pre_prompt if chatbot else args.prompt
|
||||
start_pos, toks = 0, [llama.tokenizer.bos_id()] + llama.tokenizer.encode(outputted)
|
||||
|
||||
+1
-1
@@ -324,7 +324,7 @@ if __name__ == "__main__":
|
||||
|
||||
device = tuple(f"{Device.DEFAULT}:{i}" for i in range(args.shard)) if args.shard > 1 else Device.DEFAULT
|
||||
model = build_transformer(args.model, model_size=args.size, quantize=args.quantize, device=device)
|
||||
param_bytes = sum(x.nbytes() for x in get_parameters(model))
|
||||
param_bytes = sum(x.uop.size * x.dtype.itemsize for x in get_parameters(model))
|
||||
|
||||
if not args.no_api and not args.benchmark:
|
||||
from bottle import Bottle, request, response, HTTPResponse, abort, static_file
|
||||
|
||||
@@ -5,7 +5,7 @@ from tinygrad import Device, nn, Tensor, dtypes
|
||||
from train_gpt2 import GPT, GPTConfig
|
||||
from tinygrad.helpers import DEV, dedup, flatten, getenv, GlobalCounters, to_function_name
|
||||
from tinygrad.engine.realize import get_kernel
|
||||
from tinygrad.schedule.memory import memory_planner
|
||||
from tinygrad.engine.memory import memory_planner
|
||||
from tinygrad.uop.ops import Ops
|
||||
|
||||
DEV.value = "CPU"
|
||||
|
||||
@@ -23,20 +23,8 @@ FP8_DTYPE = dtypes.fp8e4m3
|
||||
FP8_GRAD_DTYPE = dtypes.fp8e5m2
|
||||
FP8_MAX = 448.0
|
||||
|
||||
# per-device abs max without allreduce (matches TE delayed scaling behavior)
|
||||
@functools.cache
|
||||
def _local_abs_max_fxn(x_p, device):
|
||||
x = Tensor(x_p, device=device)
|
||||
inner = Tensor(x.uop.src[0]) if x.uop.op is Ops.MULTI else x
|
||||
return (inner.abs().max(),)
|
||||
|
||||
def _local_abs_max(x:Tensor) -> Tensor:
|
||||
param = x.as_param(0)
|
||||
fxn = _local_abs_max_fxn(param.uop, x.device)
|
||||
return Tensor(fxn[0].uop.call(x.uop).gettuple(0))
|
||||
|
||||
def quantize_fp8(x:Tensor, amax_state:Tensor|None=None):
|
||||
new_amax = (_local_abs_max(x) if isinstance(x.device, tuple) else x.abs().max()).detach()
|
||||
new_amax = x.abs().max().detach()
|
||||
scale = FP8_MAX / ((amax_state if amax_state is not None else new_amax) + 1e-8)
|
||||
x_scaled = x * scale
|
||||
x_clamped = x_scaled + (x_scaled.detach().clamp(-FP8_MAX, FP8_MAX) - x_scaled.detach()) # STE
|
||||
@@ -205,10 +193,6 @@ class FlatTransformer:
|
||||
self.tok_embeddings.weight.shard_(device, axis=0).realize()
|
||||
self.output.shard_(device, axis=1).realize()
|
||||
self.freqs_cis.shard_(device, axis=None).realize()
|
||||
if FP8:
|
||||
for name in self._fp8_amax:
|
||||
for i in range(len(self._fp8_amax[name])):
|
||||
self._fp8_amax[name][i] = self._fp8_amax[name][i].to(device).contiguous().requires_grad_(False)
|
||||
|
||||
def __call__(self, tokens:Tensor):
|
||||
h = self.tok_embeddings(tokens)
|
||||
|
||||
+1
-2
@@ -14,10 +14,9 @@ export ASM_GEMM=${ASM_GEMM:-1}
|
||||
export WQKV=${WQKV:-1}
|
||||
export MASTER_WEIGHTS=${MASTER_WEIGHTS:-1}
|
||||
export FP8=${FP8:-1}
|
||||
export ALLREDUCE_CAST=${ALLREDUCE_CAST:-1}
|
||||
|
||||
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
||||
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-16} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2}
|
||||
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-8} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-4}
|
||||
export GBS=$((BS * GRADIENT_ACC_STEPS))
|
||||
|
||||
export MODEL="llama3"
|
||||
|
||||
+1
-2
@@ -14,10 +14,9 @@ export ASM_GEMM=${ASM_GEMM:-1}
|
||||
export WQKV=${WQKV:-1}
|
||||
export MASTER_WEIGHTS=${MASTER_WEIGHTS:-1}
|
||||
export FP8=${FP8:-1}
|
||||
export ALLREDUCE_CAST=${ALLREDUCE_CAST:-1}
|
||||
|
||||
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
||||
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-16} EVAL_BS=${EVAL_BS:-16} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-2}
|
||||
export DP=${DP:-8} MP=${MP:-1} BS=${BS:-8} EVAL_BS=${EVAL_BS:-8} GRADIENT_ACC_STEPS=${GRADIENT_ACC_STEPS:-4}
|
||||
export GBS=$((BS * GRADIENT_ACC_STEPS))
|
||||
|
||||
export MODEL="llama3"
|
||||
|
||||
+1
-2
@@ -15,10 +15,9 @@ export ASM_GEMM=1
|
||||
export WQKV=1
|
||||
export MASTER_WEIGHTS=1
|
||||
export FP8=1
|
||||
export ALLREDUCE_CAST=1
|
||||
|
||||
export DEFAULT_FLOAT="bfloat16" OPTIM_DTYPE="bfloat16"
|
||||
export DP=8 MP=1 BS=16 EVAL_BS=16 GRADIENT_ACC_STEPS=2
|
||||
export DP=8 MP=1 BS=8 EVAL_BS=8 GRADIENT_ACC_STEPS=4
|
||||
export GBS=$((BS * GRADIENT_ACC_STEPS))
|
||||
|
||||
export MODEL="llama3"
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ if __name__ == "__main__":
|
||||
model_path = Path(args.weights) if args.weights else download_weights(model_info["total_num_weights"])
|
||||
transformer = load_model(model_path, model_info["model_params"])
|
||||
tokenizer = AutoTokenizer.from_pretrained(model_info["tokenizer"])
|
||||
param_bytes = sum(x.nbytes() for x in get_parameters(transformer))
|
||||
param_bytes = sum(x.uop.size * x.dtype.itemsize for x in get_parameters(transformer))
|
||||
|
||||
outputted = args.prompt
|
||||
start_pos, toks = 0, tokenizer(outputted)["input_ids"]
|
||||
|
||||
+3
-3
@@ -44,9 +44,9 @@ nc = np.random.randn(N, N).astype(np.float32)
|
||||
|
||||
ns = nb.reshape(-1, 32).sum(axis=0)
|
||||
|
||||
a = MallocAllocator.alloc(na.nbytes)
|
||||
b = MallocAllocator.alloc(nb.nbytes)
|
||||
c = MallocAllocator.alloc(nc.nbytes)
|
||||
a = MallocAllocator.alloc(na.size * np.dtype(np.float32).itemsize)
|
||||
b = MallocAllocator.alloc(nb.size * np.dtype(np.float32).itemsize)
|
||||
c = MallocAllocator.alloc(nc.size * np.dtype(np.float32).itemsize)
|
||||
|
||||
MallocAllocator._copyin(b, flat_mv(nb.data))
|
||||
MallocAllocator._copyin(c, flat_mv(nc.data))
|
||||
|
||||
Generated
+66
@@ -0,0 +1,66 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remu"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"float-cmp",
|
||||
"half",
|
||||
"num-traits",
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "remu"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.80.0"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
half = { version = "2.3.1", features = ["num-traits"] }
|
||||
num-traits = "0.2.17"
|
||||
|
||||
[dev-dependencies]
|
||||
float-cmp = "0.9.0"
|
||||
@@ -0,0 +1,80 @@
|
||||
## Intro
|
||||
|
||||
Remu is an RDNA3 emulator built to test correctness of RDNA3 code. It is used in [tinygrad's AMD CI](https://github.com/tinygrad/tinygrad).
|
||||
|
||||
Most of the common instructions are implemented, but some formats like IMG are not supported.
|
||||
|
||||
Remu is only for testing correctness of program output, it is not a cycle accurate simulator.
|
||||
|
||||
## Build Locally
|
||||
|
||||
Remu is written in Rust. Make sure you have [Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html).
|
||||
|
||||
To build the project, run:
|
||||
|
||||
```bash
|
||||
cargo build --release --manifest-path ./extra/remu/Cargo.toml
|
||||
```
|
||||
|
||||
This will produce a binary in the `extra/remu/target/release` directory.
|
||||
|
||||
## Usage with tinygrad
|
||||
|
||||
The latest binaries are released in https://github.com/Qazalin/remu/releases. Alternatively, you can [build locally](#build-locally).
|
||||
|
||||
Tinygrad does not yet output RDNA3 kernels directly. You can either install comgr or use `DEV=AMD:LLVM` (default) if you have [LLVM@19](https://github.com/tinygrad/tinygrad/blob/e2ed673c946c8f1774d816c75e52a994c2dd8a88/.github/actions/setup-tinygrad/action.yml#L208).
|
||||
|
||||
`PYTHONPATH="." MOCKGPU=1 DEV=AMD python test/test_tiny.py TestTiny.test_plus` runs an emulated RDNA3 kernel with Remu.
|
||||
|
||||
Add `DEBUG=6` to see Remu's logs.
|
||||
|
||||
### DEBUG output
|
||||
|
||||
Remu runs each thread one at a time in a nested for loop, see lib.rs. The DEBUG output prints information about the current thread.
|
||||
|
||||
The DEBUG output has 3 sections:
|
||||
|
||||
```
|
||||
<------------ 1 ----------> <--- 2 ---> <--------------------------------------- 3 ------------------------------------------>
|
||||
[0 0 0 ] [0 0 0 ] 0 F4080100 SMEM { op: 2, sdata: 4, sbase: 0, offset: 0, soffset: 124, glc: false, dlc: false }
|
||||
```
|
||||
|
||||
#### Section 1: Grid info
|
||||
|
||||
`[gid.x, gid.y, gid.z], [lid.x, lid.y, lid.z]` of the current thread.
|
||||
|
||||
#### Section 2: Wave info
|
||||
|
||||
`<lane> <instruction hex>`
|
||||
|
||||
RDNA3 divides threads into chunks of 32. Each thread is assigned to a "lane" from 0-31.
|
||||
|
||||
In Remu, even though all threads run one at a time, each 32 thread chunk (a wave) shares state like SGPR, VGPR, LDS, EXEC mask, etc.
|
||||
Remu can simulate up to one wave sync instruction.
|
||||
For more details, see work_group.rs.
|
||||
|
||||
Section 2 can have a green or gray color.
|
||||
|
||||
Green = The thread is actively executing the instruction.
|
||||
|
||||
Gray = The thread has been "turned off" by the EXEC mask, it skips execution of some instructions. (refer to "EXECute Mask" on [page 23](https://www.amd.com/content/dam/amd/en/documents/radeon-tech-docs/instruction-set-architectures/rdna3-shader-instruction-set-architecture-feb-2023_0.pdf#page=23) of ISA docs for more details.)
|
||||
|
||||
To see the colors in action, try running `DEBUG=6 PYTHONPATH="." MOCKGPU=1 DEV=AMD python test/test_ops.py TestOps.test_arange_big`. See how only lane 0 writes to global memory:
|
||||
```
|
||||
[255 0 0 ] [0 0 0 ] 0 DC6A0000 FLAT { op: 26, offset: 0, dlc: false, glc: false, slc: false, seg: 2, addr: 8, data: 0, saddr: 0, sve: false, vdst: 0 }
|
||||
[255 0 0 ] [1 0 0 ] 1 DC6A0000
|
||||
[255 0 0 ] [2 0 0 ] 2 DC6A0000
|
||||
[255 0 0 ] [3 0 0 ] 3 DC6A0000
|
||||
[255 0 0 ] [3 0 0 ] 4 DC6A0000
|
||||
```
|
||||
|
||||
#### Section 3: Decoded Instruction
|
||||
|
||||
This prints the instruction type and all the parsed bitfields.
|
||||
|
||||
Remu output vs llvm-objdump:
|
||||
|
||||
```
|
||||
s_load_b64 s[0:1], s[0:1], 0x10 // 00000000160C: F4040000 F8000010
|
||||
SMEM { op: 1, sdata: 0, sbase: 0, offset: 16, soffset: 124, glc: false, dlc: false }
|
||||
```
|
||||
@@ -0,0 +1 @@
|
||||
max_width = 150
|
||||
@@ -0,0 +1,162 @@
|
||||
use half::f16;
|
||||
use num_traits::{float::FloatCore, PrimInt, Unsigned, clamp};
|
||||
|
||||
pub fn bits<T>(word: T, hi: usize, lo: usize) -> T where T: PrimInt + Unsigned {
|
||||
assert!(hi >= lo);
|
||||
let width = hi - lo + 1;
|
||||
(word >> lo) & ((T::one() << width) - T::one())
|
||||
}
|
||||
|
||||
pub fn nth(val: u32, pos: usize) -> u32 {
|
||||
(val >> (31 - pos as u32)) & 1
|
||||
}
|
||||
pub fn f16_lo(val: u32) -> f16 {
|
||||
f16::from_bits((val & 0xffff) as u16)
|
||||
}
|
||||
pub fn f16_hi(val: u32) -> f16 {
|
||||
f16::from_bits(((val >> 16) & 0xffff) as u16)
|
||||
}
|
||||
|
||||
pub fn sign_ext(num: u64, bits: usize) -> i64 {
|
||||
let mut value = num;
|
||||
let is_negative = (value >> (bits - 1)) & 1 != 0;
|
||||
if is_negative {
|
||||
value |= !0 << bits;
|
||||
}
|
||||
value as i64
|
||||
}
|
||||
|
||||
pub trait IEEEClass<T> {
|
||||
fn exponent(&self) -> T;
|
||||
}
|
||||
impl IEEEClass<u32> for f32 {
|
||||
fn exponent(&self) -> u32 {
|
||||
(self.to_bits() & 0b01111111100000000000000000000000) >> 23
|
||||
}
|
||||
}
|
||||
impl IEEEClass<u16> for f16 {
|
||||
fn exponent(&self) -> u16 {
|
||||
(self.to_bits() & 0b0111110000000000) >> 10
|
||||
}
|
||||
}
|
||||
impl IEEEClass<u64> for f64 {
|
||||
fn exponent(&self) -> u64 {
|
||||
(self.to_bits() & 0b0111111111110000000000000000000000000000000000000000000000000000) >> 52
|
||||
}
|
||||
}
|
||||
|
||||
pub trait VOPModifier<T> {
|
||||
fn negate(&self, pos: usize, modifier: usize) -> T;
|
||||
fn absolute(&self, pos: usize, modifier: usize) -> T;
|
||||
fn clmp(&self, cm: bool) -> T;
|
||||
}
|
||||
impl<T> VOPModifier<T> for T
|
||||
where
|
||||
T: FloatCore,
|
||||
{
|
||||
fn negate(&self, pos: usize, modifier: usize) -> T {
|
||||
match (modifier >> pos) & 1 {
|
||||
1 => -*self,
|
||||
_ => *self,
|
||||
}
|
||||
}
|
||||
fn absolute(&self, pos: usize, modifier: usize) -> T {
|
||||
match (modifier >> pos) & 1 {
|
||||
1 => self.abs(),
|
||||
_ => *self,
|
||||
}
|
||||
}
|
||||
fn clmp(&self, cm:bool) -> T {
|
||||
if !cm { return *self }
|
||||
let r = clamp(*self, T::zero(), T::one());
|
||||
if r == T::zero() { T::zero() } else { r }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_mantissa(x: f64) -> f64 {
|
||||
if x.is_infinite() || x.is_nan() {
|
||||
return x;
|
||||
}
|
||||
let bits = x.to_bits();
|
||||
let mantissa_mask: u64 = 0x000FFFFFFFFFFFFF;
|
||||
let bias: u64 = 1023;
|
||||
let normalized_mantissa_bits = (bits & mantissa_mask) | ((bias - 1) << 52);
|
||||
return f64::from_bits(normalized_mantissa_bits);
|
||||
}
|
||||
pub fn ldexp(x: f64, exp: i32) -> f64 {
|
||||
x * 2f64.powi(exp)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_extract_mantissa() {
|
||||
assert_eq!(extract_mantissa(2.0f64), 0.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_normal_exponent() {
|
||||
assert_eq!(2.5f32.exponent(), 128);
|
||||
assert_eq!(1.17549435e-38f32.exponent(), 1);
|
||||
assert_eq!(f32::INFINITY.exponent(), 255);
|
||||
assert_eq!(f32::NEG_INFINITY.exponent(), 255);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_denormal_exponent() {
|
||||
assert_eq!(1.0e-40f32.exponent(), 0);
|
||||
assert_eq!(1.0e-42f32.exponent(), 0);
|
||||
assert_eq!(1.0e-44f32.exponent(), 0);
|
||||
assert_eq!((1.17549435e-38f32 / 2.0).exponent(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_normal_exponent_f16() {
|
||||
assert_eq!(f16::from_f32(3.14f32).exponent(), 16);
|
||||
assert_eq!(f16::NEG_INFINITY.exponent(), 31);
|
||||
assert_eq!(f16::INFINITY.exponent(), 31);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_neg() {
|
||||
assert_eq!(0.3_f32.negate(0, 0b001), -0.3_f32);
|
||||
assert_eq!(0.3_f32.negate(1, 0b010), -0.3_f32);
|
||||
assert_eq!(0.3_f32.negate(2, 0b100), -0.3_f32);
|
||||
assert_eq!(0.3_f32.negate(0, 0b110), 0.3_f32);
|
||||
assert_eq!(0.3_f32.negate(1, 0b010), -0.3_f32);
|
||||
assert_eq!(0.0_f32.negate(0, 0b001).to_bits(), (-0.0f32).to_bits());
|
||||
assert_eq!((-0.0_f32).negate(0, 0b001).to_bits(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sign_ext() {
|
||||
assert_eq!(sign_ext(0b000000000000000101000, 21), 40);
|
||||
assert_eq!(sign_ext(0b111111111111111011000, 21), -40);
|
||||
assert_eq!(sign_ext(0b000000000000000000000, 21), 0);
|
||||
assert_eq!(sign_ext(0b111111111111111111111, 21), -1);
|
||||
assert_eq!(sign_ext(0b111000000000000000000, 21), -262144);
|
||||
assert_eq!(sign_ext(0b000111111111111111111, 21), 262143);
|
||||
assert_eq!(sign_ext(7608, 13), -584);
|
||||
}
|
||||
}
|
||||
|
||||
use std::sync::LazyLock;
|
||||
pub static DEBUG: LazyLock<bool> = LazyLock::new(|| std::env::var("DEBUG").map(|v| v.parse::<usize>().unwrap_or(0) >= 6).unwrap_or(false));
|
||||
|
||||
pub fn colored(st:&str, color:&str) -> String {
|
||||
let ansi_code = match color {
|
||||
"green" => format!("\x1b[{};2;39;176;139m", 38),
|
||||
"gray" => format!("\x1b[{};2;169;169;169m", 38),
|
||||
_ => format!("\x1b[{};2;255;255;255m", 38),
|
||||
};
|
||||
format!("{}{}{}", ansi_code, st, "\x1b[0m")
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! todo_instr {
|
||||
($x:expr) => {{
|
||||
println!("{:08X}", $x);
|
||||
Err(1)
|
||||
}};
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
use crate::state::StateSnapshot;
|
||||
use crate::work_group::{WaveContext, WorkGroup};
|
||||
use std::os::raw::c_char;
|
||||
use std::slice;
|
||||
mod helpers;
|
||||
mod rdna3;
|
||||
mod state;
|
||||
mod thread;
|
||||
mod work_group;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn run_asm(lib: *const c_char, lib_sz: u32, gx: u32, gy: u32, gz: u32, lx: u32, ly: u32, lz: u32, args_ptr: *const u64) -> i32 {
|
||||
if lib.is_null() || (lib_sz % 4) != 0 {
|
||||
panic!("Pointer is null or length is not properly aligned to 4 bytes");
|
||||
}
|
||||
let kernel = unsafe { slice::from_raw_parts(lib as *const u32, (lib_sz / 4) as usize).to_vec() };
|
||||
let dispatch_dim = match (gy != 1, gz != 1) {
|
||||
(true, true) => 3,
|
||||
(true, false) => 2,
|
||||
_ => 1,
|
||||
};
|
||||
for gx in 0..gx {
|
||||
for gy in 0..gy {
|
||||
for gz in 0..gz {
|
||||
let mut wg = WorkGroup::new(dispatch_dim, [gx, gy, gz], [lx, ly, lz], &kernel, args_ptr);
|
||||
if let Err(err) = wg.exec_waves() {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
// FFI functions for single-stepping comparison tests
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wave_create(lib: *const c_char, lib_sz: u32, n_lanes: u32) -> *mut WaveContext {
|
||||
if lib.is_null() || (lib_sz % 4) != 0 { return std::ptr::null_mut(); }
|
||||
let kernel = unsafe { slice::from_raw_parts(lib as *const u32, (lib_sz / 4) as usize).to_vec() };
|
||||
Box::into_raw(Box::new(WaveContext::new(kernel, n_lanes as usize)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wave_step(ctx: *mut WaveContext) -> i32 {
|
||||
if ctx.is_null() { return -99; }
|
||||
unsafe { (*ctx).step() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wave_get_snapshot(ctx: *const WaveContext, out: *mut StateSnapshot) {
|
||||
if ctx.is_null() || out.is_null() { return; }
|
||||
unsafe { *out = (*ctx).get_snapshot(); }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wave_set_sgpr(ctx: *mut WaveContext, idx: u32, val: u32) {
|
||||
if ctx.is_null() || idx >= 128 { return; }
|
||||
unsafe { (*ctx).scalar_reg[idx as usize] = val; }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wave_set_vgpr(ctx: *mut WaveContext, lane: u32, idx: u32, val: u32) {
|
||||
if ctx.is_null() || lane >= 32 || idx >= 256 { return; }
|
||||
unsafe { (*ctx).vec_reg.get_lane_mut(lane as usize)[idx as usize] = val; }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wave_init_lds(ctx: *mut WaveContext, size: u32) {
|
||||
if ctx.is_null() { return; }
|
||||
unsafe { (*ctx).lds.data.resize(size as usize, 0); }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wave_free(ctx: *mut WaveContext) {
|
||||
if !ctx.is_null() { unsafe { drop(Box::from_raw(ctx)); } }
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
use crate::helpers::{bits, sign_ext};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Instruction {
|
||||
SOP2 { op: u8, ssrc0: u8, ssrc1: u8, sdst: u8 },
|
||||
SOP1 { op: u8, ssrc0: u8, sdst: u8 },
|
||||
SOPK { op: u8, simm16: i16, sdst: u8 },
|
||||
SOPP { op: u8, simm16: i16 },
|
||||
SOPC { op: u8, ssrc0: u8, ssrc1: u8 },
|
||||
|
||||
SMEM { op: u8, sdata: u8, sbase: u8, offset: i32, soffset: u8, glc: bool, dlc: bool },
|
||||
|
||||
VOP1 { op: u8, vdst: u8, src: u16 },
|
||||
VOP2 { op: u8, vdst: u8, vsrc: u8, src: u16 },
|
||||
VOPC { op: u8, vsrc: u8, src: u16 },
|
||||
VOP3 { op: u32, opsel: u8, cm: bool, abs: u8, vdst: u8, neg: u8, omod: u8, src2: u16, src1: u16, src0: u16 },
|
||||
VOP3SD { op: u32, cm: bool, sdst: u8, vdst: u8, neg: u8, omod: u8, src2: u16, src1: u16, src0: u16 },
|
||||
VOP3P { op: u8, vdst: u8, neg_hi: u8, opsel: u8, opsel_hi: u8, opsel_hi2: bool, cm: bool, src2: u16, src1: u16, src0: u16, neg: u8 },
|
||||
VOPD { opx: u8, opy: u8, vdstx: u8, vdsty: u8, vsrcx1: u8, vsrcy1: u8, srcx0: u16, srcy0: u16 },
|
||||
|
||||
DS { op: u8, gds: bool, offset1: u8, offset0: u8, vdst: u8, data1: u8, data0: u8, addr: u8 },
|
||||
|
||||
FLAT { op: u8, offset: u16, dlc: bool, glc: bool, slc: bool, seg: u8, addr: u8, data: u8, saddr: u8, sve: bool, vdst: u8 }
|
||||
}
|
||||
|
||||
const VOP3SD_OPS: [u32; 7] = [764, 765, 766, 767, 768, 769, 770];
|
||||
|
||||
pub fn decode(word:u32, word1:Option<&u32>) -> Instruction {
|
||||
match bits(word, 31, 30) {
|
||||
0b11 => {
|
||||
let word = (*word1.unwrap() as u64) << 32 | (word as u64);
|
||||
match bits(word, 29, 26) {
|
||||
0b1101 => {
|
||||
let sbase = (bits(word, 5, 0) as u8) << 1;
|
||||
let sdata = bits(word, 12, 6) as u8;
|
||||
let dlc = bits(word, 13, 13) != 0;
|
||||
let glc = bits(word, 14, 14) != 0;
|
||||
let op = bits(word, 25, 18) as u8;
|
||||
let offset = sign_ext(bits(word, 52, 32), 21) as i32;
|
||||
let soffset = bits(word, 63, 57) as u8;
|
||||
Instruction::SMEM { sbase, sdata, dlc, glc, op, offset, soffset }
|
||||
}
|
||||
0b0101 => {
|
||||
let op = bits(word, 25, 16) as u32;
|
||||
let vdst = bits(word, 7, 0) as u8;
|
||||
let cm = bits(word, 15, 15) != 0;
|
||||
let src0 = bits(word, 40, 32) as u16;
|
||||
let src1 = bits(word, 49, 41) as u16;
|
||||
let src2 = bits(word, 58, 50) as u16;
|
||||
let omod = bits(word, 60, 59) as u8;
|
||||
let neg = bits(word, 63, 61) as u8;
|
||||
if VOP3SD_OPS.contains(&op) {
|
||||
let sdst = bits(word, 14, 8) as u8;
|
||||
Instruction::VOP3SD { op, vdst, sdst, cm, src0, src1, src2, omod, neg }
|
||||
} else {
|
||||
let abs = bits(word, 10, 8) as u8;
|
||||
let opsel = bits(word, 14, 11) as u8;
|
||||
Instruction::VOP3 { opsel, cm, abs, vdst, neg, omod, src2, src1, src0, op }
|
||||
}
|
||||
}
|
||||
0b0011 => {
|
||||
let op = bits(word, 22, 16) as u8;
|
||||
let vdst = bits(word, 7, 0) as u8;
|
||||
let neg_hi = bits(word, 10, 8) as u8;
|
||||
let opsel = bits(word, 13, 11) as u8;
|
||||
let opsel_hi2 = bits(word, 14, 14) != 0;
|
||||
let cm = bits(word, 15, 15) != 0;
|
||||
let src0 = bits(word, 40, 32) as u16;
|
||||
let src1 = bits(word, 49, 41) as u16;
|
||||
let src2 = bits(word, 58, 50) as u16;
|
||||
let opsel_hi = bits(word, 60, 59) as u8;
|
||||
let neg = bits(word, 63, 61) as u8;
|
||||
Instruction::VOP3P { op, vdst, neg_hi, opsel, opsel_hi, opsel_hi2, cm, src0, src1, src2, neg }
|
||||
}
|
||||
0b0110 => {
|
||||
let offset0 = bits(word, 7, 0) as u8;
|
||||
let offset1 = bits(word, 15, 8) as u8;
|
||||
let gds = bits(word, 17, 17) != 0;
|
||||
let op = bits(word, 25, 18) as u8;
|
||||
let addr = bits(word, 39, 32) as u8;
|
||||
let data0 = bits(word, 47, 40) as u8;
|
||||
let data1 = bits(word, 55, 48) as u8;
|
||||
let vdst = bits(word, 63, 56) as u8;
|
||||
Instruction::DS { op, gds, offset1, offset0, vdst, data1, data0, addr }
|
||||
}
|
||||
0b0111 => {
|
||||
let offset = bits(word, 12, 0) as u16;
|
||||
let dlc = bits(word, 13, 13) != 0;
|
||||
let glc = bits(word, 14, 14) != 0;
|
||||
let slc = bits(word, 15, 15) != 0;
|
||||
let seg = bits(word, 17, 16) as u8;
|
||||
let op = bits(word, 24, 18) as u8;
|
||||
let addr = bits(word, 39, 32) as u8;
|
||||
let data = bits(word, 47, 40) as u8;
|
||||
let saddr = bits(word, 54, 48) as u8;
|
||||
let sve = bits(word, 55, 55) != 0;
|
||||
let vdst = bits(word, 63, 56) as u8;
|
||||
Instruction::FLAT { offset, dlc, glc, slc, seg, op, addr, data, saddr, sve, vdst }
|
||||
},
|
||||
0b0010 => {
|
||||
let srcx0 = bits(word, 8, 0) as u16;
|
||||
let vsrcx1 = bits(word, 16, 9) as u8;
|
||||
let opy = bits(word, 21, 17) as u8;
|
||||
let opx = bits(word, 25, 22) as u8;
|
||||
let srcy0 = bits(word, 40, 32) as u16;
|
||||
let vsrcy1 = bits(word, 48, 41) as u8;
|
||||
let vdsty = bits(word, 55, 49) as u8;
|
||||
let vdstx = bits(word, 63, 56) as u8;
|
||||
Instruction::VOPD { opx, opy, vdstx, vdsty, vsrcx1, vsrcy1, srcx0, srcy0 }
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
0b10 => {
|
||||
let ssrc0 = bits(word, 7, 0) as u8;
|
||||
let ssrc1 = bits(word, 15, 8) as u8;
|
||||
let simm16 = word as i16;
|
||||
let sdst = bits(word, 22, 16) as u8;
|
||||
match bits(word, 29, 23) {
|
||||
0b1111101 => Instruction::SOP1 { ssrc0, sdst, op: bits(word, 15, 8) as u8 },
|
||||
0b1111110 => Instruction::SOPC { ssrc0, ssrc1, op: bits(word, 22, 16) as u8 },
|
||||
0b1111111 => Instruction::SOPP { simm16, op: bits(word, 22, 16) as u8 },
|
||||
_ => {
|
||||
match bits(word, 29, 28) {
|
||||
0b11 => Instruction::SOPK { simm16, sdst, op: bits(word, 27, 23) as u8 },
|
||||
_ => Instruction::SOP2 { ssrc0, ssrc1, sdst, op: bits(word, 29, 23) as u8 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let vdst = bits(word, 24, 17) as u8;
|
||||
let src = bits(word, 8, 0) as u16;
|
||||
let vsrc = bits(word, 16, 9) as u8;
|
||||
match bits(word, 30, 25) {
|
||||
0b111110 => Instruction::VOPC { vsrc, src, op: bits(word, 24, 17) as u8 },
|
||||
0b111111 => Instruction::VOP1 { vdst, src, op: vsrc },
|
||||
_ => Instruction::VOP2 { vdst, vsrc, src, op: bits(word, 30, 25) as u8 },
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_rdna3 {
|
||||
use super::*;
|
||||
|
||||
use std::process::{Stdio, Command};
|
||||
use std::io::{Result, Write};
|
||||
|
||||
const LLVM_ARGS: &[&str; 3] = &["--arch=amdgcn", "--mcpu=gfx1100", "--triple=amdgcn-amd-amdhsa"];
|
||||
const OFFSET_PRG: usize = 16;
|
||||
const NULL: u8 = 124;
|
||||
|
||||
fn llvm_assemble(asm: &str) -> Result<Vec<u8>> {
|
||||
let mut proc = Command::new("llvm-mc").args(LLVM_ARGS).args(["-filetype=obj", "-o", "-"]).stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
|
||||
proc.stdin.as_mut().unwrap().write_all(asm.as_bytes())?;
|
||||
let out = proc.wait_with_output()?;
|
||||
match out.status.success() {
|
||||
true => Ok(out.stdout),
|
||||
false => Err(std::io::Error::new(std::io::ErrorKind::Other, "llvm-mc err")),
|
||||
}
|
||||
}
|
||||
|
||||
fn llvm_disassemble(code: &Vec<u8>) -> Result<String> {
|
||||
let mut proc = Command::new("llvm-objdump").args(LLVM_ARGS).args(["--disassemble", "-"]).stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
|
||||
proc.stdin.as_mut().unwrap().write_all(code)?;
|
||||
let out = proc.wait_with_output()?;
|
||||
match out.status.success() {
|
||||
true => Ok(String::from_utf8(out.stdout).unwrap()),
|
||||
false => Err(std::io::Error::new(std::io::ErrorKind::Other, "llvm-objdump err")),
|
||||
}
|
||||
}
|
||||
|
||||
fn test_decode(asm: &str) -> Instruction {
|
||||
let lib = llvm_assemble(asm).unwrap();
|
||||
println!("{}", llvm_disassemble(&lib).unwrap());
|
||||
let stream: Vec<u32> = lib.chunks_exact(4).map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap())).skip(OFFSET_PRG).collect();
|
||||
decode(stream[0], stream.get(1))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_smem() {
|
||||
assert_eq!(test_decode("s_load_b128 s[4:7], s[0:1], null"), Instruction::SMEM { op: 2, sdata: 4, sbase: 0, offset: 0, soffset: NULL, glc: false, dlc: false });
|
||||
assert_eq!(test_decode("s_load_b32 s10, s[0:1], 0xc"), Instruction::SMEM { op: 0, sdata: 10, sbase: 0, offset: 0xc, soffset: NULL, glc: false, dlc: false });
|
||||
assert_eq!(test_decode("s_load_b32 s0, s[4:5], s6"), Instruction::SMEM { op: 0, sdata: 0, sbase: 4, offset: 0, soffset: 6, glc: false, dlc: false });
|
||||
assert_eq!(test_decode("s_load_b32 s0, s[4:5], glc dlc"), Instruction::SMEM { op: 0, sdata: 0, sbase: 4, offset: 0, soffset: NULL, glc: true, dlc: true });
|
||||
assert_eq!(test_decode("s_load_b32 s0, s[4:5], glc"), Instruction::SMEM { op: 0, sdata: 0, sbase: 4, offset: 0, soffset: NULL, glc: true, dlc: false });
|
||||
assert_eq!(test_decode("s_load_b32 s0, s[4:5], -20"), Instruction::SMEM { op: 0, sdata: 0, sbase: 4, offset: -20, soffset: NULL, glc: false, dlc: false });
|
||||
assert_eq!(test_decode("s_load_b32 s0, s[4:5], -1048576"), Instruction::SMEM { op: 0, sdata: 0, sbase: 4, offset: -1048576, soffset: NULL, glc: false, dlc: false });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_salu() {
|
||||
assert_eq!(test_decode("s_add_u32 s1 s2 s3"), Instruction::SOP2 { op: 0, ssrc0: 2, ssrc1: 3, sdst: 1 });
|
||||
assert_eq!(test_decode("s_add_u32 vcc_hi exec_lo vcc_lo"), Instruction::SOP2 { op: 0, ssrc0: 126, ssrc1: 106, sdst: 107 });
|
||||
assert_eq!(test_decode("s_mov_b32 s1 -0.5"), Instruction::SOP1 { op: 0, ssrc0: 241, sdst: 1 });
|
||||
assert_eq!(test_decode("s_cmpk_eq_i32 s0 -30"), Instruction::SOPK { op: 3, sdst: 0, simm16: -30 });
|
||||
assert_eq!(test_decode("s_cmpk_eq_u32 s0 65535"), Instruction::SOPK { op: 9, sdst: 0, simm16: -1 });
|
||||
assert_eq!(test_decode("s_cmp_ge_i32 s1 s2"), Instruction::SOPC { op: 3, ssrc0: 1, ssrc1: 2 });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_valu_e32() {
|
||||
assert_eq!(test_decode("v_mov_b32 v0, v0"), Instruction::VOP1 { op: 1, vdst: 0, src: 256 });
|
||||
assert_eq!(test_decode("v_mov_b32 v0, s0"), Instruction::VOP1 { op: 1, vdst: 0, src: 0 });
|
||||
assert_eq!(test_decode("v_cmp_t_f32 v1, v0"), Instruction::VOPC { op: 31, vsrc: 0, src: 257 });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_valu_e64() {
|
||||
assert_eq!(test_decode("v_log_f32_e64 v2, |v0|"), Instruction::VOP3 { op: 423, vdst: 2, src0: 256, src1: 0, src2: 0, abs: 0b001, neg: 0, opsel: 0, omod: 0, cm: false });
|
||||
assert_eq!(test_decode("v_div_scale_f32 v2, s1, v0, v1, v2"), Instruction::VOP3SD { op: 764, cm: false, vdst: 2, sdst: 1, src0: 256, src1: 257, src2: 258, omod: 0, neg: 0 });
|
||||
assert_eq!(test_decode("v_pk_add_i16 v1, v0, v2"), Instruction::VOP3P { op: 2, vdst: 1, neg_hi: 0, opsel: 0, opsel_hi: 3, opsel_hi2: true, cm: false, src2: 0, src1: 258, src0: 256, neg: 0 });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_ds() {
|
||||
assert_eq!(test_decode("ds_add_u32 v2, v4 offset:16"), Instruction::DS { op: 0, gds: false, offset1: 0, offset0: 0x10, vdst: 0, data1: 0, data0: 4, addr: 2 });
|
||||
assert_eq!(test_decode("ds_store_b32 v0, v1, offset: 0x04 gds"), Instruction::DS { op: 13, gds: true, offset1: 0, offset0: 0x04, vdst: 0, data1: 0, data0: 1, addr: 0 });
|
||||
assert_eq!(test_decode("ds_load_u8 v1, v0 offset:16"), Instruction::DS { op: 58, gds: false, offset1: 0, offset0: 16, vdst: 1, data1: 0, data0: 0, addr: 0 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
pub trait Register {
|
||||
fn read64(&self, idx: usize) -> u64;
|
||||
fn write64(&mut self, idx: usize, addr: u64);
|
||||
}
|
||||
impl<T> Register for T where T: Index<usize, Output = u32> + IndexMut<usize> {
|
||||
fn read64(&self, idx: usize) -> u64 {
|
||||
let lsb = self[idx] as u64;
|
||||
let msb = self[idx + 1] as u64;
|
||||
(msb << 32) | lsb
|
||||
}
|
||||
|
||||
fn write64(&mut self, idx: usize, value: u64) {
|
||||
self[idx] = (value & 0xffffffff) as u32;
|
||||
self[idx + 1] = ((value & (0xffffffff << 32)) >> 32) as u32;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VGPR {
|
||||
values: [[u32; 256]; 32],
|
||||
pub default_lane: Option<usize>,
|
||||
}
|
||||
impl Index<usize> for VGPR {
|
||||
type Output = u32;
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self.values[self.default_lane.unwrap()][index]
|
||||
}
|
||||
}
|
||||
impl IndexMut<usize> for VGPR {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
&mut self.values[self.default_lane.unwrap()][index]
|
||||
}
|
||||
}
|
||||
impl VGPR {
|
||||
pub fn new() -> Self {
|
||||
VGPR {
|
||||
values: [[0; 256]; 32],
|
||||
default_lane: None,
|
||||
}
|
||||
}
|
||||
pub fn get_lane(&self, lane: usize) -> [u32; 256] {
|
||||
*self.values.get(lane).unwrap()
|
||||
}
|
||||
pub fn get_lane_mut(&mut self, lane: usize) -> &mut [u32; 256] {
|
||||
self.values.get_mut(lane).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Value {
|
||||
fn mut_hi16(&mut self, val: u16);
|
||||
fn mut_lo16(&mut self, val: u16);
|
||||
}
|
||||
impl Value for u32 {
|
||||
fn mut_hi16(&mut self, val: u16) {
|
||||
*self = ((val as u32) << 16) | (*self as u16 as u32);
|
||||
}
|
||||
fn mut_lo16(&mut self, val: u16) {
|
||||
*self = ((((*self & (0xffff << 16)) >> 16) as u32) << 16) | val as u32;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct WaveValue {
|
||||
pub value: u32,
|
||||
pub warp_size: usize,
|
||||
pub default_lane: Option<usize>,
|
||||
pub mutations: Option<[bool; 32]>,
|
||||
}
|
||||
impl WaveValue {
|
||||
pub fn new(value: u32, warp_size: usize) -> Self {
|
||||
Self {
|
||||
value,
|
||||
warp_size,
|
||||
default_lane: None,
|
||||
mutations: None,
|
||||
}
|
||||
}
|
||||
pub fn read(&self) -> bool {
|
||||
(self.value >> self.default_lane.unwrap()) & 1 == 1
|
||||
}
|
||||
pub fn set_lane(&mut self, value: bool) {
|
||||
if self.mutations.is_none() {
|
||||
self.mutations = Some([false; 32])
|
||||
}
|
||||
self.mutations.as_mut().unwrap()[self.default_lane.unwrap()] = value;
|
||||
}
|
||||
pub fn apply_muts(&mut self) {
|
||||
self.value = 0;
|
||||
for lane in 0..self.warp_size {
|
||||
if self.mutations.unwrap()[lane] {
|
||||
self.value |= 1 << lane;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// C-compatible state snapshot for FFI - used for comparing emulator states
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StateSnapshot {
|
||||
pub pc: u32,
|
||||
pub scc: u32,
|
||||
pub vcc: u32,
|
||||
pub exec_mask: u32,
|
||||
pub sgpr: [u32; 128],
|
||||
pub vgpr: [[u32; 256]; 32],
|
||||
}
|
||||
|
||||
impl StateSnapshot {
|
||||
pub fn new() -> Self {
|
||||
Self { pc: 0, scc: 0, vcc: 0, exec_mask: 0, sgpr: [0; 128], vgpr: [[0; 256]; 32] }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VecDataStore {
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl VecDataStore {
|
||||
pub fn new() -> Self {
|
||||
Self { data: Vec::new() }
|
||||
}
|
||||
pub fn write(&mut self, addr: usize, val: u32) {
|
||||
if addr + 4 >= self.data.len() {
|
||||
self.data.resize(self.data.len() + addr + 5, 0);
|
||||
}
|
||||
self.data[addr..addr + 4].iter_mut().enumerate().for_each(|(i, x)| {
|
||||
*x = val.to_le_bytes()[i];
|
||||
});
|
||||
}
|
||||
pub fn write64(&mut self, addr: usize, val: u64) {
|
||||
self.write(addr, (val & 0xffffffff) as u32);
|
||||
self.write(addr + 4, ((val & (0xffffffff << 32)) >> 32) as u32);
|
||||
}
|
||||
pub fn read(&self, addr: usize) -> u32 {
|
||||
let mut bytes: [u8; 4] = [0; 4];
|
||||
bytes.copy_from_slice(&self.data[addr + 0..addr + 4]);
|
||||
u32::from_le_bytes(bytes)
|
||||
}
|
||||
pub fn read64(&mut self, addr: usize) -> u64 {
|
||||
let lsb = self.read(addr);
|
||||
let msb = self.read(addr + 4);
|
||||
((msb as u64) << 32) | lsb as u64
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_state {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_wave_value() {
|
||||
let mut val = WaveValue::new(0b11000000000000011111111111101110, 32);
|
||||
val.default_lane = Some(0);
|
||||
assert!(!val.read());
|
||||
val.default_lane = Some(31);
|
||||
assert!(val.read());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_small() {
|
||||
let mut val = WaveValue::new(0, 1);
|
||||
val.default_lane = Some(0);
|
||||
assert!(!val.read());
|
||||
assert_eq!(val.value, 0);
|
||||
val.set_lane(true);
|
||||
val.apply_muts();
|
||||
assert!(val.read());
|
||||
assert_eq!(val.value, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_small_alt() {
|
||||
let mut val = WaveValue::new(0, 2);
|
||||
val.default_lane = Some(0);
|
||||
assert!(!val.read());
|
||||
assert_eq!(val.value, 0);
|
||||
val.set_lane(true);
|
||||
val.apply_muts();
|
||||
assert!(val.read());
|
||||
assert_eq!(val.value, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_exec() {
|
||||
let warp_size = 32;
|
||||
let val = WaveValue::new(u32::MAX, warp_size);
|
||||
assert_eq!(val.value, u32::MAX);
|
||||
let warp_size = 3;
|
||||
let val = WaveValue::new((1 << warp_size) - 1, warp_size);
|
||||
assert_eq!(val.value, 7)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_toggle_one() {
|
||||
let warp_size = 2;
|
||||
let mut val = WaveValue::new(0b11, warp_size);
|
||||
// 0
|
||||
val.default_lane = Some(0);
|
||||
val.set_lane(false);
|
||||
// 1
|
||||
val.default_lane = Some(1);
|
||||
val.set_lane(true);
|
||||
val.apply_muts();
|
||||
assert_eq!(val.value, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_mutate_small() {
|
||||
let mut val = WaveValue::new(0, 2);
|
||||
val.default_lane = Some(0);
|
||||
assert!(!val.read());
|
||||
assert_eq!(val.value, 0);
|
||||
val.set_lane(true);
|
||||
val.apply_muts();
|
||||
assert!(val.read());
|
||||
assert_eq!(val.value, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_mutations() {
|
||||
let mut val = WaveValue::new(0b10001, 32);
|
||||
val.default_lane = Some(0);
|
||||
val.set_lane(false);
|
||||
assert!(val.mutations.unwrap().iter().all(|x| !x));
|
||||
val.default_lane = Some(1);
|
||||
val.set_lane(true);
|
||||
assert_eq!(val.value, 0b10001);
|
||||
assert_eq!(
|
||||
val.mutations,
|
||||
Some([
|
||||
false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
])
|
||||
);
|
||||
|
||||
val.apply_muts();
|
||||
assert_eq!(val.value, 0b10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write16() {
|
||||
let mut vgpr = VGPR::new();
|
||||
vgpr.default_lane = Some(0);
|
||||
vgpr[0] = 0b11100000000000001111111111111111;
|
||||
vgpr[0].mut_lo16(0b1011101111111110);
|
||||
assert_eq!(vgpr[0], 0b11100000000000001011101111111110);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write16hi() {
|
||||
let mut vgpr = VGPR::new();
|
||||
vgpr.default_lane = Some(0);
|
||||
vgpr[0] = 0b11100000000000001111111111111111;
|
||||
vgpr[0].mut_hi16(0b1011101111111110);
|
||||
assert_eq!(vgpr[0], 0b10111011111111101111111111111111);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vgpr() {
|
||||
let mut vgpr = VGPR::new();
|
||||
vgpr.default_lane = Some(0);
|
||||
vgpr[0] = 42;
|
||||
vgpr.default_lane = Some(10);
|
||||
vgpr[0] = 10;
|
||||
assert_eq!(vgpr.get_lane(0)[0], 42);
|
||||
assert_eq!(vgpr.get_lane(10)[0], 10);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,323 @@
|
||||
use crate::helpers::{colored, DEBUG};
|
||||
use crate::state::{Register, StateSnapshot, VecDataStore, WaveValue, VGPR};
|
||||
use crate::thread::{Thread, END_PRG, SGPR_COUNT};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub const WAVE_SIZE: usize = 32;
|
||||
|
||||
pub struct WorkGroup<'a> {
|
||||
dispatch_dim: u32,
|
||||
id: [u32; 3],
|
||||
lds: VecDataStore,
|
||||
kernel: &'a Vec<u32>,
|
||||
kernel_args: *const u64,
|
||||
launch_bounds: [u32; 3],
|
||||
wave_state: HashMap<usize, WaveState>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct WaveState {
|
||||
scalar_reg: [u32; SGPR_COUNT],
|
||||
scc: u32,
|
||||
vcc: WaveValue,
|
||||
exec: WaveValue,
|
||||
vec_reg: VGPR,
|
||||
pc: usize,
|
||||
sds: HashMap<usize, VecDataStore>,
|
||||
}
|
||||
|
||||
const SYNCS: [u32; 4] = [0xBF89FC07, 0xBC7C0000, 0xBF890007, 0xbFB60003];
|
||||
const S_BARRIER: u32 = 0xBFBD0000;
|
||||
|
||||
/// Context for single-stepping through a wave - holds all mutable state
|
||||
pub struct WaveContext {
|
||||
pub kernel: Vec<u32>,
|
||||
pub scalar_reg: [u32; SGPR_COUNT],
|
||||
pub scc: u32,
|
||||
pub pc: usize,
|
||||
pub vec_reg: VGPR,
|
||||
pub vcc: WaveValue,
|
||||
pub exec: WaveValue,
|
||||
pub lds: VecDataStore,
|
||||
pub sds: HashMap<usize, VecDataStore>,
|
||||
pub n_lanes: usize,
|
||||
}
|
||||
|
||||
impl WaveContext {
|
||||
pub fn new(kernel: Vec<u32>, n_lanes: usize) -> Self {
|
||||
let active = (!0u32).wrapping_shr(32 - (n_lanes as u32));
|
||||
Self {
|
||||
kernel,
|
||||
scalar_reg: [0; SGPR_COUNT],
|
||||
scc: 0,
|
||||
pc: 0,
|
||||
vec_reg: VGPR::new(),
|
||||
vcc: WaveValue::new(0, n_lanes),
|
||||
exec: WaveValue::new(active, n_lanes),
|
||||
lds: VecDataStore::new(),
|
||||
sds: (0..=31).map(|i| (i, VecDataStore::new())).collect(),
|
||||
n_lanes,
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute a single instruction. Returns: 0=continue, -1=endpgm, -2=barrier, 1=done (pc past program), negative=error
|
||||
pub fn step(&mut self) -> i32 {
|
||||
if self.pc >= self.kernel.len() { return 1; }
|
||||
if self.kernel[self.pc] == END_PRG { return -1; }
|
||||
if self.kernel[self.pc] == S_BARRIER { self.pc += 1; return -2; }
|
||||
// Skip sync/nop instructions
|
||||
if SYNCS.contains(&self.kernel[self.pc]) || self.kernel[self.pc] >> 20 == 0xbf8 || self.kernel[self.pc] == 0x7E000000 {
|
||||
self.pc += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut sgpr_co = None;
|
||||
for lane_id in 0..self.n_lanes {
|
||||
self.vec_reg.default_lane = Some(lane_id);
|
||||
self.vcc.default_lane = Some(lane_id);
|
||||
self.exec.default_lane = Some(lane_id);
|
||||
let mut thread = Thread {
|
||||
scalar_reg: &mut self.scalar_reg,
|
||||
scc: &mut self.scc,
|
||||
vec_reg: &mut self.vec_reg,
|
||||
vcc: &mut self.vcc,
|
||||
exec: &mut self.exec,
|
||||
lds: &mut self.lds,
|
||||
sds: &mut self.sds.get_mut(&lane_id).unwrap(),
|
||||
pc_offset: 0,
|
||||
stream: self.kernel[self.pc..].to_vec(),
|
||||
scalar: false,
|
||||
simm: None,
|
||||
warp_size: self.n_lanes,
|
||||
sgpr_co: &mut sgpr_co,
|
||||
};
|
||||
if let Err(e) = thread.interpret() { return e; }
|
||||
if thread.scalar {
|
||||
self.pc = ((self.pc as isize) + 1 + (thread.pc_offset as isize)) as usize;
|
||||
break;
|
||||
}
|
||||
if lane_id == self.n_lanes - 1 {
|
||||
self.pc = ((self.pc as isize) + 1 + (thread.pc_offset as isize)) as usize;
|
||||
}
|
||||
}
|
||||
if self.vcc.mutations.is_some() { self.vcc.apply_muts(); self.vcc.mutations = None; }
|
||||
if self.exec.mutations.is_some() { self.exec.apply_muts(); self.exec.mutations = None; }
|
||||
if let Some((idx, mut wv)) = sgpr_co.take() { wv.apply_muts(); self.scalar_reg[idx] = wv.value; }
|
||||
0
|
||||
}
|
||||
|
||||
pub fn get_snapshot(&self) -> StateSnapshot {
|
||||
let mut snap = StateSnapshot::new();
|
||||
snap.pc = self.pc as u32;
|
||||
snap.scc = self.scc;
|
||||
snap.vcc = self.vcc.value;
|
||||
snap.exec_mask = self.exec.value;
|
||||
snap.sgpr = self.scalar_reg;
|
||||
for lane in 0..32 { snap.vgpr[lane] = self.vec_reg.get_lane(lane); }
|
||||
snap
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> WorkGroup<'a> {
|
||||
pub fn new(dispatch_dim: u32, id: [u32; 3], launch_bounds: [u32; 3], kernel: &'a Vec<u32>, kernel_args: *const u64) -> Self {
|
||||
Self { dispatch_dim, id, kernel, launch_bounds, kernel_args, lds: VecDataStore::new(), wave_state: HashMap::new() }
|
||||
}
|
||||
|
||||
pub fn exec_waves(&mut self) -> Result<(), i32> {
|
||||
let mut threads = vec![];
|
||||
for z in 0..self.launch_bounds[2] {
|
||||
for y in 0..self.launch_bounds[1] {
|
||||
for x in 0..self.launch_bounds[0] {
|
||||
threads.push([x, y, z])
|
||||
}
|
||||
}
|
||||
}
|
||||
let waves = threads.chunks(WAVE_SIZE).collect::<Vec<_>>();
|
||||
|
||||
let mut sync = false;
|
||||
for (i, x) in self.kernel.iter().enumerate() {
|
||||
if i != 0 && *x == S_BARRIER {
|
||||
sync = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0..=(sync as usize) {
|
||||
for w in waves.iter().enumerate() {
|
||||
self.exec_wave(w)?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn exec_wave(&mut self, (wave_id, threads): (usize, &&[[u32; 3]])) -> Result<(), i32> {
|
||||
let (mut scalar_reg, mut scc, mut pc, mut vec_reg, mut vcc, mut exec, mut sds) = match self.wave_state.get(&wave_id) {
|
||||
None => {
|
||||
let mut scalar_reg = [0; SGPR_COUNT];
|
||||
scalar_reg.write64(0, self.kernel_args as u64);
|
||||
|
||||
let [gx, gy, gz] = self.id;
|
||||
match self.dispatch_dim {
|
||||
3 => (scalar_reg[13], scalar_reg[14], scalar_reg[15]) = (gx, gy, gz),
|
||||
2 => (scalar_reg[14], scalar_reg[15]) = (gx, gy),
|
||||
_ => scalar_reg[15] = gx,
|
||||
}
|
||||
|
||||
let mut vec_reg = VGPR::new();
|
||||
for (t, [x, y, z]) in threads.iter().enumerate() {
|
||||
vec_reg.get_lane_mut(t)[0] = match &self.launch_bounds {
|
||||
[_, 1, 1] => *x,
|
||||
_ => (z << 20) | (y << 10) | x,
|
||||
}
|
||||
}
|
||||
|
||||
let vcc = WaveValue::new(0, threads.len());
|
||||
let active = (!0u32).wrapping_shr(32 - (threads.len() as u32));
|
||||
let exec = WaveValue::new(active, threads.len());
|
||||
|
||||
let sds = (0..=31).map(|i| (i, VecDataStore::new())).collect();
|
||||
(scalar_reg, 0, 0, vec_reg, vcc, exec, sds)
|
||||
}
|
||||
|
||||
Some(val) => {
|
||||
let val = val.clone();
|
||||
(val.scalar_reg, val.scc, val.pc, val.vec_reg, val.vcc, val.exec, val.sds)
|
||||
}
|
||||
};
|
||||
|
||||
loop {
|
||||
if self.kernel[pc] == END_PRG {
|
||||
break Ok(());
|
||||
}
|
||||
if self.kernel[pc] == S_BARRIER && self.wave_state.get(&wave_id).is_none() {
|
||||
self.wave_state.insert(wave_id, WaveState { scalar_reg, scc, vec_reg, vcc, exec, pc, sds });
|
||||
break Ok(());
|
||||
}
|
||||
if self.kernel[pc] == S_BARRIER || SYNCS.contains(&self.kernel[pc]) || self.kernel[pc] >> 20 == 0xbf8 || self.kernel[pc] == 0x7E000000 {
|
||||
pc += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut sgpr_co = None;
|
||||
for (lane_id, [x, y, z]) in threads.iter().enumerate() {
|
||||
vec_reg.default_lane = Some(lane_id);
|
||||
vcc.default_lane = Some(lane_id);
|
||||
exec.default_lane = Some(lane_id);
|
||||
if *DEBUG {
|
||||
let lane = format!("{:<2} {:08X} ", lane_id, self.kernel[pc]);
|
||||
let state = match exec.read() {
|
||||
true => "green",
|
||||
false => "gray",
|
||||
};
|
||||
let [id0, id1, id2] = self.id;
|
||||
print!("[{id0:<3} {id1:<3} {id2:<3}] [{x:<3} {y:<3} {z:<3}] {}", colored(&lane, state));
|
||||
}
|
||||
let mut thread = Thread {
|
||||
scalar_reg: &mut scalar_reg,
|
||||
scc: &mut scc,
|
||||
vec_reg: &mut vec_reg,
|
||||
vcc: &mut vcc,
|
||||
exec: &mut exec,
|
||||
lds: &mut self.lds,
|
||||
sds: &mut sds.get_mut(&lane_id).unwrap(),
|
||||
pc_offset: 0,
|
||||
stream: self.kernel[pc..self.kernel.len()].to_vec(),
|
||||
scalar: false,
|
||||
simm: None,
|
||||
warp_size: threads.len(),
|
||||
sgpr_co: &mut sgpr_co,
|
||||
};
|
||||
thread.interpret()?;
|
||||
if *DEBUG {
|
||||
println!();
|
||||
}
|
||||
if thread.scalar {
|
||||
pc = ((pc as isize) + 1 + (thread.pc_offset as isize)) as usize;
|
||||
break;
|
||||
}
|
||||
if lane_id == threads.len() - 1 {
|
||||
pc = ((pc as isize) + 1 + (thread.pc_offset as isize)) as usize;
|
||||
}
|
||||
}
|
||||
|
||||
if vcc.mutations.is_some() {
|
||||
vcc.apply_muts();
|
||||
vcc.mutations = None;
|
||||
}
|
||||
if exec.mutations.is_some() {
|
||||
exec.apply_muts();
|
||||
exec.mutations = None;
|
||||
}
|
||||
if let Some((idx, mut wv)) = sgpr_co.take() {
|
||||
wv.apply_muts();
|
||||
scalar_reg[idx] = wv.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_workgroup {
|
||||
use super::*;
|
||||
|
||||
// TODO: make this generic by adding the assembler
|
||||
fn global_store_sgpr(addr: u64, instructions: Vec<u32>, src: u32) -> Vec<u32> {
|
||||
[
|
||||
instructions,
|
||||
vec![
|
||||
0x7E020200 + src,
|
||||
0x7E0402FF,
|
||||
addr as u32,
|
||||
0x7E0602FF,
|
||||
(addr >> 32) as u32,
|
||||
0xDC6A0000,
|
||||
0x007C0102,
|
||||
],
|
||||
vec![END_PRG],
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_state_vcc() {
|
||||
let mut ret: u32 = 0;
|
||||
let kernel = vec![
|
||||
0xBEEA00FF,
|
||||
0b11111111111111111111111111111111, // initial vcc state
|
||||
0x7E140282,
|
||||
0x7C94010A, // cmp blockDim.x == 2
|
||||
];
|
||||
let addr = (&mut ret as *mut u32) as u64;
|
||||
let kernel = global_store_sgpr(addr, kernel, 106);
|
||||
let mut wg = WorkGroup::new(1, [0, 0, 0], [3, 1, 1], &kernel, [addr].as_ptr());
|
||||
wg.exec_waves().unwrap();
|
||||
assert_eq!(ret, 0b100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_state_exec() {
|
||||
let mut ret: u32 = 0;
|
||||
let kernel = vec![
|
||||
0xBEFE00FF,
|
||||
0b11111111111111111111111111111111,
|
||||
0x7E140282,
|
||||
0x7D9C010A, // cmpx blockDim.x <= 2
|
||||
];
|
||||
let addr = (&mut ret as *mut u32) as u64;
|
||||
let kernel = global_store_sgpr(addr, kernel, 126);
|
||||
let mut wg = WorkGroup::new(1, [0, 0, 0], [4, 1, 1], &kernel, [addr].as_ptr());
|
||||
wg.exec_waves().unwrap();
|
||||
assert_eq!(ret, 0b0111);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wave_value_sgpr_co() {
|
||||
let mut ret: u32 = 0;
|
||||
let kernel = vec![0xBE8D00FF, 0x7FFFFFFF, 0x7E1402FF, u32::MAX, 0xD700000A, 0x0002010A];
|
||||
let addr = (&mut ret as *mut u32) as u64;
|
||||
let kernel = global_store_sgpr(addr, kernel, 0);
|
||||
let mut wg = WorkGroup::new(1, [0, 0, 0], [5, 1, 1], &kernel, [addr].as_ptr());
|
||||
wg.exec_waves().unwrap();
|
||||
assert_eq!(ret, 0b11110);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
# ruff: noqa: F405, F403
|
||||
# allow define from star imports
|
||||
|
||||
import numpy as np
|
||||
import unittest
|
||||
import subprocess, struct, math, functools
|
||||
from tinygrad import Tensor, dtypes, Device
|
||||
from tinygrad.helpers import getenv
|
||||
|
||||
from tinygrad.runtime.autogen.amd.rdna3.ins import *
|
||||
from tinygrad.renderer.amd.asm import waitcnt
|
||||
|
||||
from test.testextra.test_cfg_viz import asm_kernel
|
||||
|
||||
def get_output(asm:list, n_threads:int=1, vdst:VGPR=v[1]):
|
||||
out = Tensor([0]*n_threads, dtype=dtypes.uint32).realize()
|
||||
insts = [
|
||||
s_load_b64(s[0:1], s[0:1], NULL),
|
||||
*asm,
|
||||
v_lshlrev_b32_e32(v[0], 2, v[0]),
|
||||
s_waitcnt(simm16=waitcnt(lgkmcnt=0)),
|
||||
#global_store_b32(v[0], v[1], s[0:1]),
|
||||
global_store_b32(addr=v[0], data=vdst, saddr=s[0:1]),
|
||||
s_endpgm()
|
||||
]
|
||||
out = Tensor.custom_kernel(out, fxn=functools.partial(asm_kernel, name="test", insts=insts, device=out.device, n_threads=n_threads))[0]
|
||||
out.realize()
|
||||
return out.tolist()
|
||||
|
||||
def f16_to_bits(x:float) -> int: return struct.unpack('<H', struct.pack('<e', x))[0]
|
||||
def f32_from_bits(x:int) -> float: return struct.unpack('<f', struct.pack('<I', x))[0]
|
||||
def f32_to_bits(x:float) -> int: return struct.unpack('<I', struct.pack('<f', x))[0]
|
||||
|
||||
@unittest.skipUnless(Device.DEFAULT == "AMD", "tests RDNA3")
|
||||
class TestHW(unittest.TestCase):
|
||||
def setUp(self):
|
||||
if getenv("MOCKGPU"): subprocess.run(["cargo", "build", "--release", "--manifest-path", "./extra/remu/Cargo.toml"], check=True)
|
||||
|
||||
def test_simple_v_mov(self):
|
||||
out = get_output([
|
||||
v_mov_b32_e32(v[1], 2),
|
||||
])
|
||||
self.assertEqual(out, [2])
|
||||
|
||||
def test_simple_s_mov(self):
|
||||
out = get_output([
|
||||
s_mov_b32(s[7], 0x7fffffff),
|
||||
v_mov_b32_e32(v[1], s[7]),
|
||||
])
|
||||
self.assertEqual(out, [0x7fffffff])
|
||||
|
||||
def test_exec_mov(self):
|
||||
out = get_output([
|
||||
v_mov_b32_e32(v[1], 42),
|
||||
s_mov_b32(EXEC_LO, 0b10),
|
||||
v_mov_b32_e32(v[1], 10),
|
||||
s_mov_b32(EXEC_LO, 0b11),
|
||||
], n_threads=2)
|
||||
np.testing.assert_equal(out, [42, 10])
|
||||
|
||||
def test_exec_cmp_vopc(self):
|
||||
out = get_output([
|
||||
s_mov_b32(VCC_LO, 0), # reset vcc
|
||||
v_mov_b32_e32(v[1], 42),
|
||||
v_mov_b32_e32(v[2], 10),
|
||||
s_mov_b32(EXEC_LO, 0b01),
|
||||
v_cmp_ne_u32_e32(v[1], v[2]),
|
||||
s_mov_b32(EXEC_LO, 0b11),
|
||||
v_mov_b32_e32(v[1], VCC_LO),
|
||||
], n_threads=2)[0]
|
||||
np.testing.assert_equal(out, 1)
|
||||
|
||||
def test_exec_cmpx_vop3(self):
|
||||
out = get_output([
|
||||
s_mov_b32(EXEC_LO, 0b11),
|
||||
v_mov_b32_e32(v[1], 42),
|
||||
v_mov_b32_e32(v[2], 10),
|
||||
s_mov_b32(EXEC_LO, 0b01),
|
||||
v_cmpx_ne_u32_e32(v[1], v[2]),
|
||||
s_mov_b32(s[10], EXEC_LO),
|
||||
s_mov_b32(EXEC_LO, 0b11),
|
||||
v_mov_b32_e32(v[1], s[10]),
|
||||
], n_threads=2)[0]
|
||||
np.testing.assert_equal(out & 0b11, 0b01)
|
||||
|
||||
def test_fmac_vop3_modifier(self):
|
||||
init_state = [
|
||||
v_mov_b32_e32(a:=v[1], f16_to_bits(4.0)),
|
||||
v_mov_b32_e32(b:=v[2], f16_to_bits(3.0)),
|
||||
v_mov_b32_e32(c:=v[3], f16_to_bits(2.0)),
|
||||
]
|
||||
def run_fmac(a, b): return get_output(init_state+[v_fmac_f16_e64(c, a, b)], vdst=c)[0]
|
||||
self.assertEqual(run_fmac(a, b), f16_to_bits(14.0))
|
||||
self.assertEqual(run_fmac(a, -b), f16_to_bits(-10.0))
|
||||
self.assertEqual(run_fmac(-a, -b), f16_to_bits(14.0))
|
||||
|
||||
def test_s_abs_i32(self):
|
||||
def check(x, y, dst=s[10], scc=0):
|
||||
for reg,val in [(dst, y), (SCC, scc)]:
|
||||
self.assertEqual(get_output([
|
||||
s_mov_b32(dst, x),
|
||||
s_abs_i32(dst, dst),
|
||||
v_mov_b32_e32(v[1], reg)
|
||||
])[0], val)
|
||||
|
||||
check(0x00000001, 0x00000001, scc=1)
|
||||
check(0x7fffffff, 0x7fffffff, scc=1)
|
||||
check(0x80000000, 0x80000000, scc=1)
|
||||
check(0x80000001, 0x7fffffff, scc=1)
|
||||
check(0x80000002, 0x7ffffffe, scc=1)
|
||||
check(0xffffffff, 0x00000001, scc=1)
|
||||
check(0, 0, scc=0)
|
||||
|
||||
def test_v_rcp_f32_neg_vop3(self):
|
||||
def v_neg_rcp_f32(x:float, y:float):
|
||||
out = get_output([
|
||||
v_mov_b32_e32(v[2], f32_to_bits(x)),
|
||||
v_rcp_f32_e64(v[2], -v[2]),
|
||||
], vdst=v[2])[0]
|
||||
assert out == f32_to_bits(y), f"{f32_from_bits(out)} != {y} / {out} != {f32_to_bits(y)}"
|
||||
|
||||
v_neg_rcp_f32(math.inf, -0.0)
|
||||
v_neg_rcp_f32(-math.inf, 0.0)
|
||||
v_neg_rcp_f32(0.0, -math.inf)
|
||||
v_neg_rcp_f32(-0.0, math.inf)
|
||||
v_neg_rcp_f32(-2.0, 0.5)
|
||||
v_neg_rcp_f32(2.0, -0.5)
|
||||
|
||||
def test_v_cndmask_b32_neg(self):
|
||||
def v_neg(x:float, y:float):
|
||||
out = get_output([
|
||||
v_mov_b32_e32(v[1], f32_to_bits(x)),
|
||||
s_mov_b32(s[10], 1),
|
||||
v_cndmask_b32_e64(v[1], v[1], -v[1], s[10]),
|
||||
])[0]
|
||||
assert out == f32_to_bits(y), f"{f32_from_bits(out)} != {y} / {out} != {f32_to_bits(y)}"
|
||||
|
||||
v_neg(-0.0, 0.0)
|
||||
v_neg(0.0, -0.0)
|
||||
v_neg(2.0, -2.0)
|
||||
v_neg(math.inf, -math.inf)
|
||||
v_neg(-math.inf, math.inf)
|
||||
|
||||
@unittest.skip("how does VOPD work in the dsl")
|
||||
def test_v_subrev_wrap(self):
|
||||
out = get_output([
|
||||
#v_dual_mov_b32(v[1], 0xffffffff, v[2], 0x0),
|
||||
#v_dual_mov_b32(vdstx=v[1], srcx=0xffffffff, vdsty=v[2], srcy=0x0),
|
||||
#VOPD(opx=VOPDOp.V_DUAL_MOV_B32, opy=VOPDOp.V_DUAL_MOV_B32, vdstx=v[1], srcx=0xffffffff, vdsty=v[2], srcy=0x0),
|
||||
v_subrev_co_u32(v[2], VCC_LO, v[2], v[1]),
|
||||
], vdst=v[2])[0]
|
||||
self.assertEqual(out, 0xffff_ffff)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -3,7 +3,7 @@ INSTALL_PATH="${1:-/opt/homebrew/lib}"
|
||||
if [ ! -d "$INSTALL_PATH" ]; then
|
||||
USER=$(whoami)
|
||||
echo "No path $INSTALL_PATH. Will create. Might need your password..."
|
||||
echo "You can stop now and provide any location as an argument where you want to save the library (note, that not default locations should be in LD_LIBRARY_PATH, so tinygrad can find it)."
|
||||
echo "You can stop now and provide any location as an argument where you want to save the libs (note, that not default locations should be in LD_LIBRARY_PATH, so tinygrad can find the libs)."
|
||||
echo "Press any key or symbol to continue..."
|
||||
read -n 1 -s
|
||||
|
||||
@@ -11,6 +11,11 @@ if [ ! -d "$INSTALL_PATH" ]; then
|
||||
sudo chown -R "$USER":staff "$INSTALL_PATH"
|
||||
fi
|
||||
|
||||
# Download libremu.dylib
|
||||
curl -s https://api.github.com/repos/Qazalin/remu/releases/latest | \
|
||||
jq -r '.assets[] | select(.name == "libremu.dylib").browser_download_url' | \
|
||||
xargs curl -L -o $INSTALL_PATH/libremu.dylib
|
||||
|
||||
# Download libamd_comgr.dylib
|
||||
curl -s https://api.github.com/repos/tinygrad/amdcomgr_dylib/releases/latest | \
|
||||
jq -r '.assets[] | select(.name == "libamd_comgr.dylib").browser_download_url' | \
|
||||
|
||||
+6
-7
@@ -136,8 +136,7 @@ def print_data(data:dict) -> None:
|
||||
|
||||
def main() -> None:
|
||||
import tinygrad.viz.serve as viz
|
||||
from tinygrad.uop.ops import RewriteTrace
|
||||
data = viz.VizData()
|
||||
viz.ctxs = []
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--profile', type=pathlib.Path, metavar="PATH", help='Path to profile (optional file, default: latest profile)',
|
||||
@@ -148,24 +147,24 @@ def main() -> None:
|
||||
|
||||
with args.profile.open("rb") as f: profile = pickle.load(f)
|
||||
|
||||
viz.get_profile(profile, data=data)
|
||||
viz.get_profile(profile)
|
||||
|
||||
# List all kernels
|
||||
if args.kernel is None:
|
||||
for c in data.ctxs:
|
||||
for c in viz.ctxs:
|
||||
print(c["name"])
|
||||
for s in c["steps"]: print(" "+s["name"])
|
||||
return None
|
||||
|
||||
# Find kernel trace
|
||||
trace = next((c for c in data.ctxs if c["name"] == f"SQTT {args.kernel}"), None)
|
||||
trace = next((c for c in viz.ctxs if c["name"] == f"Exec {args.kernel}"), None)
|
||||
if not trace: raise RuntimeError(f"no matching trace for {args.kernel}")
|
||||
n = 0
|
||||
for s in trace["steps"]:
|
||||
if "PKTS" in s["name"]: continue
|
||||
print(s["name"])
|
||||
ret = viz.get_render(data, s["query"])
|
||||
print_data(ret)
|
||||
data = viz.get_render(s["query"])
|
||||
print_data(data)
|
||||
n += 1
|
||||
if n > args.n: break
|
||||
|
||||
|
||||
+14
-13
@@ -52,15 +52,16 @@ def get(data:dict, key:str):
|
||||
raise RuntimeError(f'item "{key}" not found in list'+(f", did you mean {match[0]!r}?" if match else ''))
|
||||
|
||||
def main(args) -> None:
|
||||
viz.load_rewrites(viz_data:=viz.VizData(viz.load_pickle(args.rewrites_path, default=RewriteTrace([], [], {}))))
|
||||
viz.trace = viz.load_pickle(args.rewrites_path, default=RewriteTrace([], [], {}))
|
||||
viz.ctxs = viz.get_rewrites(viz.trace)
|
||||
|
||||
def format_colored(s:str) -> str: return ansistrip(s) if args.no_color else s
|
||||
|
||||
if args.profile:
|
||||
events:list = viz.load_pickle(args.profile_path, default=[])
|
||||
if (profile_bytes:=viz.get_profile(viz_data, events)) is None: raise RuntimeError(f"empty profile in {args.profile_path}")
|
||||
if (profile_bytes:=viz.get_profile(events)) is None: raise RuntimeError(f"empty profile in {args.profile_path}")
|
||||
profile = decode_profile(profile_bytes)
|
||||
profile["layout"].update([(f'{c["name"][5:]}{" SQTT" if s["name"].endswith("PKTS") else ""} {s["name"]}', s["data"]) for c in viz_data.ctxs
|
||||
profile["layout"].update([(f'{c["name"][5:]}{" SQTT" if s["name"].endswith("PKTS") else ""} {s["name"]}', s["data"]) for c in viz.ctxs
|
||||
if c["name"].startswith("SQTT") for s in c["steps"] if s["name"].endswith(("PMC", "PKTS"))])
|
||||
if args.src is None:
|
||||
for k in profile["layout"]:
|
||||
@@ -102,10 +103,10 @@ def main(args) -> None:
|
||||
|
||||
# ** PMC printer
|
||||
if "PMC" in args.src:
|
||||
pmc = viz.unpack_pmc(data)
|
||||
cols = pmc["cols"]
|
||||
table = viz.unpack_pmc(data[0])
|
||||
cols = table["cols"]
|
||||
rows:list = []
|
||||
for r in pmc["rows"]:
|
||||
for r in table["rows"]:
|
||||
if args.item is None: rows.append(r[:2])
|
||||
elif args.item == r[0]:
|
||||
rows = r[2]["rows"] if len(r) > 2 else [r[:2]]
|
||||
@@ -131,17 +132,17 @@ def main(args) -> None:
|
||||
if agg and total > 0:
|
||||
from tabulate import tabulate
|
||||
items = sorted(agg.items(), key=lambda kv:kv[1][0], reverse=True)
|
||||
num_rows = 20
|
||||
table = [[format_colored(name), time_to_str(t, w=9), c, f"{(t/total*100.0):.2f}%"] for name,(t,c) in items[:num_rows]]
|
||||
if items[num_rows:]:
|
||||
other_t = sum(t for _,(t,_) in items[num_rows:])
|
||||
other_c = sum(c for _,(_,c) in items[num_rows:])
|
||||
rows = 20
|
||||
table = [[format_colored(name), time_to_str(t, w=9), c, f"{(t/total*100.0):.2f}%"] for name,(t,c) in items[:rows]]
|
||||
if items[rows:]:
|
||||
other_t = sum(t for _,(t,_) in items[rows:])
|
||||
other_c = sum(c for _,(_,c) in items[rows:])
|
||||
table.append(["Other", time_to_str(other_t, w=9), other_c, f"{(other_t/total*100.0):.2f}%"])
|
||||
print(tabulate(table, headers=["name", "total", "count", "pct"], tablefmt="github"))
|
||||
return None
|
||||
|
||||
# ** Graph rewrites printer
|
||||
rewrites = {c["name"]:{s["name"]:s for s in c["steps"]} for c in viz_data.ctxs if c.get("steps")}
|
||||
rewrites = {c["name"]:{s["name"]:s for s in c["steps"]} for c in viz.ctxs if c.get("steps")}
|
||||
if args.src is None:
|
||||
for k in rewrites: print(f" {format_colored(k)}")
|
||||
return None
|
||||
@@ -149,7 +150,7 @@ def main(args) -> None:
|
||||
if args.item is None:
|
||||
for k,v in steps.items(): print(" "*v["depth"]+k+(f" - {v['match_count']}" if v.get('match_count', 0) else ''))
|
||||
else:
|
||||
data = viz.get_render(data, get(steps, args.item)["query"])
|
||||
data = viz.get_render(get(steps, args.item)["query"])
|
||||
if isinstance(data.get("value"), Iterator):
|
||||
for m in data["value"]:
|
||||
if m.get("uop"): print(f"Input UOp:\n{m['uop']}")
|
||||
|
||||
+2
-2
@@ -50,8 +50,8 @@ tinygrad = ["py.typed"]
|
||||
|
||||
|
||||
[project.optional-dependencies]
|
||||
# arm = ["unicorn"]
|
||||
# triton = ["triton-nightly>=2.1.0.dev20231014192330"]
|
||||
arm = ["unicorn"]
|
||||
triton = ["triton-nightly>=2.1.0.dev20231014192330"]
|
||||
linting = [
|
||||
"pylint",
|
||||
"mypy==1.19.1",
|
||||
|
||||
+16
-6
@@ -2,7 +2,6 @@
|
||||
from __future__ import annotations
|
||||
import re
|
||||
from typing import Callable
|
||||
from test.amd.helpers import decode_dpp16
|
||||
from tinygrad.renderer.amd.dsl import Inst, Reg
|
||||
|
||||
# Special register mappings for disassembly
|
||||
@@ -839,11 +838,22 @@ def _disasm_vop1_sdwa(inst) -> str:
|
||||
|
||||
def _decode_dpp(dpp: int) -> str:
|
||||
"""Decode DPP control value to string."""
|
||||
op, arg = decode_dpp16(dpp)
|
||||
if op == "quad_perm": return f"quad_perm:[{','.join(str(x) for x in arg)}]"
|
||||
if op in ("row_mirror", "row_half_mirror"): return op
|
||||
if op == "dpp": return f"dpp:{arg:#x}"
|
||||
return f"{op}:{arg}"
|
||||
if dpp < 0x100: return f"quad_perm:[{dpp&3},{(dpp>>2)&3},{(dpp>>4)&3},{(dpp>>6)&3}]"
|
||||
if 0x100 <= dpp <= 0x10f: return f"row_shl:{dpp & 0xf}"
|
||||
if 0x110 <= dpp <= 0x11f: return f"row_shr:{dpp & 0xf}"
|
||||
if 0x120 <= dpp <= 0x12f: return f"row_ror:{dpp & 0xf}"
|
||||
if dpp == 0x130: return "wave_shl:1"
|
||||
if dpp == 0x134: return "wave_rol:1"
|
||||
if dpp == 0x138: return "wave_shr:1"
|
||||
if dpp == 0x13c: return "wave_ror:1"
|
||||
if dpp == 0x140: return "row_mirror"
|
||||
if dpp == 0x141: return "row_half_mirror"
|
||||
if dpp == 0x142: return "row_bcast:15"
|
||||
if dpp == 0x143: return "row_bcast:31"
|
||||
if 0x150 <= dpp <= 0x15f: return f"row_newbcast:{dpp & 0xf}"
|
||||
if 0x160 <= dpp <= 0x16f: return f"row_share:{dpp & 0xf}"
|
||||
if 0x170 <= dpp <= 0x17f: return f"row_xmask:{dpp & 0xf}"
|
||||
return f"dpp:{dpp:#x}"
|
||||
|
||||
def _disasm_vop1_dpp(inst) -> str:
|
||||
name = inst.op_name.lower().replace('_e32', '')
|
||||
|
||||
@@ -12,19 +12,8 @@ ARCH_TO_TARGET:dict[str, list[str]] = {
|
||||
|
||||
TARGET_TO_ARCH:dict[str, str] = {t:arch for arch,targets in ARCH_TO_TARGET.items() for t in targets}
|
||||
|
||||
_DPP16_RANGE_OPS = {0x100: "row_shl", 0x110: "row_shr", 0x120: "row_ror", 0x150: "row_newbcast", 0x160: "row_share", 0x170: "row_xmask"}
|
||||
_DPP16_EXACT_OPS = {0x130: ("wave_shl", 1), 0x134: ("wave_rol", 1), 0x138: ("wave_shr", 1), 0x13c: ("wave_ror", 1),
|
||||
0x140: ("row_mirror", 0), 0x141: ("row_half_mirror", 0), 0x142: ("row_bcast", 15), 0x143: ("row_bcast", 31)}
|
||||
|
||||
def get_target(arch:str) -> str: return ARCH_TO_TARGET[arch][0]
|
||||
|
||||
def decode_dpp16(dpp: int) -> tuple[str, int | tuple[int, int, int, int]]:
|
||||
"""Decode a DPP16 control word into a symbolic operation and argument."""
|
||||
if dpp < 0x100: return "quad_perm", ((dpp >> 0) & 0x3, (dpp >> 2) & 0x3, (dpp >> 4) & 0x3, (dpp >> 6) & 0x3)
|
||||
if dpp in _DPP16_EXACT_OPS: return _DPP16_EXACT_OPS[dpp]
|
||||
if (base := dpp & 0x1f0) in _DPP16_RANGE_OPS: return _DPP16_RANGE_OPS[base], dpp & 0xf
|
||||
return "dpp", dpp
|
||||
|
||||
def get_mattr(arch:str) -> str:
|
||||
return {"rdna3":"+real-true16,+wavefrontsize32", "rdna4":"+real-true16,+wavefrontsize32", "cdna":"+wavefrontsize64"}[arch]
|
||||
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
"""Tests for DPP16 source swizzles.
|
||||
|
||||
These instructions trap in the default wave32 hw helper, so this file uses a
|
||||
minimal wave64 lane-store harness and compares emulator vs hardware directly
|
||||
when USE_HW=1.
|
||||
"""
|
||||
import ctypes, unittest
|
||||
from tinygrad.runtime.autogen.amd.rdna3.ins import *
|
||||
from tinygrad.helpers import flat_mv
|
||||
from test.amd.hw.helpers import USE_HW, assemble
|
||||
from test.mockgpu.amd.emu import run_asm
|
||||
|
||||
WAVE64 = 64
|
||||
|
||||
def _wave64_code(instructions: list, out_reg: int = 1) -> bytes:
|
||||
return assemble([
|
||||
s_mov_b32(s[80], s[0]),
|
||||
s_mov_b32(s[81], s[1]),
|
||||
v_mov_b32_e32(v[255], v[0]),
|
||||
*instructions,
|
||||
s_load_b64(s[92:93], s[80:81], 0, soffset=NULL),
|
||||
s_waitcnt(0),
|
||||
v_lshlrev_b32_e32(v[240], 2, v[255]),
|
||||
global_store_b32(addr=v[240], data=v[out_reg], saddr=s[92:93], offset=0),
|
||||
s_endpgm(),
|
||||
])
|
||||
|
||||
def _run_wave64_emu(instructions: list, out_reg: int = 1) -> list[int]:
|
||||
out_buf = (ctypes.c_uint32 * WAVE64)(*([0] * WAVE64))
|
||||
args = (ctypes.c_uint64 * 1)(ctypes.addressof(out_buf))
|
||||
code = _wave64_code(instructions, out_reg)
|
||||
kernel_buf = (ctypes.c_char * len(code)).from_buffer_copy(code)
|
||||
rsrc2 = 0x19c | (128 << 15)
|
||||
scratch_size = 0x10000
|
||||
result = run_asm(ctypes.addressof(kernel_buf), len(code), 1, 1, 1, WAVE64, 1, 1, ctypes.addressof(args), rsrc2, scratch_size)
|
||||
assert result == 0, f"run_asm failed with {result}"
|
||||
return list(out_buf)
|
||||
|
||||
def _run_wave64_hw(instructions: list, out_reg: int = 1) -> list[int]:
|
||||
from tinygrad.device import Device
|
||||
from tinygrad.runtime.ops_amd import AMDProgram
|
||||
from tinygrad.runtime.support.compiler_amd import HIPCompiler
|
||||
|
||||
dev = Device["AMD"]
|
||||
compiler = HIPCompiler(dev.arch) # type: ignore[attr-defined]
|
||||
code = _wave64_code(instructions, out_reg)
|
||||
byte_str = ', '.join(f'0x{b:02x}' for b in code)
|
||||
asm_src = f""".text
|
||||
.globl test
|
||||
.p2align 8
|
||||
.type test,@function
|
||||
test:
|
||||
.byte {byte_str}
|
||||
|
||||
.rodata
|
||||
.p2align 6
|
||||
.amdhsa_kernel test
|
||||
.amdhsa_next_free_vgpr 256
|
||||
.amdhsa_next_free_sgpr 96
|
||||
.amdhsa_user_sgpr_kernarg_segment_ptr 1
|
||||
.amdhsa_kernarg_size 8
|
||||
.amdhsa_group_segment_fixed_size 65536
|
||||
.amdhsa_private_segment_fixed_size 65536
|
||||
.amdhsa_enable_private_segment 1
|
||||
.end_amdhsa_kernel
|
||||
|
||||
.amdgpu_metadata
|
||||
---
|
||||
amdhsa.version:
|
||||
- 1
|
||||
- 0
|
||||
amdhsa.kernels:
|
||||
- .name: test
|
||||
.symbol: test.kd
|
||||
.kernarg_segment_size: 8
|
||||
.group_segment_fixed_size: 65536
|
||||
.private_segment_fixed_size: 65536
|
||||
.kernarg_segment_align: 8
|
||||
.wavefront_size: 64
|
||||
.sgpr_count: 96
|
||||
.vgpr_count: 256
|
||||
.max_flat_workgroup_size: 1024
|
||||
...
|
||||
.end_amdgpu_metadata
|
||||
"""
|
||||
lib = compiler.compile(asm_src)
|
||||
prg = AMDProgram(dev, "test", lib) # type: ignore[arg-type]
|
||||
out_gpu = dev.allocator.alloc(WAVE64 * 4)
|
||||
prg(out_gpu, global_size=(1, 1, 1), local_size=(WAVE64, 1, 1), wait=True)
|
||||
out = bytearray(WAVE64 * 4)
|
||||
dev.allocator._copyout(flat_mv(memoryview(out)), out_gpu)
|
||||
return [int.from_bytes(out[i*4:(i+1)*4], 'little') for i in range(WAVE64)]
|
||||
|
||||
def run_wave64(instructions: list, out_reg: int = 1) -> list[int]:
|
||||
emu = _run_wave64_emu(instructions, out_reg)
|
||||
if not USE_HW: return emu
|
||||
hw = _run_wave64_hw(instructions, out_reg)
|
||||
if emu != hw:
|
||||
diffs = [f"lane {i}: emu=0x{e:08x} hw=0x{h:08x}" for i, (e, h) in enumerate(zip(emu, hw)) if e != h]
|
||||
raise AssertionError("Emulator vs Hardware mismatch:\n" + '\n'.join(diffs[:16]))
|
||||
return hw
|
||||
|
||||
class TestDPP16(unittest.TestCase):
|
||||
def _run_copy(self, dpp: int, *, row_mask: int = 0xf, bank_mask: int = 0xf, bc: int = 1, dst_seed: int | None = None) -> list[int]:
|
||||
instructions = [
|
||||
v_mul_u32_u24_e32(v[0], 10, v[255]),
|
||||
v_add_nc_u32_e32(v[0], 3, v[0]),
|
||||
]
|
||||
if dst_seed is not None: instructions.append(v_mov_b32_e32(v[1], dst_seed))
|
||||
instructions += [v_mov_b32_e32(v[2], 0), v_or_b32_e32(v[1], DPP, v[2], vsrc0=v[0], dpp=dpp, row_mask=row_mask, bank_mask=bank_mask, bc=bc)]
|
||||
return run_wave64(instructions)
|
||||
|
||||
def test_quad_perm_reverse(self):
|
||||
out = self._run_copy(0x1b)
|
||||
self.assertEqual(out[0], 33)
|
||||
self.assertEqual(out[1], 23)
|
||||
self.assertEqual(out[2], 13)
|
||||
self.assertEqual(out[3], 3)
|
||||
self.assertEqual(out[4], 73)
|
||||
|
||||
def test_row_shl(self):
|
||||
out = self._run_copy(0x101)
|
||||
self.assertEqual(out[0], 13)
|
||||
self.assertEqual(out[7], 83)
|
||||
self.assertEqual(out[14], 153)
|
||||
self.assertEqual(out[15], 0)
|
||||
self.assertEqual(out[16], 173)
|
||||
|
||||
def test_row_shr(self):
|
||||
out = self._run_copy(0x111)
|
||||
self.assertEqual(out[0], 0)
|
||||
self.assertEqual(out[1], 3)
|
||||
self.assertEqual(out[8], 73)
|
||||
self.assertEqual(out[15], 143)
|
||||
self.assertEqual(out[16], 0)
|
||||
self.assertEqual(out[17], 163)
|
||||
|
||||
def test_row_ror(self):
|
||||
out = self._run_copy(0x121)
|
||||
self.assertEqual(out[0], 153)
|
||||
self.assertEqual(out[1], 3)
|
||||
self.assertEqual(out[15], 143)
|
||||
self.assertEqual(out[16], 313)
|
||||
|
||||
def test_row_mirror(self):
|
||||
out = self._run_copy(0x140)
|
||||
self.assertEqual(out[0], 153)
|
||||
self.assertEqual(out[5], 103)
|
||||
self.assertEqual(out[8], 73)
|
||||
self.assertEqual(out[16], 313)
|
||||
|
||||
def test_row_half_mirror(self):
|
||||
out = self._run_copy(0x141)
|
||||
self.assertEqual(out[0], 73)
|
||||
self.assertEqual(out[7], 3)
|
||||
self.assertEqual(out[8], 153)
|
||||
self.assertEqual(out[15], 83)
|
||||
self.assertEqual(out[16], 233)
|
||||
|
||||
def test_row_mask(self):
|
||||
out = self._run_copy(0x101, row_mask=0x5, dst_seed=0xDEADBEEF)
|
||||
self.assertEqual(out[0], 13)
|
||||
self.assertEqual(out[15], 0)
|
||||
self.assertEqual(out[16], 0xDEADBEEF)
|
||||
self.assertEqual(out[32], 333)
|
||||
self.assertEqual(out[47], 0)
|
||||
self.assertEqual(out[48], 0xDEADBEEF)
|
||||
|
||||
def test_bank_mask(self):
|
||||
out = self._run_copy(0x101, bank_mask=0x5, dst_seed=0xDEADBEEF)
|
||||
self.assertEqual(out[0], 13)
|
||||
self.assertEqual(out[3], 43)
|
||||
self.assertEqual(out[4], 0xDEADBEEF)
|
||||
self.assertEqual(out[8], 93)
|
||||
self.assertEqual(out[12], 0xDEADBEEF)
|
||||
|
||||
class TestVOPCDPP16(unittest.TestCase):
|
||||
def test_row_bcast15_materializes_vcc(self):
|
||||
out = run_wave64([
|
||||
v_mov_b32_e32(v[0], v[255]),
|
||||
v_cmp_eq_u32_e32(DPP, v[0], vsrc0=v[0], dpp=0x142, row_mask=0xf, bank_mask=0xf, bc=1),
|
||||
v_mov_b32_e32(v[2], 0),
|
||||
v_mov_b32_e32(v[3], 1),
|
||||
v_cndmask_b32_e32(v[1], v[2], v[3]),
|
||||
])
|
||||
for lane in (0, 16, 32, 48): self.assertEqual(out[lane], 1)
|
||||
for lane in (1, 15, 31, 47, 63): self.assertEqual(out[lane], 0)
|
||||
@@ -833,6 +833,8 @@ class TestDsPermute(unittest.TestCase):
|
||||
src_lane = lane ^ 1
|
||||
expected = src_lane + 100
|
||||
self.assertEqual(st.vgpr[lane][2], expected, f"lane {lane}: expected v[1] from lane {src_lane} = {expected}, got {st.vgpr[lane][2]}")
|
||||
|
||||
|
||||
class TestDSSubDword(unittest.TestCase):
|
||||
"""Tests for sub-dword DS operations (ds_store_b16, ds_store_b16_d16_hi)."""
|
||||
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
"""RDNA4 V_PERMLANE16_VAR_B32 / V_PERMLANEX16_VAR_B32 coverage.
|
||||
|
||||
Exercises the generated pcode path end-to-end in the emulator and compares against
|
||||
real RDNA4 hardware when USE_HW=1.
|
||||
"""
|
||||
import ctypes, unittest
|
||||
import tinygrad.runtime.autogen.amd.rdna4.ins as r4
|
||||
from tinygrad.helpers import flat_mv
|
||||
from tinygrad.renderer.amd.dsl import NULL
|
||||
from test.amd.hw.helpers import USE_HW, assemble
|
||||
from test.mockgpu.amd.emu import run_asm
|
||||
|
||||
LANES = 32
|
||||
|
||||
def _code(instructions: list, out_reg: int = 2) -> bytes:
|
||||
return assemble([
|
||||
r4.s_mov_b32(r4.s[80], r4.s[0]),
|
||||
r4.s_mov_b32(r4.s[81], r4.s[1]),
|
||||
r4.v_mov_b32_e32(r4.v[255], r4.v[0]),
|
||||
*instructions,
|
||||
r4.s_load_b64(r4.s[92:93], r4.s[80:81], soffset=NULL),
|
||||
r4.s_wait_kmcnt(simm16=0),
|
||||
r4.v_lshlrev_b32_e32(r4.v[240], 2, r4.v[255]),
|
||||
r4.v_mov_b32_e32(r4.v[241], 0),
|
||||
r4.global_store_b32(vaddr=r4.v[240:241], saddr=r4.s[92:93], vsrc=r4.v[out_reg]),
|
||||
r4.s_endpgm(),
|
||||
])
|
||||
|
||||
def _run_emu(instructions: list, out_reg: int = 2) -> list[int]:
|
||||
out_buf = (ctypes.c_uint32 * LANES)(*([0] * LANES))
|
||||
args = (ctypes.c_uint64 * 1)(ctypes.addressof(out_buf))
|
||||
code = _code(instructions, out_reg)
|
||||
kernel_buf = (ctypes.c_char * len(code)).from_buffer_copy(code)
|
||||
result = run_asm(ctypes.addressof(kernel_buf), len(code), 1, 1, 1, LANES, 1, 1, ctypes.addressof(args), arch='rdna4')
|
||||
assert result == 0, f"run_asm failed with {result}"
|
||||
return list(out_buf)
|
||||
|
||||
def _run_hw(instructions: list, out_reg: int = 2) -> list[int]:
|
||||
from tinygrad.device import Device
|
||||
from tinygrad.runtime.ops_amd import AMDProgram
|
||||
from tinygrad.runtime.support.compiler_amd import HIPCompiler
|
||||
|
||||
dev = Device['AMD']
|
||||
if not dev.arch.startswith('gfx12'): raise unittest.SkipTest('requires RDNA4 hardware')
|
||||
compiler = HIPCompiler(dev.arch)
|
||||
code = _code(instructions, out_reg)
|
||||
byte_str = ', '.join(f'0x{b:02x}' for b in code)
|
||||
asm_src = f""".text
|
||||
.globl test
|
||||
.p2align 8
|
||||
.type test,@function
|
||||
test:
|
||||
.byte {byte_str}
|
||||
|
||||
.rodata
|
||||
.p2align 6
|
||||
.amdhsa_kernel test
|
||||
.amdhsa_next_free_vgpr 256
|
||||
.amdhsa_next_free_sgpr 96
|
||||
.amdhsa_wavefront_size32 1
|
||||
.amdhsa_user_sgpr_kernarg_segment_ptr 1
|
||||
.amdhsa_kernarg_size 8
|
||||
.amdhsa_group_segment_fixed_size 65536
|
||||
.amdhsa_private_segment_fixed_size 65536
|
||||
.amdhsa_enable_private_segment 1
|
||||
.end_amdhsa_kernel
|
||||
|
||||
.amdgpu_metadata
|
||||
---
|
||||
amdhsa.version:
|
||||
- 1
|
||||
- 0
|
||||
amdhsa.kernels:
|
||||
- .name: test
|
||||
.symbol: test.kd
|
||||
.kernarg_segment_size: 8
|
||||
.group_segment_fixed_size: 65536
|
||||
.private_segment_fixed_size: 65536
|
||||
.kernarg_segment_align: 8
|
||||
.wavefront_size: 32
|
||||
.sgpr_count: 96
|
||||
.vgpr_count: 256
|
||||
.max_flat_workgroup_size: 1024
|
||||
...
|
||||
.end_amdgpu_metadata
|
||||
"""
|
||||
lib = compiler.compile(asm_src)
|
||||
prg = AMDProgram(dev, 'test', lib)
|
||||
out_gpu = dev.allocator.alloc(LANES * 4)
|
||||
prg(out_gpu, global_size=(1, 1, 1), local_size=(LANES, 1, 1), wait=True)
|
||||
out = bytearray(LANES * 4)
|
||||
dev.allocator._copyout(flat_mv(memoryview(out)), out_gpu)
|
||||
return [int.from_bytes(out[i*4:(i+1)*4], 'little') for i in range(LANES)]
|
||||
|
||||
def run_rdna4(instructions: list, out_reg: int = 2) -> list[int]:
|
||||
emu = _run_emu(instructions, out_reg)
|
||||
if not USE_HW: return emu
|
||||
hw = _run_hw(instructions, out_reg)
|
||||
if emu != hw:
|
||||
diffs = [f"lane {i}: emu=0x{e:08x} hw=0x{h:08x}" for i, (e, h) in enumerate(zip(emu, hw)) if e != h]
|
||||
raise AssertionError("Emulator vs Hardware mismatch:\n" + '\n'.join(diffs[:16]))
|
||||
return hw
|
||||
|
||||
class TestPermlaneVarRDNA4(unittest.TestCase):
|
||||
def test_v_permlane16_var_b32_reverse(self):
|
||||
out = run_rdna4([
|
||||
r4.v_mov_b32_e32(r4.v[0], r4.v[255]),
|
||||
r4.v_xor_b32_e32(r4.v[1], 15, r4.v[255]),
|
||||
r4.v_permlane16_var_b32(r4.v[2], r4.v[0], r4.v[1]),
|
||||
])
|
||||
self.assertEqual(out[0], 15)
|
||||
self.assertEqual(out[5], 10)
|
||||
self.assertEqual(out[15], 0)
|
||||
self.assertEqual(out[16], 31)
|
||||
self.assertEqual(out[21], 26)
|
||||
self.assertEqual(out[31], 16)
|
||||
|
||||
def test_v_permlanex16_var_b32_cross_row(self):
|
||||
out = run_rdna4([
|
||||
r4.v_mov_b32_e32(r4.v[0], r4.v[255]),
|
||||
r4.v_mov_b32_e32(r4.v[1], r4.v[255]),
|
||||
r4.v_permlanex16_var_b32(r4.v[2], r4.v[0], r4.v[1]),
|
||||
])
|
||||
self.assertEqual(out[0], 16)
|
||||
self.assertEqual(out[5], 21)
|
||||
self.assertEqual(out[15], 31)
|
||||
self.assertEqual(out[16], 0)
|
||||
self.assertEqual(out[21], 5)
|
||||
self.assertEqual(out[31], 15)
|
||||
@@ -1,35 +0,0 @@
|
||||
"""Tests for VINTERP instructions."""
|
||||
import unittest
|
||||
from test.amd.hw.helpers import *
|
||||
|
||||
class TestVInterp(unittest.TestCase):
|
||||
def test_v_interp_p10_f32(self):
|
||||
instructions = [
|
||||
v_mov_b32_e32(v[10], v[255]),
|
||||
v_cvt_f32_u32_e32(v[1], v[10]),
|
||||
s_mov_b32(s[0], f2i(100.0)),
|
||||
v_add_f32_e32(v[1], s[0], v[1]),
|
||||
v_cvt_f32_u32_e32(v[3], v[10]),
|
||||
s_mov_b32(s[1], f2i(10.0)),
|
||||
v_add_f32_e32(v[3], s[1], v[3]),
|
||||
s_mov_b32(s[2], f2i(2.0)),
|
||||
v_interp_p10_f32(v[4], v[1], s[2], v[3]),
|
||||
]
|
||||
st = run_program(instructions, n_lanes=8)
|
||||
for lane in range(4): self.assertAlmostEqual(i2f(st.vgpr[lane][4]), 212.0, places=5)
|
||||
for lane in range(4, 8): self.assertAlmostEqual(i2f(st.vgpr[lane][4]), 224.0, places=5)
|
||||
|
||||
def test_v_interp_p10_f16_f32(self):
|
||||
instructions = [
|
||||
v_mov_b32_e32(v[10], v[255]),
|
||||
v_cvt_f32_u32_e32(v[11], v[10]),
|
||||
v_cvt_f16_f32_e32(v[1], v[11]),
|
||||
s_mov_b32(s[0], f2i(10.0)),
|
||||
v_add_f32_e32(v[12], s[0], v[11]),
|
||||
v_cvt_f16_f32_e32(v[3], v[12]),
|
||||
s_mov_b32(s[1], f2i(2.0)),
|
||||
v_interp_p10_f16_f32(v[4], v[1], s[1], v[3]),
|
||||
]
|
||||
st = run_program(instructions, n_lanes=8)
|
||||
for lane in range(4): self.assertAlmostEqual(i2f(st.vgpr[lane][4]), 12.0, places=5)
|
||||
for lane in range(4, 8): self.assertAlmostEqual(i2f(st.vgpr[lane][4]), 24.0, places=5)
|
||||
@@ -30,17 +30,6 @@ class TestBasicArithmetic(unittest.TestCase):
|
||||
st = run_program(instructions, n_lanes=1)
|
||||
self.assertAlmostEqual(i2f(st.vgpr[0][2]), 8.0, places=5)
|
||||
|
||||
def test_v_add_f32_dpp_row_shl(self):
|
||||
"""V_ADD_F32 DPP row_shl swizzles src0 before the add."""
|
||||
instructions = [
|
||||
v_cvt_f32_u32_e32(v[0], v[255]),
|
||||
v_add_f32_e32(v[1], DPP, v[0], vsrc0=v[0], dpp=0x101, row_mask=0xf, bank_mask=0xf, bc=1),
|
||||
]
|
||||
st = run_program(instructions, n_lanes=16)
|
||||
self.assertAlmostEqual(i2f(st.vgpr[0][1]), 1.0, places=5)
|
||||
self.assertAlmostEqual(i2f(st.vgpr[1][1]), 3.0, places=5)
|
||||
self.assertAlmostEqual(i2f(st.vgpr[14][1]), 29.0, places=5)
|
||||
|
||||
def test_v_fmac_f32(self):
|
||||
"""V_FMAC_F32: d = d + a*b using inline constants."""
|
||||
instructions = [
|
||||
|
||||
+16
-35
@@ -20,28 +20,6 @@ class TestFMA(unittest.TestCase):
|
||||
st = run_program(instructions, n_lanes=1)
|
||||
self.assertAlmostEqual(i2f(st.vgpr[0][3]), 9.0, places=5)
|
||||
|
||||
def test_v_mullit_f32_basic(self):
|
||||
"""V_MULLIT_F32 multiplies when the guard input is valid."""
|
||||
instructions = [
|
||||
v_mov_b32_e32(v[0], f2i(2.0)),
|
||||
v_mov_b32_e32(v[1], f2i(3.0)),
|
||||
v_mov_b32_e32(v[2], f2i(1.0)),
|
||||
v_mullit_f32(v[3], v[0], v[1], v[2]),
|
||||
]
|
||||
st = run_program(instructions, n_lanes=1)
|
||||
self.assertAlmostEqual(i2f(st.vgpr[0][3]), 6.0, places=5)
|
||||
|
||||
def test_v_mullit_f32_invalid_guard(self):
|
||||
"""V_MULLIT_F32 returns -MAX_FLOAT_F32 when the guard input is non-positive."""
|
||||
instructions = [
|
||||
v_mov_b32_e32(v[0], f2i(2.0)),
|
||||
v_mov_b32_e32(v[1], f2i(3.0)),
|
||||
v_mov_b32_e32(v[2], f2i(0.0)),
|
||||
v_mullit_f32(v[3], v[0], v[1], v[2]),
|
||||
]
|
||||
st = run_program(instructions, n_lanes=1)
|
||||
self.assertEqual(st.vgpr[0][3], 0xFF7FFFFF)
|
||||
|
||||
def test_v_fma_f32_negative(self):
|
||||
"""V_FMA_F32 with negative multiplier."""
|
||||
instructions = [
|
||||
@@ -1614,7 +1592,8 @@ class TestModifierInteractions(unittest.TestCase):
|
||||
self.assertEqual(st.vgpr[0][2], 0x80000000, "-|(-0.0)| = -0.0")
|
||||
|
||||
def test_clamp_with_nan(self):
|
||||
"""Clamp with NaN input saturates to 0 on RDNA3 hardware."""
|
||||
"""Clamp with NaN input should still produce NaN."""
|
||||
import math
|
||||
quiet_nan = 0x7fc00000
|
||||
instructions = [
|
||||
s_mov_b32(s[0], quiet_nan),
|
||||
@@ -1622,7 +1601,7 @@ class TestModifierInteractions(unittest.TestCase):
|
||||
VOP3(VOP3Op.V_ADD_F32, vdst=v[1], src0=v[0], src1=0.0, clmp=1),
|
||||
]
|
||||
st = run_program(instructions, n_lanes=1)
|
||||
self.assertEqual(st.vgpr[0][1], 0)
|
||||
self.assertTrue(math.isnan(i2f(st.vgpr[0][1])))
|
||||
|
||||
def test_omod_ignored(self):
|
||||
"""OMOD field is ignored on RDNA3 hardware."""
|
||||
@@ -3626,30 +3605,32 @@ class TestPermlane(unittest.TestCase):
|
||||
"""V_PERMLANE16_B32 broadcast lane 0 to all lanes in row."""
|
||||
# lanesel = all zeros -> all positions read from lane 0 within row
|
||||
instructions = [
|
||||
v_mov_b32_e32(v[0], v[255]),
|
||||
v_mov_b32_e32(v[0], 0xCAFEBABE), # source data
|
||||
s_mov_b32(s[0], 0), # lanesel low = 0 (all read lane 0)
|
||||
s_mov_b32(s[1], 0), # lanesel high = 0
|
||||
v_permlane16_b32(v[1], v[0], s[0], s[1]),
|
||||
]
|
||||
st = run_program(instructions, n_lanes=32)
|
||||
for lane in range(16): self.assertEqual(st.vgpr[lane][1], 0)
|
||||
for lane in range(16, 32): self.assertEqual(st.vgpr[lane][1], 16)
|
||||
st = run_program(instructions, n_lanes=4)
|
||||
# All lanes read from lane 0 of their row
|
||||
for lane in range(4):
|
||||
self.assertEqual(st.vgpr[lane][1], 0xCAFEBABE)
|
||||
|
||||
def test_v_permlanex16_b32_identity(self):
|
||||
"""V_PERMLANEX16_B32 cross-row read with identity selection."""
|
||||
# In wave32: row 0 (lanes 0-15) reads from row 1 (lanes 16-31) and vice versa
|
||||
# With single lane in row 0, it reads from lane 0 of row 1 (lane 16)
|
||||
# But lane 16 doesn't exist in 1-lane test, so use 32 lanes
|
||||
instructions = [
|
||||
v_mov_b32_e32(v[0], v[255]),
|
||||
v_mov_b32_e32(v[0], 0x11111111), # All lanes have this initially
|
||||
s_mov_b32(s[0], 0x76543210), # lanesel low
|
||||
s_mov_b32(s[1], 0xFEDCBA98), # lanesel high
|
||||
v_permlanex16_b32(v[1], v[0], s[0], s[1]),
|
||||
]
|
||||
st = run_program(instructions, n_lanes=32)
|
||||
self.assertEqual(st.vgpr[0][1], 16)
|
||||
self.assertEqual(st.vgpr[5][1], 21)
|
||||
self.assertEqual(st.vgpr[15][1], 31)
|
||||
self.assertEqual(st.vgpr[16][1], 0)
|
||||
self.assertEqual(st.vgpr[21][1], 5)
|
||||
self.assertEqual(st.vgpr[31][1], 15)
|
||||
# Lane 0 in row 0 reads from lane 0 of row 1 (lane 16)
|
||||
self.assertEqual(st.vgpr[0][1], 0x11111111)
|
||||
# Lane 16 in row 1 reads from lane 0 of row 0 (lane 0)
|
||||
self.assertEqual(st.vgpr[16][1], 0x11111111)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -0,0 +1,528 @@
|
||||
# Test to compare Python and Rust RDNA3 emulators by running real tinygrad kernels
|
||||
import unittest, ctypes
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from tinygrad import Device
|
||||
|
||||
from test.mockgpu.amd.emu import WaveState, _decode_at, WAVE_SIZE, VCC_LO, EXEC_LO, SCC
|
||||
from tinygrad.renderer.amd import decode_inst
|
||||
import tinygrad
|
||||
REMU_PATH = Path(tinygrad.__file__).parent.parent / "extra/remu/target/release/libremu.so"
|
||||
if not REMU_PATH.exists(): REMU_PATH = Path(tinygrad.__file__).parent.parent / "extra/remu/target/release/libremu.dylib"
|
||||
|
||||
def set_valid_mem_ranges(ranges): pass # emu2 doesn't need this
|
||||
|
||||
def _is_f32_nan(bits: int) -> bool:
|
||||
"""Check if 32-bit value is a NaN (exponent all 1s, mantissa non-zero)."""
|
||||
return (bits & 0x7f800000) == 0x7f800000 and (bits & 0x007fffff) != 0
|
||||
|
||||
def _vals_equal(a: int, b: int) -> bool:
|
||||
"""Compare two 32-bit values, treating all NaN bit patterns as equal."""
|
||||
if a == b: return True
|
||||
return _is_f32_nan(a) and _is_f32_nan(b)
|
||||
|
||||
@dataclass
|
||||
class KernelSnapshot:
|
||||
code: bytes
|
||||
src: str
|
||||
global_size: tuple[int, int, int]
|
||||
local_size: tuple[int, int, int]
|
||||
buf_idxs: list[int] # indices into shared buffer pool
|
||||
buf_sizes: list[int] # sizes for each buffer index
|
||||
|
||||
@dataclass
|
||||
class StateSnapshot:
|
||||
pc: int
|
||||
scc: int
|
||||
vcc: int
|
||||
exec_mask: int
|
||||
sgpr: list[int]
|
||||
vgpr: list[list[int]]
|
||||
|
||||
def diff(self, other: 'StateSnapshot', n_lanes: int, arrow: str = " vs ") -> list[str]:
|
||||
"""Return list of differences between two states."""
|
||||
diffs = []
|
||||
if self.pc != other.pc: diffs.append(f"pc: {self.pc}{arrow}{other.pc}")
|
||||
if self.scc != other.scc: diffs.append(f"scc: {self.scc}{arrow}{other.scc}")
|
||||
if self.vcc != other.vcc: diffs.append(f"vcc: 0x{self.vcc:08x}{arrow}0x{other.vcc:08x}")
|
||||
if self.exec_mask != other.exec_mask: diffs.append(f"exec: 0x{self.exec_mask:08x}{arrow}0x{other.exec_mask:08x}")
|
||||
for i, (a, b) in enumerate(zip(self.sgpr, other.sgpr)):
|
||||
# Skip VCC_LO/HI (106/107) and EXEC_LO/HI (126/127) as they alias vcc/exec_mask which are compared separately
|
||||
if i in (106, 107, 126, 127): continue
|
||||
if not _vals_equal(a, b): diffs.append(f"sgpr[{i}]: 0x{a:08x}{arrow}0x{b:08x}")
|
||||
for lane in range(n_lanes):
|
||||
for i, (a, b) in enumerate(zip(self.vgpr[lane], other.vgpr[lane])):
|
||||
if not _vals_equal(a, b): diffs.append(f"vgpr[{lane}][{i}]: 0x{a:08x}{arrow}0x{b:08x}")
|
||||
return diffs
|
||||
|
||||
class CStateSnapshot(ctypes.Structure):
|
||||
_fields_ = [("pc", ctypes.c_uint32), ("scc", ctypes.c_uint32), ("vcc", ctypes.c_uint32), ("exec_mask", ctypes.c_uint32),
|
||||
("sgpr", ctypes.c_uint32 * 128), ("vgpr", (ctypes.c_uint32 * 256) * 32)]
|
||||
|
||||
def to_snapshot(self) -> StateSnapshot:
|
||||
return StateSnapshot(pc=self.pc, scc=self.scc, vcc=self.vcc, exec_mask=self.exec_mask,
|
||||
sgpr=list(self.sgpr), vgpr=[list(self.vgpr[i]) for i in range(32)])
|
||||
|
||||
class RustEmulator:
|
||||
def __init__(self):
|
||||
self.lib = ctypes.CDLL(str(REMU_PATH))
|
||||
self.lib.wave_create.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint32]
|
||||
self.lib.wave_create.restype = ctypes.c_void_p
|
||||
self.lib.wave_step.argtypes = [ctypes.c_void_p]
|
||||
self.lib.wave_step.restype = ctypes.c_int32
|
||||
self.lib.wave_get_snapshot.argtypes = [ctypes.c_void_p, ctypes.POINTER(CStateSnapshot)]
|
||||
self.lib.wave_set_sgpr.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint32]
|
||||
self.lib.wave_set_vgpr.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_uint32]
|
||||
self.lib.wave_init_lds.argtypes = [ctypes.c_void_p, ctypes.c_uint32]
|
||||
self.lib.wave_free.argtypes = [ctypes.c_void_p]
|
||||
self.ctx = None
|
||||
|
||||
def create(self, kernel: bytes, n_lanes: int):
|
||||
kernel_buf = (ctypes.c_char * len(kernel)).from_buffer_copy(kernel)
|
||||
self.ctx = self.lib.wave_create(ctypes.addressof(kernel_buf), len(kernel), n_lanes)
|
||||
self._kernel_buf = kernel_buf
|
||||
|
||||
def step(self) -> int: return self.lib.wave_step(self.ctx)
|
||||
def set_sgpr(self, idx: int, val: int): self.lib.wave_set_sgpr(self.ctx, idx, val)
|
||||
def set_vgpr(self, lane: int, idx: int, val: int): self.lib.wave_set_vgpr(self.ctx, lane, idx, val)
|
||||
def init_lds(self, size: int): self.lib.wave_init_lds(self.ctx, size)
|
||||
|
||||
def get_snapshot(self) -> StateSnapshot:
|
||||
snap = CStateSnapshot()
|
||||
self.lib.wave_get_snapshot(self.ctx, ctypes.byref(snap))
|
||||
return snap.to_snapshot()
|
||||
|
||||
def free(self):
|
||||
if self.ctx:
|
||||
self.lib.wave_free(self.ctx)
|
||||
self.ctx = None
|
||||
|
||||
class PythonEmulator:
|
||||
def __init__(self):
|
||||
self.state: WaveState | None = None
|
||||
self.program: dict[int, tuple] = {} # lazily populated: pc -> (name, fxn, globals)
|
||||
self.vmem_buf = None
|
||||
self.lds_buf = None
|
||||
self.kernel_buf = None # Keep kernel bytes alive
|
||||
self.lib_addr = 0 # Base address of kernel code
|
||||
|
||||
def create(self, kernel: bytes, n_lanes: int):
|
||||
import ctypes
|
||||
from tinygrad.device import Buffer, BufferSpec
|
||||
from tinygrad.dtype import dtypes
|
||||
# Store kernel in a ctypes buffer so _decode_at can read from memory at actual PC address
|
||||
self.kernel_buf = (ctypes.c_char * len(kernel)).from_buffer_copy(kernel)
|
||||
self.lib_addr = ctypes.addressof(self.kernel_buf)
|
||||
self.program = {}
|
||||
self.state = WaveState(n_lanes)
|
||||
self.state.pc = self.lib_addr # Set PC to code base address
|
||||
self.vmem_buf = Buffer('CPU', 1 << 40, dtypes.uint32, options=BufferSpec(external_ptr=0)).ensure_allocated()
|
||||
self.lds_buf = Buffer('CPU', 65536 // 4, dtypes.uint32).ensure_allocated()
|
||||
|
||||
def _ensure_decoded(self, pc: int):
|
||||
if pc not in self.program:
|
||||
runner, _ = _decode_at(pc, "rdna3")
|
||||
self.program[pc] = (runner.p.function_name, runner._prg.fxn, runner.p.globals)
|
||||
|
||||
def step(self) -> int:
|
||||
import ctypes
|
||||
assert self.state is not None
|
||||
pc = self.state.pc
|
||||
if pc == 0xFFFFFFFFFFFFFFFF: return -1
|
||||
self._ensure_decoded(pc)
|
||||
name, fxn, globals_list = self.program[pc]
|
||||
buf_addrs = {0: self.state.sgpr_buf._buf.va_addr, 1: self.state.vgpr_buf._buf.va_addr, # type: ignore[union-attr]
|
||||
2: self.vmem_buf._buf.va_addr, 3: self.lds_buf._buf.va_addr} # type: ignore[union-attr]
|
||||
fxn(*[ctypes.c_uint64(buf_addrs[g]) for g in globals_list], ctypes.c_int32(0))
|
||||
return -1 if self.state.pc == 0xFFFFFFFFFFFFFFFF else 0
|
||||
|
||||
def set_sgpr(self, idx: int, val: int):
|
||||
assert self.state is not None
|
||||
self.state._write_sgpr(idx, val)
|
||||
def set_vgpr(self, lane: int, idx: int, val: int):
|
||||
assert self.state is not None
|
||||
self.state._write_vgpr(idx, lane, val)
|
||||
|
||||
def get_snapshot(self) -> StateSnapshot:
|
||||
assert self.state is not None
|
||||
sgpr = [self.state._read_sgpr(i) for i in range(128)]
|
||||
vgpr = [[self.state._read_vgpr(reg, lane) for reg in range(256)] for lane in range(WAVE_SIZE)]
|
||||
# Convert actual PC address to word offset for comparison with Rust emulator
|
||||
pc_offset = (self.state.pc - self.lib_addr) // 4 if self.state.pc != 0xFFFFFFFFFFFFFFFF else 0xFFFFFFFFFFFFFFFF
|
||||
return StateSnapshot(pc=pc_offset, scc=self.state._read_sgpr(SCC.offset), vcc=sgpr[VCC_LO.offset],
|
||||
exec_mask=sgpr[EXEC_LO.offset], sgpr=sgpr, vgpr=vgpr)
|
||||
|
||||
def run_single_kernel(kernel: bytes, n_lanes: int, args_ptr: int, global_size: tuple[int, int, int],
|
||||
local_size: tuple[int, int, int], max_steps: int, debug: bool, trace_len: int,
|
||||
kernel_idx: int = 0, max_workgroups: int = 8) -> tuple[bool, str, int]:
|
||||
"""Run a single kernel through both emulators. Returns (success, message, total_steps)."""
|
||||
gx, gy, gz = global_size
|
||||
lx, ly, lz = local_size
|
||||
total_steps = 0
|
||||
wg_count = 0
|
||||
|
||||
for gidz in range(gz):
|
||||
for gidy in range(gy):
|
||||
for gidx in range(gx):
|
||||
if wg_count >= max_workgroups: return True, f"Completed {wg_count} workgroups (limit reached)", total_steps
|
||||
wg_count += 1
|
||||
rust = RustEmulator()
|
||||
python = PythonEmulator()
|
||||
rust.create(kernel, n_lanes)
|
||||
python.create(kernel, n_lanes)
|
||||
|
||||
# Initialize LDS (64KB, standard size for AMD GPUs)
|
||||
rust.init_lds(65536)
|
||||
|
||||
for emu in (rust, python):
|
||||
emu.set_sgpr(0, args_ptr & 0xffffffff)
|
||||
emu.set_sgpr(1, (args_ptr >> 32) & 0xffffffff)
|
||||
emu.set_sgpr(13, gidx)
|
||||
emu.set_sgpr(14, gidy)
|
||||
emu.set_sgpr(15, gidz)
|
||||
# Initialize v[0] with packed workitem IDs for each lane
|
||||
for lane in range(n_lanes):
|
||||
tid = lane
|
||||
z, y, x = tid // (lx * ly), (tid // lx) % ly, tid % lx
|
||||
emu.set_vgpr(lane, 0, (z << 20) | (y << 10) | x)
|
||||
|
||||
step = 0
|
||||
trace: list[tuple[int, int, str, StateSnapshot, StateSnapshot]] = []
|
||||
prev_sync_after = False # Track if previous instruction had known Rust bugs
|
||||
try:
|
||||
while step < max_steps:
|
||||
rust_before = rust.get_snapshot()
|
||||
python_before = python.get_snapshot()
|
||||
|
||||
pc_addr = python.lib_addr + python_before.pc * 4 # Convert word offset to actual address
|
||||
python._ensure_decoded(pc_addr)
|
||||
inst_hex_name = python.program[pc_addr][0]
|
||||
# Decode the instruction to get mnemonic for sync_after checks
|
||||
try:
|
||||
# Format is mnemonic_hexbytes, e.g. v_exp_f32_e32_014b027e -> hex is 014b027e
|
||||
parts = inst_hex_name.rsplit('_', 1)
|
||||
inst_bytes_hex = parts[1] if len(parts) == 2 else ""
|
||||
inst_bytes = bytes.fromhex(inst_bytes_hex) if inst_bytes_hex else b''
|
||||
decoded = decode_inst(inst_bytes) if inst_bytes else None
|
||||
inst_mnemonic = repr(decoded).split('(')[0] if decoded else ""
|
||||
except Exception:
|
||||
inst_mnemonic = ""
|
||||
# For generic instructions, use function name for sync_after check
|
||||
if not inst_mnemonic: inst_mnemonic = inst_hex_name
|
||||
inst_str = inst_hex_name
|
||||
trace.append((step, python_before.pc, inst_str, rust_before, python_before))
|
||||
if len(trace) > trace_len: trace.pop(0)
|
||||
|
||||
if debug: print(f"K{kernel_idx} WG({gidx},{gidy},{gidz}) Step {step}: PC={python_before.pc}, inst={inst_str}")
|
||||
|
||||
# Instructions with known Rust emulator bugs or precision differences - sync Python to Rust after execution
|
||||
# v_div_scale/v_div_fixup: Rust has different VCC handling
|
||||
# v_cvt_f16_f32: Rust clears high 16 bits, but hardware (and Python) preserves them
|
||||
# s_add_i32/s_sub_i32: Rust has incorrect SCC overflow detection
|
||||
# v_exp_f32/v_log_f32/v_ldexp_f32: precision differences in transcendental functions
|
||||
# s_delay_alu: Rust handles differently
|
||||
# v_add_co_ci_u32/v_sub_co_ci_u32/v_subrev_co_ci_u32: Rust preserves inactive VCC bits, but hardware clears all bits
|
||||
sync_after = any(x in inst_mnemonic.lower() for x in ('v_div_scale', 'v_div_fixup', 'v_cvt_f16_f32', 's_add_i32', 's_sub_i32',
|
||||
'v_exp_f32', 'v_log_f32', 'v_ldexp_f32', 's_delay_alu',
|
||||
'v_add_co_ci_u32', 'v_sub_co_ci_u32', 'v_subrev_co_ci_u32'))
|
||||
# Skip comparison if previous instruction had known Rust bugs (states were synced but may still differ slightly)
|
||||
diffs = rust_before.diff(python_before, n_lanes) if not prev_sync_after else []
|
||||
if diffs:
|
||||
trace_lines = []
|
||||
for idx, (s, pc, d, rb, pb) in enumerate(trace):
|
||||
trace_lines.append(f" step {s}: PC={pc:3d} {d}")
|
||||
if idx < len(trace) - 1:
|
||||
next_rb, next_pb = trace[idx + 1][3:5]
|
||||
rust_diffs = rb.diff(next_rb, n_lanes, "->")
|
||||
python_diffs = pb.diff(next_pb, n_lanes, "->")
|
||||
if rust_diffs: trace_lines.append(f" rust: {', '.join(rust_diffs[:5])}")
|
||||
if python_diffs: trace_lines.append(f" python: {', '.join(python_diffs[:5])}")
|
||||
elif rust_diffs: trace_lines.append(" python: (no changes)")
|
||||
else:
|
||||
# Last traced instruction - compare with current state
|
||||
rust_diffs = rb.diff(rust_before, n_lanes, "->")
|
||||
python_diffs = pb.diff(python_before, n_lanes, "->")
|
||||
if rust_diffs: trace_lines.append(f" rust: {', '.join(rust_diffs[:5])}")
|
||||
if python_diffs: trace_lines.append(f" python: {', '.join(python_diffs[:5])}")
|
||||
elif rust_diffs: trace_lines.append(" python: (no changes)")
|
||||
trace_str = "\n".join(trace_lines)
|
||||
msg = f"K{kernel_idx} WG({gidx},{gidy},{gidz}) Step {step} before inst '{inst_str}': states differ (rust vs python):\n "
|
||||
msg += "\n ".join(diffs[:10]) + f"\n Recent instructions:\n{trace_str}"
|
||||
return False, msg, total_steps
|
||||
|
||||
rust_result = rust.step()
|
||||
python_result = python.step()
|
||||
|
||||
if rust_result != python_result:
|
||||
# Rust returns 1 for unsupported instructions - skip test
|
||||
if rust_result == 1 and python_result == 0:
|
||||
raise unittest.SkipTest(f"Rust emulator doesn't support instruction: {inst_str}")
|
||||
trace_str = "\n".join(f" step {s}: PC={pc:3d} {d}" for s, pc, d, _, _ in trace)
|
||||
msg = (f"K{kernel_idx} WG({gidx},{gidy},{gidz}) Step {step}: different return codes: "
|
||||
f"rust={rust_result}, python={python_result}, inst={inst_str}\n Recent instructions:\n{trace_str}")
|
||||
return False, msg, total_steps
|
||||
|
||||
# Sync Python state to Rust after instructions with known Rust emulator differences
|
||||
if sync_after:
|
||||
rust_after = rust.get_snapshot()
|
||||
for i in range(128): python.set_sgpr(i, rust_after.sgpr[i])
|
||||
for lane in range(n_lanes):
|
||||
for i in range(256): python.set_vgpr(lane, i, rust_after.vgpr[lane][i])
|
||||
assert python.state is not None
|
||||
# Convert Rust's word-based PC to Python's actual address
|
||||
python.state.pc = python.lib_addr + rust_after.pc * 4
|
||||
python.state._write_sgpr(SCC.offset, rust_after.scc)
|
||||
python.state._write_sgpr(VCC_LO.offset, rust_after.vcc)
|
||||
python.state._write_sgpr(EXEC_LO.offset, rust_after.exec_mask)
|
||||
prev_sync_after = sync_after
|
||||
|
||||
if rust_result == -1:
|
||||
total_steps += step + 1
|
||||
break
|
||||
if rust_result == 1:
|
||||
total_steps += step + 1
|
||||
break
|
||||
if rust_result < 0 and rust_result != -2:
|
||||
return False, f"K{kernel_idx} WG({gidx},{gidy},{gidz}) Step {step}: error code {rust_result}", total_steps
|
||||
|
||||
step += 1
|
||||
else:
|
||||
return False, f"K{kernel_idx} WG({gidx},{gidy},{gidz}) Max steps ({max_steps}) reached", total_steps
|
||||
finally:
|
||||
rust.free()
|
||||
|
||||
return True, f"Completed {gx*gy*gz} workgroups", total_steps
|
||||
|
||||
def compare_emulators_multi_kernel(kernels: list[KernelSnapshot], buf_pool: dict[int, int], max_steps: int = 1000,
|
||||
debug: bool = False, trace_len: int = 10, buf_data: dict[int, bytes] | None = None) -> tuple[bool, str]:
|
||||
"""Run all kernels through both emulators with shared buffer pool."""
|
||||
if buf_data is None: buf_data = {}
|
||||
|
||||
# Allocate shared buffer pool with padding for over-reads (GPU loads up to 16 bytes at once)
|
||||
buf_id_to_ptr: dict[int, int] = {}
|
||||
buffers = []
|
||||
for buf_id, size in buf_pool.items():
|
||||
padded_size = ((size + 15) // 16) * 16 + 16 # round up to 16 bytes + extra padding
|
||||
# Initialize with data from COPY if available
|
||||
init_data = buf_data.get(buf_id, b'\x00' * padded_size)
|
||||
init_list = list(init_data) + [0] * (padded_size - len(init_data))
|
||||
buf = (ctypes.c_uint8 * padded_size)(*init_list[:padded_size])
|
||||
buffers.append((buf, padded_size))
|
||||
buf_id_to_ptr[buf_id] = ctypes.addressof(buf)
|
||||
|
||||
# Set up valid memory ranges
|
||||
ranges = {(ctypes.addressof(b), size) for b, size in buffers}
|
||||
|
||||
total_steps = 0
|
||||
for ki, kernel in enumerate(kernels):
|
||||
# Create args array for this kernel's buffers
|
||||
args = (ctypes.c_uint64 * len(kernel.buf_idxs))(*[buf_id_to_ptr[bid] for bid in kernel.buf_idxs])
|
||||
args_ptr = ctypes.addressof(args)
|
||||
|
||||
# Update valid ranges to include this args array
|
||||
kernel_ranges = ranges | {(args_ptr, ctypes.sizeof(args))}
|
||||
set_valid_mem_ranges(kernel_ranges)
|
||||
|
||||
n_lanes = kernel.local_size[0] * kernel.local_size[1] * kernel.local_size[2]
|
||||
|
||||
ok, msg, steps = run_single_kernel(
|
||||
kernel.code, min(n_lanes, 32), args_ptr, kernel.global_size,
|
||||
kernel.local_size, max_steps, debug, trace_len, ki
|
||||
)
|
||||
total_steps += steps
|
||||
if not ok:
|
||||
return False, msg
|
||||
|
||||
return True, f"Completed {len(kernels)} kernels, {total_steps} total steps"
|
||||
|
||||
def compare_emulators_with_memory(kernel: bytes, n_lanes: int, buf_sizes: list, max_steps: int = 1000, debug: bool = False,
|
||||
global_size: tuple[int, int, int] = (1, 1, 1), trace_len: int = 10) -> tuple[bool, str]:
|
||||
"""Run both emulators with memory set up for tinygrad kernels, executing all workgroups. Legacy wrapper."""
|
||||
# Allocate buffers
|
||||
buffers = []
|
||||
for size in buf_sizes:
|
||||
buf = (ctypes.c_uint8 * size)(*[0] * size)
|
||||
buffers.append(buf)
|
||||
|
||||
# Create args array with buffer pointers
|
||||
args = (ctypes.c_uint64 * len(buffers))(*[ctypes.addressof(b) for b in buffers])
|
||||
args_ptr = ctypes.addressof(args)
|
||||
|
||||
# Set up valid memory ranges for Python emulator
|
||||
ranges = {(ctypes.addressof(b), len(b)) for b in buffers}
|
||||
ranges.add((args_ptr, ctypes.sizeof(args)))
|
||||
set_valid_mem_ranges(ranges)
|
||||
|
||||
# Legacy wrapper assumes local_size = (n_lanes, 1, 1)
|
||||
ok, msg, _ = run_single_kernel(kernel, n_lanes, args_ptr, global_size, (n_lanes, 1, 1), max_steps, debug, trace_len)
|
||||
return ok, msg
|
||||
|
||||
def get_kernels_from_tinygrad(op_fn) -> tuple[list[KernelSnapshot], dict[int, int], dict[int, bytes]]:
|
||||
"""Compile a tinygrad operation and extract all kernels with their buffer mappings."""
|
||||
from tinygrad import Tensor
|
||||
from tinygrad.runtime.support.elf import elf_loader
|
||||
|
||||
out = op_fn(Tensor)
|
||||
sched = out.schedule()
|
||||
kernels = []
|
||||
buf_pool: dict[int, int] = {} # buffer id -> size
|
||||
buf_data: dict[int, bytes] = {} # buffer id -> initial data from COPY
|
||||
|
||||
for ei in sched:
|
||||
lowered = ei.lower()
|
||||
if ei.ast.op.name == 'COPY':
|
||||
# Handle COPY: extract source data to initialize destination buffer
|
||||
if len(lowered.bufs) >= 2:
|
||||
dst_buf, src_buf = lowered.bufs[0], lowered.bufs[1]
|
||||
dst_id = id(dst_buf)
|
||||
if dst_id not in buf_pool:
|
||||
buf_pool[dst_id] = dst_buf.nbytes
|
||||
# Get source data if it's from numpy/CPU
|
||||
if hasattr(src_buf, 'base') and src_buf.base is not None and hasattr(src_buf.base, '_buf'):
|
||||
src_data = bytes(src_buf.base._buf)
|
||||
buf_data[dst_id] = src_data
|
||||
elif ei.ast.op.name == 'SINK':
|
||||
if lowered.prg and lowered.prg.p.lib:
|
||||
lib = bytes(lowered.prg.p.lib)
|
||||
_, sections, _ = elf_loader(lib)
|
||||
for sec in sections:
|
||||
if sec.name == '.text':
|
||||
buf_idxs = []
|
||||
buf_sizes = []
|
||||
for b in lowered.bufs:
|
||||
buf_id = id(b)
|
||||
if buf_id not in buf_pool:
|
||||
buf_pool[buf_id] = b.nbytes
|
||||
buf_idxs.append(buf_id)
|
||||
buf_sizes.append(b.nbytes)
|
||||
kernels.append(KernelSnapshot(
|
||||
code=bytes(sec.content),
|
||||
src=lowered.prg.p.src,
|
||||
global_size=tuple(lowered.prg.p.global_size),
|
||||
local_size=tuple(lowered.prg.p.local_size),
|
||||
buf_idxs=buf_idxs,
|
||||
buf_sizes=buf_sizes
|
||||
))
|
||||
if not kernels: raise RuntimeError("No kernel found")
|
||||
return kernels, buf_pool, buf_data
|
||||
|
||||
def get_kernel_from_tinygrad(op_fn) -> tuple[bytes, tuple[int, int, int], tuple[int, int, int], list]:
|
||||
"""Compile a tinygrad operation and extract the last (main) kernel binary. Legacy wrapper."""
|
||||
kernels, _, _ = get_kernels_from_tinygrad(op_fn)
|
||||
k = kernels[-1]
|
||||
return k.code, k.global_size, k.local_size, k.buf_sizes
|
||||
|
||||
@unittest.skipUnless(Device.DEFAULT == "AMD", "requires AMD device")
|
||||
class TestTinygradKernels(unittest.TestCase):
|
||||
"""Compare emulators on real tinygrad-compiled kernels."""
|
||||
|
||||
def _test_kernel(self, op_fn, max_steps=10000):
|
||||
kernels, buf_pool, buf_data = get_kernels_from_tinygrad(op_fn)
|
||||
ok, msg = compare_emulators_multi_kernel(kernels, buf_pool, max_steps=max_steps, buf_data=buf_data)
|
||||
self.assertTrue(ok, msg)
|
||||
|
||||
# Basic ops - consolidated tests covering key instruction patterns
|
||||
def test_unary_ops(self): self._test_kernel(lambda T: T([-1.0, 0.0, 1.0, 2.0]).relu().exp().log().sqrt().reciprocal())
|
||||
def test_binary_ops(self): self._test_kernel(lambda T: (T([1.0, 2.0]) + T([3.0, 4.0])) * T([0.5, 0.5]) - T([1.0, 1.0]))
|
||||
def test_trig(self): self._test_kernel(lambda T: T([0.1, 1.0, 3.14, -1.0]*8).sin() + T([0.1, 1.0, 3.14, -1.0]*8).cos())
|
||||
def test_compare(self): self._test_kernel(lambda T: (T.empty(64) < T.empty(64)).where(T.empty(64), T.empty(64)))
|
||||
def test_bitwise(self): self._test_kernel(lambda T: (T([0xF0, 0x0F, 0xFF]*11).int() & T([0x0F, 0x0F, 0x00]*11).int()) | T([1]*33).int())
|
||||
def test_int_ops(self): self._test_kernel(lambda T: ((T.empty(64).int() + T.empty(64).int()) * T.empty(64).int()).float())
|
||||
|
||||
# Reductions
|
||||
def test_reduce(self): self._test_kernel(lambda T: T.empty(64).sum() + T.empty(64).max())
|
||||
def test_argmax(self): self._test_kernel(lambda T: T.empty(64).argmax())
|
||||
|
||||
# Matmul
|
||||
def test_gemm(self): self._test_kernel(lambda T: T.empty(8, 8) @ T.empty(8, 8), max_steps=100000)
|
||||
@unittest.skip("Rust emulator crashes on this kernel (assertion failure in thread.rs)")
|
||||
def test_gemm_fp16(self): self._test_kernel(lambda T: T.empty(16, 16).half() @ T.empty(16, 16).half(), max_steps=100000)
|
||||
|
||||
# Complex ops
|
||||
def test_softmax(self): self._test_kernel(lambda T: T.empty(16).softmax())
|
||||
def test_layernorm(self): self._test_kernel(lambda T: T.empty(8, 8).layernorm())
|
||||
|
||||
# Memory patterns
|
||||
def test_memory(self): self._test_kernel(lambda T: T.empty(4, 4).permute(1, 0).contiguous() + T.empty(4, 1).expand(4, 4))
|
||||
|
||||
# Cast ops
|
||||
def test_cast(self): self._test_kernel(lambda T: T.empty(32).half().float() + T.empty(32).int().float())
|
||||
|
||||
# Pooling - regression for VCC wave32 mode
|
||||
def test_pool2d(self):
|
||||
self._test_kernel(lambda T: T.empty(1, 1, 8, 8).avg_pool2d(kernel_size=(4,4)) + T.empty(1, 1, 8, 8).max_pool2d(kernel_size=(4,4)))
|
||||
|
||||
# Convolution
|
||||
def test_conv2d(self): self._test_kernel(lambda T: T.empty(1, 2, 8, 8).conv2d(T.empty(2, 2, 3, 3)), max_steps=50000)
|
||||
|
||||
# Regression tests
|
||||
def test_topk(self): self._test_kernel(lambda T: T.empty(64).topk(3)[0])
|
||||
def test_interpolate(self): self._test_kernel(lambda T: T.empty(1,2,16,16).relu().cast('uint8').interpolate((8,8), mode="linear"))
|
||||
def test_index_int64(self):
|
||||
from tinygrad import dtypes
|
||||
self._test_kernel(lambda T: T.empty(4, 4)[T.arange(4).cast(dtypes.int64), :])
|
||||
def test_gelu(self): self._test_kernel(lambda T: T.empty(32, 32).gelu())
|
||||
def test_exp(self): self._test_kernel(lambda T: T.empty(1024).exp())
|
||||
def test_cross_entropy(self):
|
||||
import numpy as np
|
||||
np.random.seed(0)
|
||||
classes = np.random.randint(0, 10, (16,), dtype=np.int32).tolist()
|
||||
x_np = np.random.randn(16, 10).astype(np.float32)
|
||||
self._test_kernel(lambda T: (T(x_np.tolist()).reshape(16,10) + 0).cross_entropy((T(classes).int().reshape(16) + 0)))
|
||||
def test_isinf(self): self._test_kernel(lambda T: T([float('-inf'), 0., float('inf'), 1.1]*8).isinf())
|
||||
def test_sin_f64(self):
|
||||
from tinygrad import dtypes
|
||||
self._test_kernel(lambda T: T([2.0], dtype=dtypes.float64).sin())
|
||||
|
||||
def test_sin_large_f32(self):
|
||||
"""Test sin with large values that trigger Payne-Hanek range reduction."""
|
||||
# Values around 859240 trigger the Payne-Hanek algorithm
|
||||
# This tests the integer multiply-high instructions used in range reduction
|
||||
self._test_kernel(lambda T: T([859240.0, 1000000.0, 100594688.0]).sin())
|
||||
|
||||
def test_clip_zero_one(self):
|
||||
"""Test clip(0, 1) - regression for binary_crossentropy failure."""
|
||||
import numpy as np
|
||||
np.random.seed(0)
|
||||
x_np = np.random.uniform(-2, 2, (32, 10)).astype(np.float32).tolist()
|
||||
self._test_kernel(lambda T: T(x_np).clip(0, 1))
|
||||
|
||||
def test_mod_int64(self):
|
||||
"""Test int64 modulo, especially edge cases like 1 % -1."""
|
||||
from tinygrad import dtypes
|
||||
self._test_kernel(lambda T: T([1, 10, -10, 7], dtype=dtypes.int64) % T([-1, 3, 3, -3], dtype=dtypes.int64))
|
||||
|
||||
def test_expand_flatten_sum(self):
|
||||
"""Test flatten of expanded tensor followed by sum.
|
||||
|
||||
Bug: flatten() of an expanded tensor produces wrong results for certain sizes.
|
||||
Sizes that are multiples of 32 work (32, 48, 64), but sizes like 33, 49, 50 fail.
|
||||
This breaks masked_select and nonzero operations.
|
||||
"""
|
||||
import numpy as np
|
||||
np.random.seed(0)
|
||||
x_np = np.random.uniform(-2, 2, (33,)).astype(np.float32)
|
||||
self._test_kernel(lambda T: (T(x_np.tolist()) > 0.5).unsqueeze(-1).expand(33, 3).flatten().sum())
|
||||
|
||||
@unittest.skip("slow and broken with AMD:LLVM")
|
||||
def test_nonzero(self):
|
||||
"""Test nonzero operation - counts and gathers indices of non-zero elements."""
|
||||
import numpy as np
|
||||
np.random.seed(42)
|
||||
x_np = np.random.rand(10, 5, 3).astype(np.float32)
|
||||
self._test_kernel(lambda T: (T(x_np.tolist()) > 0.5).nonzero())
|
||||
|
||||
@unittest.skip("Precision differences in v_exp/v_log accumulate across kernels, causing memory divergence")
|
||||
def test_softmax_argmax_fused(self):
|
||||
"""Test fused softmax+argmax - tracks exp2 precision issue.
|
||||
|
||||
The fused kernel recomputes softmax inline and Python emulator's exp2 polynomial
|
||||
has up to 1 ULP error vs native exp2f, causing accumulated differences.
|
||||
"""
|
||||
import torch
|
||||
torch.manual_seed(0)
|
||||
x_np = torch.rand(4, 10).numpy()
|
||||
self._test_kernel(lambda T: T(x_np.tolist()).softmax(1).argmax())
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -15,7 +15,7 @@ from extra.gemm.amd_asm_matmul import Kernel
|
||||
def custom_add_one(A:UOp) -> UOp:
|
||||
A = A.flatten()
|
||||
assert dtypes.is_float(A.dtype.base), f"buffer dtype must be float32, got {A.dtype}"
|
||||
threads = UOp.special(A.numel(), "lidx0")
|
||||
threads = UOp.special(A.size, "lidx0")
|
||||
insts = [
|
||||
s_load_b64(s[0:1], s[0:1], soffset=NULL),
|
||||
s_waitcnt_lgkmcnt(sdst=NULL, simm16=0),
|
||||
@@ -27,13 +27,13 @@ def custom_add_one(A:UOp) -> UOp:
|
||||
global_store_b32(addr=v[0], data=v[1], saddr=s[0:1]),
|
||||
s_endpgm(),
|
||||
]
|
||||
sink = UOp.sink(A.base, threads, arg=KernelInfo(f"custom_add_one_{A.numel()}", estimates=Estimates(ops=A.numel(), mem=A.numel()*4*2)))
|
||||
sink = UOp.sink(A.base, threads, arg=KernelInfo(f"custom_add_one_{A.size}", estimates=Estimates(ops=A.size, mem=A.size*4*2)))
|
||||
return UOp(Ops.PROGRAM, src=(sink, UOp(Ops.DEVICE, arg="AMD"), UOp(Ops.LINEAR, src=tuple([UOp(Ops.INS, arg=x) for x in insts]))))
|
||||
|
||||
def custom_add_var(A:UOp, B:UOp) -> UOp:
|
||||
A,B = A.flatten(), B.flatten()
|
||||
assert A.dtype.base == dtypes.uint32, f"buffer dtype must be uint32, got {A.dtype}"
|
||||
threads = UOp.special(A.numel(), "lidx0")
|
||||
threads = UOp.special(A.size, "lidx0")
|
||||
var = UOp.variable("var", 0, 10)
|
||||
insts = [
|
||||
s_load_b128(s[4:7], s[0:1]),
|
||||
@@ -46,7 +46,7 @@ def custom_add_var(A:UOp, B:UOp) -> UOp:
|
||||
global_store_b32(addr=v[0], data=v[1], saddr=s[4:5]),
|
||||
s_endpgm(),
|
||||
]
|
||||
sink = UOp.sink(A.base, B.base, var, threads, arg=KernelInfo(f"custom_add_var_{A.numel()}"))
|
||||
sink = UOp.sink(A.base, B.base, var, threads, arg=KernelInfo(f"custom_add_var_{A.size}"))
|
||||
return UOp(Ops.PROGRAM, src=(sink, UOp(Ops.DEVICE, arg="AMD"), UOp(Ops.LINEAR, src=tuple([UOp(Ops.INS, arg=x) for x in insts]))))
|
||||
|
||||
def custom_wave_sync(A:UOp, arch:str) -> UOp:
|
||||
@@ -132,7 +132,7 @@ def custom_handwritten(A:UOp, arch:str) -> UOp:
|
||||
|
||||
def custom_data_deps(A:UOp, arch:str) -> UOp:
|
||||
A = A.flatten()
|
||||
threads = UOp.special(A.numel(), "lidx0")
|
||||
threads = UOp.special(A.size, "lidx0")
|
||||
k = Kernel(arch)
|
||||
k.emit(s_load_b64(s[0:1], s[0:1], soffset=NULL))
|
||||
k.emit(s_waitcnt_lgkmcnt(sdst=NULL, simm16=0))
|
||||
|
||||
@@ -7,7 +7,7 @@ from tinygrad.uop.ops import UOp, Ops
|
||||
from test.mockgpu.amd.emu import parse_pcode
|
||||
from test.mockgpu.amd.pcode import parse_expr
|
||||
from tinygrad.runtime.autogen.amd.rdna3.str_pcode import PCODE
|
||||
from tinygrad.runtime.autogen.amd.rdna3.enum import VOP1Op, VOP2Op, SOP2Op, DSOp, GLOBALOp
|
||||
from tinygrad.runtime.autogen.amd.rdna3.enum import VOP1Op, VOP2Op, SOP2Op, DSOp
|
||||
|
||||
def _srcs():
|
||||
"""Create minimal source variables for pcode parsing."""
|
||||
@@ -113,7 +113,6 @@ class TestParseExpr(unittest.TestCase):
|
||||
result = parse_expr('cond ? a : b', vrs)
|
||||
self.assertEqual(result.op, Ops.WHERE)
|
||||
|
||||
|
||||
class TestForLoopParsing(unittest.TestCase):
|
||||
"""Test for loop parsing (CLZ/CTZ patterns)."""
|
||||
|
||||
@@ -165,20 +164,6 @@ class TestForLoopParsing(unittest.TestCase):
|
||||
class TestDSPcodePatterns(unittest.TestCase):
|
||||
"""Test DS instruction pcode patterns."""
|
||||
|
||||
def test_global_atomic_add_f32_parsing(self):
|
||||
"""Test GLOBAL_ATOMIC_ADD_F32 keeps memory values in float dtype."""
|
||||
vmem = UOp(Ops.PARAM, dtypes.uint32.ptr(1024), arg=2)
|
||||
srcs = {
|
||||
'ADDR': UOp.const(dtypes.uint64, 0),
|
||||
'DATA': UOp.const(dtypes.uint32, 0x3f800000),
|
||||
'_vmem': vmem,
|
||||
}
|
||||
|
||||
_, assigns = parse_pcode(PCODE[GLOBALOp.GLOBAL_ATOMIC_ADD_F32], srcs)
|
||||
mem_write = next(val for dest, val in assigns if dest == 'MEM[ADDR].f32')
|
||||
self.assertEqual(mem_write[1].op, Ops.ADD) # type: ignore[index]
|
||||
self.assertEqual(mem_write[1].dtype, dtypes.float32) # type: ignore[index]
|
||||
|
||||
def test_ds_load_b32_pcode(self):
|
||||
"""Test DS_LOAD_B32 pcode is parseable."""
|
||||
pcode = PCODE.get(DSOp.DS_LOAD_B32)
|
||||
@@ -300,47 +285,6 @@ class TestConditionalParsing(unittest.TestCase):
|
||||
# Result should be a WHERE (ternary becomes WHERE)
|
||||
self.assertEqual(val.op, Ops.WHERE)
|
||||
|
||||
class TestConcatWidthParsing(unittest.TestCase):
|
||||
"""Test that bit extracts keep the right width for concat/unary ops."""
|
||||
|
||||
def test_permlanex16_altrow_concat(self):
|
||||
for row, expected in [(0, 1), (1, 0), (2, 3), (3, 2)]:
|
||||
parsed = parse_expr('{ row[1], ~row[0] }', {'row': UOp.const(dtypes.uint32, row)})
|
||||
self.assertEqual(parsed.simplify().arg, expected)
|
||||
|
||||
def test_permlane64_altlane_concat(self):
|
||||
for lane, expected in [(0, 32), (1, 33), (31, 63), (32, 0), (63, 31)]:
|
||||
parsed = parse_expr('{ ~lane[5], lane[4:0] }', {'lane': UOp.const(dtypes.uint32, lane)})
|
||||
self.assertEqual(parsed.simplify().arg, expected)
|
||||
|
||||
def test_permlane64_wave64_pcode_indices(self):
|
||||
vgpr = UOp(Ops.PARAM, dtypes.uint32.ptr(256), arg=0)
|
||||
srcs = {
|
||||
'SRC0': UOp.const(dtypes.uint32, 0),
|
||||
'VDST': UOp.const(dtypes.uint32, 1),
|
||||
'EXEC_LO': UOp.const(dtypes.uint32, 0xFFFFFFFF),
|
||||
'EXEC': UOp.const(dtypes.uint64, 0xFFFFFFFFFFFFFFFF),
|
||||
'_vgpr': vgpr,
|
||||
'_wave_size': 64,
|
||||
'S0': UOp.const(dtypes.uint32, 0),
|
||||
'S1': UOp.const(dtypes.uint32, 0),
|
||||
'S2': UOp.const(dtypes.uint32, 0),
|
||||
}
|
||||
|
||||
def load_idx(v: UOp) -> int:
|
||||
simp = v.simplify()
|
||||
self.assertEqual(simp.op, Ops.LOAD)
|
||||
self.assertEqual(simp.src[0].op, Ops.INDEX)
|
||||
idx = simp.src[0].src[1].simplify()
|
||||
self.assertEqual(idx.op, Ops.CONST)
|
||||
return idx.arg
|
||||
|
||||
_, assigns = parse_pcode(PCODE[VOP1Op.V_PERMLANE64_B32_E32], srcs)
|
||||
self.assertEqual(len(assigns), 64)
|
||||
for lane, (dst_idx, src_idx) in {0: (64, 32), 31: (95, 63), 32: (96, 0), 63: (127, 31)}.items():
|
||||
self.assertEqual(assigns[lane][1][0].simplify().arg, dst_idx) # type: ignore[index]
|
||||
self.assertEqual(load_idx(assigns[lane][1][1]), src_idx) # type: ignore[index]
|
||||
|
||||
class TestAllPcode(unittest.TestCase):
|
||||
"""Test that all pcode from all architectures can be parsed."""
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ dev.synchronize()
|
||||
env = os.environ.copy()
|
||||
env["AMD"] = "1"
|
||||
env["MOCKGPU"] = "1"
|
||||
env["PYTHON_REMU"] = "1"
|
||||
env["HCQDEV_WAIT_TIMEOUT_MS"] = "10000"
|
||||
|
||||
st = time.perf_counter()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Roundtrip tests: generate tinygrad kernels, decode instructions, re-encode, verify match."""
|
||||
import unittest, io, sys, re
|
||||
from dataclasses import dataclass
|
||||
from tinygrad import Device
|
||||
from tinygrad.renderer.amd import detect_format
|
||||
from test.amd.helpers import llvm_assemble, llvm_disasm, get_target, get_mattr
|
||||
@@ -45,64 +44,6 @@ def compile_and_disasm_batch(instrs: list[str], arch: str = 'rdna3') -> list[str
|
||||
code = b''.join(llvm_assemble(instrs, mcpu, mattr))
|
||||
return llvm_disasm(code, mcpu, mattr)[:len(instrs)]
|
||||
|
||||
@dataclass
|
||||
class KernelSnapshot:
|
||||
code: bytes
|
||||
src: str
|
||||
global_size: tuple[int, int, int]
|
||||
local_size: tuple[int, int, int]
|
||||
buf_idxs: list[int] # indices into shared buffer pool
|
||||
buf_sizes: list[int] # sizes for each buffer index
|
||||
|
||||
def get_kernels_from_tinygrad(op_fn) -> tuple[list[KernelSnapshot], dict[int, int], dict[int, bytes]]:
|
||||
"""Compile a tinygrad operation and extract all kernels with their buffer mappings."""
|
||||
from tinygrad import Tensor
|
||||
from tinygrad.runtime.support.elf import elf_loader
|
||||
|
||||
out = op_fn(Tensor)
|
||||
sched = out.schedule()
|
||||
kernels = []
|
||||
buf_pool: dict[int, int] = {} # buffer id -> size
|
||||
buf_data: dict[int, bytes] = {} # buffer id -> initial data from COPY
|
||||
|
||||
for ei in sched:
|
||||
lowered = ei.lower()
|
||||
if ei.ast.op.name == 'COPY':
|
||||
# Handle COPY: extract source data to initialize destination buffer
|
||||
if len(lowered.bufs) >= 2:
|
||||
dst_buf, src_buf = lowered.bufs[0], lowered.bufs[1]
|
||||
dst_id = id(dst_buf)
|
||||
if dst_id not in buf_pool:
|
||||
buf_pool[dst_id] = dst_buf.nbytes
|
||||
# Get source data if it's from numpy/CPU
|
||||
if hasattr(src_buf, 'base') and src_buf.base is not None and hasattr(src_buf.base, '_buf'):
|
||||
src_data = bytes(src_buf.base._buf)
|
||||
buf_data[dst_id] = src_data
|
||||
elif ei.ast.op.name == 'SINK':
|
||||
if lowered.prg and lowered.prg.p.lib:
|
||||
lib = bytes(lowered.prg.p.lib)
|
||||
_, sections, _ = elf_loader(lib)
|
||||
for sec in sections:
|
||||
if sec.name == '.text':
|
||||
buf_idxs = []
|
||||
buf_sizes = []
|
||||
for b in lowered.bufs:
|
||||
buf_id = id(b)
|
||||
if buf_id not in buf_pool:
|
||||
buf_pool[buf_id] = b.nbytes
|
||||
buf_idxs.append(buf_id)
|
||||
buf_sizes.append(b.nbytes)
|
||||
kernels.append(KernelSnapshot(
|
||||
code=bytes(sec.content),
|
||||
src=lowered.prg.p.src,
|
||||
global_size=tuple(lowered.prg.p.global_size),
|
||||
local_size=tuple(lowered.prg.p.local_size),
|
||||
buf_idxs=buf_idxs,
|
||||
buf_sizes=buf_sizes
|
||||
))
|
||||
if not kernels: raise RuntimeError("No kernel found")
|
||||
return kernels, buf_pool, buf_data
|
||||
|
||||
@unittest.skipUnless(Device.DEFAULT == "AMD", "requires AMD device")
|
||||
class TestTinygradKernelRoundtrip(unittest.TestCase):
|
||||
"""Test roundtrip on real tinygrad-generated kernels using get_kernels_from_tinygrad pattern."""
|
||||
@@ -116,6 +57,7 @@ class TestTinygradKernelRoundtrip(unittest.TestCase):
|
||||
"""
|
||||
arch = self.arch
|
||||
|
||||
from test.amd.test_compare_emulators import get_kernels_from_tinygrad
|
||||
from tinygrad.runtime.support.elf import elf_loader
|
||||
from tinygrad.runtime.support.compiler_amd import HIPCompiler, AMDLLVMCompiler
|
||||
from tinygrad.helpers import DEV
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import unittest, contextlib
|
||||
from tinygrad import Device, Tensor, Context, TinyJit
|
||||
from tinygrad.device import Compiled, ProfileProgramEvent, ProfileDeviceEvent
|
||||
from tinygrad.viz.serve import load_amd_counters, VizData
|
||||
from tinygrad.viz.serve import load_amd_counters
|
||||
|
||||
@contextlib.contextmanager
|
||||
def save_sqtt():
|
||||
data = VizData()
|
||||
yield data.ctxs
|
||||
yield (ret:=[])
|
||||
Device[Device.DEFAULT].synchronize()
|
||||
Device[Device.DEFAULT]._at_profile_finalize()
|
||||
load_amd_counters(data, Compiled.profile_events)
|
||||
data.ctxs[:] = [r for r in data.ctxs if r["name"].startswith("SQTT")]
|
||||
load_amd_counters(ret, Compiled.profile_events)
|
||||
ret[:] = [r for r in ret if r["name"].startswith("SQTT")]
|
||||
|
||||
@unittest.skipUnless(Device.DEFAULT == "AMD", "only runs on AMD")
|
||||
class TestSQTTProfiler(unittest.TestCase):
|
||||
|
||||
@@ -4,7 +4,7 @@ from tinygrad import Tensor, GlobalCounters, dtypes, nn, Device, Variable
|
||||
from tinygrad.helpers import Context, getenv, DEV
|
||||
from tinygrad.engine.realize import run_schedule
|
||||
from tinygrad.engine.realize import CompiledRunner, get_program
|
||||
from tinygrad.schedule import ExecItem
|
||||
from tinygrad.engine.schedule import ExecItem
|
||||
from tinygrad.renderer import Estimates
|
||||
from tinygrad.renderer.ptx import PTXRenderer
|
||||
from test.helpers import needs_second_gpu
|
||||
|
||||
@@ -6,8 +6,8 @@ from tinygrad.uop.ops import KernelInfo, AxisType
|
||||
# **** kernels ****
|
||||
|
||||
def custom_arange_kernel(C:UOp) -> UOp:
|
||||
i = UOp.range(C.shape[0], 0)
|
||||
return C[i].store(i.cast(C.dtype.base)).end(i).sink(arg=KernelInfo(name=f"custom_arange_{C.shape[0]}"))
|
||||
i = UOp.range(C.size, 0)
|
||||
return C[i].store(i.cast(C.dtype.base)).end(i).sink(arg=KernelInfo(name=f"custom_arange_{C.size}"))
|
||||
|
||||
def custom_eye_kernel(C:UOp) -> UOp:
|
||||
i = UOp.range(C.shape[0], 0)
|
||||
@@ -16,22 +16,22 @@ def custom_eye_kernel(C:UOp) -> UOp:
|
||||
|
||||
def custom_add_one_kernel(B:UOp, A:UOp) -> UOp:
|
||||
A,B = A.flatten(), B.flatten()
|
||||
assert B.numel() == A.numel()
|
||||
i = UOp.range(A.numel(), 0)
|
||||
return B[i].store(A[i] + 1).end(i).sink(arg=KernelInfo(name=f"add_one_{A.numel()}"))
|
||||
assert B.size == A.size
|
||||
i = UOp.range(A.size, 0)
|
||||
return B[i].store(A[i] + 1).end(i).sink(arg=KernelInfo(name=f"add_one_{A.size}"))
|
||||
|
||||
def custom_elementwise_add_kernel(C:UOp, A:UOp, B:UOp) -> UOp:
|
||||
C,A,B = C.flatten(), A.flatten(), B.flatten()
|
||||
i = UOp.range(C.numel(), 0)
|
||||
return C[i].store(A[i]+B[i]).end(i).sink(arg=KernelInfo(name=f"custom_add_kernel_{C.numel()}")).simplify()
|
||||
i = UOp.range(C.size, 0)
|
||||
return C[i].store(A[i]+B[i]).end(i).sink(arg=KernelInfo(name=f"custom_add_kernel_{C.size}")).simplify()
|
||||
|
||||
def custom_elementwise_addmul_kernel(C:UOp, D:UOp, A:UOp, B:UOp) -> UOp:
|
||||
C,D,A,B = C.flatten(), D.flatten(), A.flatten(), B.flatten()
|
||||
assert C.numel() == D.numel()
|
||||
i = UOp.range(C.numel(), 0)
|
||||
assert C.size == D.size
|
||||
i = UOp.range(C.size, 0)
|
||||
store_c = C[i].store(A[i]+B[i])
|
||||
store_d = D[i].store(A[i]*B[i])
|
||||
return UOp.group(store_c, store_d).end(i).sink(arg=KernelInfo(name=f"custom_addmul_kernel_{C.numel()}")).simplify()
|
||||
return UOp.group(store_c, store_d).end(i).sink(arg=KernelInfo(name=f"custom_addmul_kernel_{C.size}")).simplify()
|
||||
|
||||
def custom_gemm(C:UOp, A:UOp, B:UOp) -> UOp:
|
||||
assert A.shape[1] == B.shape[0]
|
||||
@@ -291,10 +291,10 @@ class TestCustomKernel(unittest.TestCase):
|
||||
|
||||
def custom_add_with_tmp(o1:UOp, o2:UOp, A:UOp, B:UOp) -> UOp:
|
||||
o1,o2,A,B = o1.flatten(), o2.flatten(), A.flatten(), B.flatten()
|
||||
i = UOp.range(o1.numel(), 0)
|
||||
i = UOp.range(o1.size, 0)
|
||||
store_o1 = o1[i].store(A[i]+B[i])
|
||||
store_o2 = o2[i].store(A[i]+B[i]+2)
|
||||
return UOp.group(store_o1, store_o2).end(i).sink(arg=KernelInfo(name=f"add_with_tmp_{o1.numel()}")).simplify()
|
||||
return UOp.group(store_o1, store_o2).end(i).sink(arg=KernelInfo(name=f"add_with_tmp_{o1.size}")).simplify()
|
||||
|
||||
from tinygrad import function
|
||||
@function(precompile=True)
|
||||
|
||||
+223
-206
@@ -2,12 +2,13 @@ import numpy as np
|
||||
import functools, unittest, ctypes
|
||||
|
||||
from tinygrad.device import Device, Buffer
|
||||
from tinygrad.tensor import Tensor
|
||||
from tinygrad.helpers import Context, from_mv
|
||||
from tinygrad.tensor import Tensor, _to_np_dtype
|
||||
from tinygrad.helpers import Context, dedup, from_mv
|
||||
from tinygrad.dtype import dtypes
|
||||
from tinygrad.engine.jit import MultiGraphRunner
|
||||
from tinygrad.schedule import linear_to_schedule
|
||||
from tinygrad.uop.ops import UOp, Ops, buffers
|
||||
from tinygrad.engine.realize import BufferXfer, get_runner, CompiledRunner
|
||||
from tinygrad.engine.schedule import ExecItem
|
||||
from tinygrad.uop.ops import UOp, Ops
|
||||
|
||||
from test.helpers import needs_second_gpu
|
||||
|
||||
@@ -16,46 +17,77 @@ Tensor.manual_seed(1337)
|
||||
BUF_SIZE = 4096
|
||||
RUN_CNT = 5
|
||||
|
||||
# cache AST by (device, num_inputs)
|
||||
cached_asts: dict[tuple[str, int], UOp] = {}
|
||||
def get_ast(device:str, num_inputs:int) -> UOp:
|
||||
if (device, num_inputs) not in cached_asts:
|
||||
cached_prgs = {}
|
||||
def helper_exec_op(device, outbuf, inbufs):
|
||||
if (device, len(inbufs)) not in cached_prgs:
|
||||
with Context(DEBUG=0):
|
||||
fst = [Tensor.randn(BUF_SIZE, dtype=dtypes.int).realize() for _ in range(num_inputs)]
|
||||
fst = [Tensor.randn(BUF_SIZE, dtype=dtypes.int).realize() for i in range(len(inbufs))]
|
||||
s = fst[0]
|
||||
for i in range(1, num_inputs): s = s.bitwise_xor(fst[i])
|
||||
cached_asts[(device, num_inputs)] = s.schedule()[-1].ast
|
||||
return cached_asts[(device, num_inputs)]
|
||||
for i in range(1, len(inbufs)): s = s.bitwise_xor(fst[i])
|
||||
|
||||
def make_buffer(device, size=BUF_SIZE, fill=False):
|
||||
buf = Buffer(device, size, dtypes.int).ensure_allocated()
|
||||
si = s.schedule()[-1]
|
||||
prg = get_runner(device, si.ast)
|
||||
cached_prgs[(device, len(inbufs))] = prg
|
||||
|
||||
return ExecItem(UOp(Ops.NOOP), [outbuf] + inbufs, prg=cached_prgs[(device, len(inbufs))])
|
||||
|
||||
def helper_copy_op(device, dest, src):
|
||||
prg = BufferXfer(dest.nbytes, device, src.device)
|
||||
return ExecItem(UOp(Ops.NOOP), [dest, src], prg=prg)
|
||||
|
||||
def helper_alloc_rawbuffer(device, fill=False):
|
||||
rawbuf = Buffer(device, BUF_SIZE, dtypes.int).ensure_allocated()
|
||||
if fill:
|
||||
with Context(DEBUG=0):
|
||||
buf.copyin(Tensor(np.random.randint(-10000, 10000, size=size, dtype=np.int32)).realize().uop.base.realized.as_memoryview())
|
||||
return buf
|
||||
data = np.random.randint(-10000, 10000, size=rawbuf.size, dtype=_to_np_dtype(rawbuf.dtype))
|
||||
rawbuf.copyin(Tensor(data).realize().uop.base.realized.as_memoryview())
|
||||
return rawbuf
|
||||
|
||||
def make_view(base, offset_elems, size_elems):
|
||||
def helper_create_offset_rawbuffer(base, offset=0):
|
||||
x = Buffer(base.device, base.size-offset, base.dtype, base=base, offset=offset)
|
||||
return x.ensure_allocated()
|
||||
|
||||
def helper_alloc_rawbuffer_sized(device, size, fill=False):
|
||||
rawbuf = Buffer(device, size, dtypes.int).ensure_allocated()
|
||||
if fill:
|
||||
with Context(DEBUG=0):
|
||||
data = np.random.randint(-10000, 10000, size=rawbuf.size, dtype=_to_np_dtype(rawbuf.dtype))
|
||||
rawbuf.copyin(Tensor(data).realize().uop.base.realized.as_memoryview())
|
||||
return rawbuf
|
||||
|
||||
def helper_make_view(base, offset_elems, size_elems):
|
||||
return Buffer(base.device, size_elems, base.dtype, base=base, offset=offset_elems * base.dtype.itemsize).ensure_allocated()
|
||||
|
||||
def get_buf_uop(buf:Buffer, cache:dict[Buffer,UOp]) -> UOp:
|
||||
if buf not in cache:
|
||||
cache[buf] = u = UOp.new_buffer(buf.device, buf.size, buf.dtype)
|
||||
buffers[u] = buf
|
||||
return cache[buf]
|
||||
|
||||
def make_graph(graph_cls, calls:list[UOp]):
|
||||
linear = UOp(Ops.LINEAR, src=tuple(calls))
|
||||
cf = UOp(Ops.CUSTOM_FUNCTION, dtypes.void, src=(linear,), arg="graph")
|
||||
return graph_cls(cf, [])
|
||||
|
||||
def run_schedule(calls:list[UOp]):
|
||||
for ei in linear_to_schedule(UOp(Ops.LINEAR, src=tuple(calls))): ei.lower().run({})
|
||||
|
||||
def zero_bufs(bufs):
|
||||
for b in bufs:
|
||||
mv = memoryview(bytearray(b.nbytes))
|
||||
def helper_run_jit(jis, bufs, out_buffers):
|
||||
for rawbuf in out_buffers:
|
||||
mv = memoryview(bytearray(rawbuf.size * rawbuf.dtype.itemsize))
|
||||
ctypes.memset(from_mv(mv), 0, len(mv))
|
||||
b.copyin(mv)
|
||||
rawbuf.copyin(mv)
|
||||
|
||||
for ei in jis: ei.run({}, jit=True)
|
||||
return [rawbuf.as_memoryview() for rawbuf in bufs]
|
||||
|
||||
def helper_test_graphs(graph_impl, graphs, runs=RUN_CNT):
|
||||
reg_ji = []
|
||||
bufs = []
|
||||
out_buffers = set()
|
||||
for graph in graphs:
|
||||
for ji in graph:
|
||||
out_buffers.update([ji.bufs[i] for i in (ji.prg.p.outs if isinstance(ji.prg, CompiledRunner) else [0])])
|
||||
bufs += ji.bufs
|
||||
reg_ji.append(ji)
|
||||
bufs = dedup(bufs)
|
||||
|
||||
ground_thruth_bufs = helper_run_jit(reg_ji, bufs, out_buffers)
|
||||
ground_truth_np = [np.frombuffer(x, _to_np_dtype(bufs[i].dtype)) for i,x in enumerate(ground_thruth_bufs)]
|
||||
|
||||
# Build graphs
|
||||
gr_ji = [ExecItem(UOp(Ops.NOOP), [], prg=graph_impl(None, None, graph)) for graph in graphs]
|
||||
|
||||
for _ in range(runs):
|
||||
test_bufs = helper_run_jit(gr_ji, bufs, out_buffers)
|
||||
test_bufs_np = [np.frombuffer(x, _to_np_dtype(bufs[i].dtype)) for i,x in enumerate(test_bufs)]
|
||||
for i in range(len(ground_thruth_bufs)): np.testing.assert_equal(ground_truth_np[i], test_bufs_np[i])
|
||||
|
||||
@unittest.skipUnless(Device[Device.DEFAULT].graph is not None, "graph support required")
|
||||
class TestGraph(unittest.TestCase):
|
||||
@@ -69,251 +101,236 @@ class TestGraph(unittest.TestCase):
|
||||
|
||||
def test_order_2_writes_to_same_buf(self):
|
||||
d0 = Device.DEFAULT
|
||||
b = [make_buffer(d0, fill=True) for _ in range(5)]
|
||||
c: dict[Buffer,UOp] = {}
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(5)]
|
||||
|
||||
calls = [
|
||||
get_ast(d0, 2).call(get_buf_uop(b[0],c), get_buf_uop(b[1],c), get_buf_uop(b[2],c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(b[0],c), get_buf_uop(b[3],c), get_buf_uop(b[4],c), metadata=()),
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[0], [b0[1], b0[2]]), helper_exec_op(d0, b0[0], [b0[3], b0[4]])]
|
||||
]
|
||||
|
||||
zero_bufs([b[0]])
|
||||
run_schedule(calls)
|
||||
expected = [np.frombuffer(x.as_memoryview(), np.int32).copy() for x in b]
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs([b[0]])
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for i, buf in enumerate(b): np.testing.assert_equal(expected[i], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_order_read_write_same_buf(self):
|
||||
d0 = Device.DEFAULT
|
||||
b = [make_buffer(d0, fill=True) for _ in range(5)]
|
||||
c: dict[Buffer,UOp] = {}
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(5)]
|
||||
|
||||
calls = [
|
||||
get_ast(d0, 2).call(get_buf_uop(b[0],c), get_buf_uop(b[1],c), get_buf_uop(b[2],c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(b[1],c), get_buf_uop(b[3],c), get_buf_uop(b[4],c), metadata=()),
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[0], [b0[1], b0[2]]), helper_exec_op(d0, b0[1], [b0[3], b0[4]])]
|
||||
]
|
||||
|
||||
zero_bufs([b[0], b[1]])
|
||||
run_schedule(calls)
|
||||
expected = [np.frombuffer(x.as_memoryview(), np.int32).copy() for x in b]
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs([b[0], b[1]])
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for i, buf in enumerate(b): np.testing.assert_equal(expected[i], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_order_write_read_same_buf(self):
|
||||
d0 = Device.DEFAULT
|
||||
b = [make_buffer(d0, fill=True) for _ in range(5)]
|
||||
c: dict[Buffer,UOp] = {}
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(5)]
|
||||
|
||||
calls = [
|
||||
get_ast(d0, 2).call(get_buf_uop(b[0],c), get_buf_uop(b[1],c), get_buf_uop(b[2],c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(b[1],c), get_buf_uop(b[0],c), get_buf_uop(b[4],c), metadata=()),
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[0], [b0[1], b0[2]]), helper_exec_op(d0, b0[1], [b0[0], b0[4]])]
|
||||
]
|
||||
|
||||
zero_bufs([b[0], b[1]])
|
||||
run_schedule(calls)
|
||||
expected = [np.frombuffer(x.as_memoryview(), np.int32).copy() for x in b]
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs([b[0], b[1]])
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for i, buf in enumerate(b): np.testing.assert_equal(expected[i], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_order_copy_writed(self):
|
||||
self.skip_if_not_multigraph()
|
||||
d0 = Device.DEFAULT
|
||||
b = [make_buffer(d0, fill=True) for _ in range(4)]
|
||||
c: dict[Buffer,UOp] = {}
|
||||
|
||||
calls = [
|
||||
get_ast(d0, 2).call(get_buf_uop(b[0],c), get_buf_uop(b[1],c), get_buf_uop(b[2],c), metadata=()),
|
||||
UOp(Ops.COPY).call(get_buf_uop(b[3],c), get_buf_uop(b[0],c), metadata=()),
|
||||
d0 = Device.DEFAULT
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(4)]
|
||||
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[0], [b0[1], b0[2]]), helper_copy_op(d0, b0[3], b0[0])]
|
||||
]
|
||||
|
||||
zero_bufs([b[0], b[3]])
|
||||
run_schedule(calls)
|
||||
expected = [np.frombuffer(x.as_memoryview(), np.int32).copy() for x in b]
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs([b[0], b[3]])
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for i, buf in enumerate(b): np.testing.assert_equal(expected[i], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_order_copy_then_read(self):
|
||||
self.skip_if_not_multigraph()
|
||||
d0 = Device.DEFAULT
|
||||
b = [make_buffer(d0, fill=True) for _ in range(4)]
|
||||
c: dict[Buffer,UOp] = {}
|
||||
|
||||
calls = [
|
||||
UOp(Ops.COPY).call(get_buf_uop(b[1],c), get_buf_uop(b[0],c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(b[3],c), get_buf_uop(b[1],c), get_buf_uop(b[2],c), metadata=()),
|
||||
d0 = Device.DEFAULT
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(4)]
|
||||
|
||||
graphs = [
|
||||
[helper_copy_op(d0, b0[1], b0[0]), helper_exec_op(d0, b0[3], [b0[1], b0[2]])]
|
||||
]
|
||||
|
||||
zero_bufs([b[1], b[3]])
|
||||
run_schedule(calls)
|
||||
expected = [np.frombuffer(x.as_memoryview(), np.int32).copy() for x in b]
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs([b[1], b[3]])
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for i, buf in enumerate(b): np.testing.assert_equal(expected[i], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_read_write_several_graphs(self):
|
||||
d0 = Device.DEFAULT
|
||||
b = [make_buffer(d0, fill=True) for _ in range(8)]
|
||||
c: dict[Buffer,UOp] = {}
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(8)]
|
||||
|
||||
calls1 = [get_ast(d0, 2).call(get_buf_uop(b[3],c), get_buf_uop(b[1],c), get_buf_uop(b[2],c), metadata=())]
|
||||
calls2 = [get_ast(d0, 2).call(get_buf_uop(b[4],c), get_buf_uop(b[1],c), get_buf_uop(b[3],c), metadata=())]
|
||||
calls3 = [get_ast(d0, 2).call(get_buf_uop(b[5],c), get_buf_uop(b[4],c), get_buf_uop(b[2],c), metadata=())]
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[3], [b0[1], b0[2]])],
|
||||
[helper_exec_op(d0, b0[4], [b0[1], b0[3]])],
|
||||
[helper_exec_op(d0, b0[5], [b0[4], b0[2]])]
|
||||
]
|
||||
|
||||
out = [b[3], b[4], b[5]]
|
||||
zero_bufs(out)
|
||||
run_schedule(calls1 + calls2 + calls3)
|
||||
expected = [np.frombuffer(x.as_memoryview(), np.int32).copy() for x in b]
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs(out)
|
||||
make_graph(Device[d0].graph, calls1)([], {})
|
||||
make_graph(Device[d0].graph, calls2)([], {})
|
||||
make_graph(Device[d0].graph, calls3)([], {})
|
||||
for i, buf in enumerate(b): np.testing.assert_equal(expected[i], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[3], [b0[1], b0[2]]), helper_exec_op(d0, b0[4], [b0[1], b0[2]]), helper_exec_op(d0, b0[5], [b0[1], b0[2]])],
|
||||
[helper_exec_op(d0, b0[2], [b0[6], b0[7]])]
|
||||
]
|
||||
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
@needs_second_gpu
|
||||
def test_copies_2_devs(self):
|
||||
self.skip_if_not_multigraph()
|
||||
d0, d1 = Device.DEFAULT, f"{Device.DEFAULT}:1"
|
||||
b0 = [make_buffer(d0, fill=True) for _ in range(3)]
|
||||
b1 = [make_buffer(d1, fill=True)]
|
||||
c: dict[Buffer,UOp] = {}
|
||||
|
||||
calls = [
|
||||
UOp(Ops.COPY).call(get_buf_uop(b1[0],c), get_buf_uop(b0[0],c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(b0[2],c), get_buf_uop(b0[0],c), get_buf_uop(b0[1],c), metadata=()),
|
||||
d0, d1 = Device.DEFAULT, f"{Device.DEFAULT}:1"
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(3)]
|
||||
b1 = [helper_alloc_rawbuffer(d1, fill=True) for _ in range(1)]
|
||||
|
||||
graphs = [
|
||||
[helper_copy_op(d0, b1[0], b0[0]), helper_exec_op(d0, b0[2], [b0[0], b0[1]])]
|
||||
]
|
||||
|
||||
out = [b1[0], b0[2]]
|
||||
zero_bufs(out)
|
||||
run_schedule(calls)
|
||||
expected = {buf: np.frombuffer(buf.as_memoryview(), np.int32).copy() for buf in b0 + b1}
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs(out)
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for buf in b0 + b1: np.testing.assert_equal(expected[buf], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
@needs_second_gpu
|
||||
def test_copies_after_graph_global(self):
|
||||
self.skip_if_not_multigraph()
|
||||
|
||||
d0, d1, d2, d3 = Device.DEFAULT, f"{Device.DEFAULT}:1", f"{Device.DEFAULT}:2", f"{Device.DEFAULT}:3"
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(8)]
|
||||
b1 = [helper_alloc_rawbuffer(d1, fill=True) for _ in range(6)]
|
||||
b2 = [helper_alloc_rawbuffer(d2, fill=True) for _ in range(6)]
|
||||
b3 = [helper_alloc_rawbuffer(d3, fill=True) for _ in range(6)]
|
||||
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[2], [b0[0], b0[1]]), helper_exec_op(d0, b0[3], [b0[0], b0[2]]), helper_exec_op(d0, b0[4], [b0[3], b0[2]]),
|
||||
helper_exec_op(d0, b0[5], [b0[0], b0[2]]), helper_exec_op(d0, b0[6], [b0[1], b0[2]]), helper_exec_op(d0, b0[7], [b0[0], b0[2]])],
|
||||
[helper_copy_op(d1, b0[2], b1[0])],
|
||||
[helper_exec_op(d0, b0[2], [b0[0], b0[1]]), helper_exec_op(d0, b0[3], [b0[0], b0[2]]), helper_exec_op(d0, b0[4], [b0[3], b0[2]]),
|
||||
helper_exec_op(d0, b0[5], [b0[0], b0[2]]), helper_exec_op(d0, b0[6], [b0[1], b0[2]]), helper_exec_op(d0, b0[7], [b0[0], b0[2]])],
|
||||
[helper_copy_op(d3, b0[2], b3[0])],
|
||||
]
|
||||
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[2], [b0[0], b0[1]]), helper_exec_op(d0, b0[3], [b0[0], b0[2]]), helper_exec_op(d0, b0[4], [b0[3], b0[2]]),
|
||||
helper_exec_op(d0, b0[5], [b0[0], b0[2]]), helper_copy_op(d0, b2[0], b0[2]), helper_copy_op(d0, b2[1], b0[5]),
|
||||
helper_exec_op(d0, b0[7], [b0[0], b0[2]])],
|
||||
[helper_copy_op(d1, b0[2], b1[0])],
|
||||
[helper_exec_op(d0, b0[2], [b0[0], b0[1]])],
|
||||
[helper_copy_op(d3, b0[2], b3[0])],
|
||||
]
|
||||
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
graphs = [
|
||||
[helper_exec_op(d0, b0[2], [b0[0], b0[1]]), helper_exec_op(d0, b0[3], [b0[0], b0[2]]), helper_exec_op(d0, b0[4], [b0[3], b0[2]]),
|
||||
helper_exec_op(d0, b0[5], [b0[0], b0[2]]), helper_copy_op(d0, b2[0], b0[2]), helper_copy_op(d0, b2[1], b0[5]),
|
||||
helper_exec_op(d0, b0[7], [b0[0], b0[2]])],
|
||||
[helper_copy_op(d1, b0[5], b1[0])],
|
||||
[helper_copy_op(d3, b0[5], b3[0])],
|
||||
]
|
||||
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
graphs = [
|
||||
[helper_copy_op(d1, b0[5], b1[0])],
|
||||
[helper_copy_op(d3, b0[5], b3[0])],
|
||||
]
|
||||
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
@needs_second_gpu
|
||||
def test_graph_after_copies_devs(self):
|
||||
self.skip_if_not_multigraph()
|
||||
|
||||
d0, d1, d2, d3 = Device.DEFAULT, f"{Device.DEFAULT}:1", f"{Device.DEFAULT}:2", f"{Device.DEFAULT}:3"
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(8)]
|
||||
b1 = [helper_alloc_rawbuffer(d1, fill=True) for _ in range(1)]
|
||||
b2 = [helper_alloc_rawbuffer(d2, fill=True) for _ in range(2)]
|
||||
b3 = [helper_alloc_rawbuffer(d3, fill=True) for _ in range(2)]
|
||||
|
||||
graphs = [
|
||||
[helper_copy_op(d1, b0[0], b1[0])],
|
||||
[helper_copy_op(d2, b0[1], b2[0]), helper_copy_op(d3, b0[2], b3[0])],
|
||||
[helper_exec_op(d0, b0[3], [b0[0], b0[2]]), helper_exec_op(d0, b0[4], [b0[3], b0[2]]),
|
||||
helper_exec_op(d0, b0[5], [b0[0], b0[2]])],
|
||||
]
|
||||
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
graphs = [
|
||||
[helper_copy_op(d1, b0[0], b1[0])],
|
||||
[helper_exec_op(d0, b0[2], [b0[0], b0[1]])],
|
||||
[helper_copy_op(d2, b0[1], b2[0]), helper_copy_op(d3, b0[2], b3[0])],
|
||||
[helper_exec_op(d0, b0[3], [b0[0], b0[2]]), helper_exec_op(d0, b0[4], [b0[3], b0[2]]),
|
||||
helper_exec_op(d0, b0[5], [b0[0], b0[2]])],
|
||||
]
|
||||
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_graph_offset_bufs(self):
|
||||
self.skip_if_not_multigraph()
|
||||
|
||||
d0 = Device.DEFAULT
|
||||
if not hasattr(Device[d0].allocator, "_offset"): self.skipTest("device does not support _offset")
|
||||
|
||||
b0 = make_buffer(d0, fill=True)
|
||||
b1 = make_view(b0, 0, b0.size)
|
||||
b2 = make_view(b0, 0, b0.size)
|
||||
c: dict[Buffer,UOp] = {}
|
||||
b0 = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(1)]
|
||||
b0 += [helper_create_offset_rawbuffer(b0[0]), helper_create_offset_rawbuffer(b0[0])]
|
||||
|
||||
calls = [
|
||||
UOp(Ops.COPY).call(get_buf_uop(b0,c), get_buf_uop(b2,c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(b1,c), get_buf_uop(b0,c), get_buf_uop(b2,c), metadata=()),
|
||||
graphs = [
|
||||
[helper_copy_op(d0, b0[0], b0[2]), helper_exec_op(d0, b0[1], [b0[0], b0[2]])],
|
||||
]
|
||||
|
||||
zero_bufs([b0])
|
||||
run_schedule(calls)
|
||||
expected = np.frombuffer(b0.as_memoryview(), np.int32).copy()
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs([b0])
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
np.testing.assert_equal(expected, np.frombuffer(b0.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_partial_write_preserves_write_dep(self):
|
||||
self.skip_if_not_multigraph()
|
||||
self.skip_if_no_offset()
|
||||
d0 = Device.DEFAULT
|
||||
|
||||
base = make_buffer(d0, BUF_SIZE * 2, fill=True)
|
||||
copy_src_full = make_buffer(d0, BUF_SIZE * 2, fill=True)
|
||||
copy_src_lo = make_buffer(d0, fill=True)
|
||||
v_lo, v_hi = make_view(base, 0, BUF_SIZE), make_view(base, BUF_SIZE, BUF_SIZE)
|
||||
a, out = make_buffer(d0, fill=True), make_buffer(d0, fill=True)
|
||||
c: dict[Buffer,UOp] = {}
|
||||
base = helper_alloc_rawbuffer_sized(d0, BUF_SIZE * 2, fill=True)
|
||||
copy_src_full = helper_alloc_rawbuffer_sized(d0, BUF_SIZE * 2, fill=True)
|
||||
copy_src_lo = helper_alloc_rawbuffer(d0, fill=True)
|
||||
v_lo = helper_make_view(base, 0, BUF_SIZE)
|
||||
v_hi = helper_make_view(base, BUF_SIZE, BUF_SIZE)
|
||||
a, c = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(2)]
|
||||
|
||||
calls = [
|
||||
UOp(Ops.COPY).call(get_buf_uop(base,c), get_buf_uop(copy_src_full,c), metadata=()),
|
||||
UOp(Ops.COPY).call(get_buf_uop(v_lo,c), get_buf_uop(copy_src_lo,c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(out,c), get_buf_uop(v_hi,c), get_buf_uop(a,c), metadata=()),
|
||||
graphs = [
|
||||
[helper_copy_op(d0, base, copy_src_full), helper_copy_op(d0, v_lo, copy_src_lo), helper_exec_op(d0, c, [v_hi, a])]
|
||||
]
|
||||
|
||||
zero_bufs([base, out])
|
||||
run_schedule(calls)
|
||||
expected = {base: np.frombuffer(base.as_memoryview(), np.int32).copy(), out: np.frombuffer(out.as_memoryview(), np.int32).copy()}
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs([base, out])
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for buf in [base, out]: np.testing.assert_equal(expected[buf], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_partial_write_preserves_read_dep(self):
|
||||
self.skip_if_not_multigraph()
|
||||
self.skip_if_no_offset()
|
||||
d0 = Device.DEFAULT
|
||||
|
||||
base = make_buffer(d0, BUF_SIZE * 2, fill=True)
|
||||
copy_dst = make_buffer(d0, BUF_SIZE * 2, fill=True)
|
||||
copy_src_lo = make_buffer(d0, fill=True)
|
||||
v_lo, v_hi = make_view(base, 0, BUF_SIZE), make_view(base, BUF_SIZE, BUF_SIZE)
|
||||
a, b = make_buffer(d0, fill=True), make_buffer(d0, fill=True)
|
||||
c: dict[Buffer,UOp] = {}
|
||||
base = helper_alloc_rawbuffer_sized(d0, BUF_SIZE * 2, fill=True)
|
||||
copy_dst = helper_alloc_rawbuffer_sized(d0, BUF_SIZE * 2, fill=True)
|
||||
copy_src_lo = helper_alloc_rawbuffer(d0, fill=True)
|
||||
v_lo = helper_make_view(base, 0, BUF_SIZE)
|
||||
v_hi = helper_make_view(base, BUF_SIZE, BUF_SIZE)
|
||||
a, b = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(2)]
|
||||
|
||||
calls = [
|
||||
UOp(Ops.COPY).call(get_buf_uop(copy_dst,c), get_buf_uop(base,c), metadata=()),
|
||||
UOp(Ops.COPY).call(get_buf_uop(v_lo,c), get_buf_uop(copy_src_lo,c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(v_hi,c), get_buf_uop(a,c), get_buf_uop(b,c), metadata=()),
|
||||
graphs = [
|
||||
[helper_copy_op(d0, copy_dst, base), helper_copy_op(d0, v_lo, copy_src_lo), helper_exec_op(d0, v_hi, [a, b])]
|
||||
]
|
||||
|
||||
zero_bufs([copy_dst, base])
|
||||
run_schedule(calls)
|
||||
expected = {copy_dst: np.frombuffer(copy_dst.as_memoryview(), np.int32).copy(), base: np.frombuffer(base.as_memoryview(), np.int32).copy()}
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs([copy_dst, base])
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for buf in [copy_dst, base]: np.testing.assert_equal(expected[buf], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
def test_middle_write_splits_write_dep(self):
|
||||
self.skip_if_not_multigraph()
|
||||
self.skip_if_no_offset()
|
||||
d0 = Device.DEFAULT
|
||||
|
||||
base = make_buffer(d0, BUF_SIZE * 3, fill=True)
|
||||
copy_src_full = make_buffer(d0, BUF_SIZE * 3, fill=True)
|
||||
copy_src_mid = make_buffer(d0, fill=True)
|
||||
v_lo, v_mid, v_hi = make_view(base, 0, BUF_SIZE), make_view(base, BUF_SIZE, BUF_SIZE), make_view(base, BUF_SIZE * 2, BUF_SIZE)
|
||||
a, out1, out2 = make_buffer(d0, fill=True), make_buffer(d0, fill=True), make_buffer(d0, fill=True)
|
||||
c: dict[Buffer,UOp] = {}
|
||||
base = helper_alloc_rawbuffer_sized(d0, BUF_SIZE * 3, fill=True)
|
||||
copy_src_full = helper_alloc_rawbuffer_sized(d0, BUF_SIZE * 3, fill=True)
|
||||
copy_src_mid = helper_alloc_rawbuffer(d0, fill=True)
|
||||
v_lo = helper_make_view(base, 0, BUF_SIZE)
|
||||
v_mid = helper_make_view(base, BUF_SIZE, BUF_SIZE)
|
||||
v_hi = helper_make_view(base, BUF_SIZE * 2, BUF_SIZE)
|
||||
a, c, e = [helper_alloc_rawbuffer(d0, fill=True) for _ in range(3)]
|
||||
|
||||
calls = [
|
||||
UOp(Ops.COPY).call(get_buf_uop(base,c), get_buf_uop(copy_src_full,c), metadata=()),
|
||||
UOp(Ops.COPY).call(get_buf_uop(v_mid,c), get_buf_uop(copy_src_mid,c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(out1,c), get_buf_uop(v_lo,c), get_buf_uop(a,c), metadata=()),
|
||||
get_ast(d0, 2).call(get_buf_uop(out2,c), get_buf_uop(v_hi,c), get_buf_uop(a,c), metadata=()),
|
||||
graphs = [
|
||||
[helper_copy_op(d0, base, copy_src_full), helper_copy_op(d0, v_mid, copy_src_mid),
|
||||
helper_exec_op(d0, c, [v_lo, a]), helper_exec_op(d0, e, [v_hi, a])]
|
||||
]
|
||||
|
||||
outs = [base, out1, out2]
|
||||
zero_bufs(outs)
|
||||
run_schedule(calls)
|
||||
expected = {buf: np.frombuffer(buf.as_memoryview(), np.int32).copy() for buf in outs}
|
||||
|
||||
for _ in range(RUN_CNT):
|
||||
zero_bufs(outs)
|
||||
make_graph(Device[d0].graph, calls)([], {})
|
||||
for buf in outs: np.testing.assert_equal(expected[buf], np.frombuffer(buf.as_memoryview(), np.int32))
|
||||
helper_test_graphs(Device[d0].graph, graphs)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -4,7 +4,7 @@ from tinygrad import Tensor, Device
|
||||
from tinygrad.helpers import get_single_element
|
||||
from tinygrad.codegen.opt import Opt, OptOps
|
||||
from tinygrad.engine.realize import CompiledRunner, get_program
|
||||
from tinygrad.schedule import ExecItem
|
||||
from tinygrad.engine.schedule import ExecItem
|
||||
|
||||
class TestOptGemm(unittest.TestCase):
|
||||
@classmethod
|
||||
|
||||
@@ -6,7 +6,7 @@ from tinygrad import Tensor, Context, Device, dtypes
|
||||
from tinygrad.uop.ops import Ops
|
||||
from tinygrad.codegen.opt import Opt, OptOps
|
||||
from tinygrad.engine.realize import CompiledRunner, get_program
|
||||
from tinygrad.schedule import ExecItem
|
||||
from tinygrad.engine.schedule import ExecItem
|
||||
|
||||
N = 512
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from tinygrad.device import Buffer, Device
|
||||
from tinygrad.uop.ops import Ops, UOp, KernelInfo, AxisType
|
||||
from tinygrad.renderer.cstyle import CStyleLanguage
|
||||
from tinygrad.engine.realize import CompiledRunner, get_program, get_runner
|
||||
from tinygrad.schedule import ExecItem
|
||||
from tinygrad.engine.schedule import ExecItem
|
||||
from tinygrad.device import is_dtype_supported
|
||||
from tinygrad.codegen.opt import Opt, OptOps
|
||||
from tinygrad.renderer.ptx import PTXRenderer
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
import unittest
|
||||
from tinygrad import Device, Tensor
|
||||
from tinygrad.schedule import create_schedule
|
||||
from tinygrad.engine.schedule import create_schedule
|
||||
from tinygrad.runtime.ops_amd import AMDDevice
|
||||
|
||||
class TestAMD(unittest.TestCase):
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import time, unittest
|
||||
from tinygrad.runtime.support.hip_comgr import compile_hip
|
||||
from tinygrad import Tensor
|
||||
from tinygrad.device import Device
|
||||
from tinygrad.schedule import create_schedule
|
||||
from tinygrad.engine.schedule import create_schedule
|
||||
from tinygrad.codegen.opt.kernel import Kernel
|
||||
|
||||
class TestHIPCompileSpeed(unittest.TestCase):
|
||||
|
||||
Vendored
+1
-1
@@ -7,7 +7,7 @@ from tinygrad import GlobalCounters, Tensor, Device
|
||||
from tinygrad.helpers import getenv
|
||||
from tinygrad.nn.state import get_parameters
|
||||
from tinygrad.engine.realize import capturing, run_schedule
|
||||
from tinygrad.schedule import linear_to_schedule
|
||||
from tinygrad.engine.schedule import linear_to_schedule
|
||||
from tinygrad.tensor import _to_np_dtype
|
||||
|
||||
class CLCache:
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
import gc
|
||||
from tinygrad import Tensor, UOp, Device, nn
|
||||
from tinygrad.schedule import schedule_cache
|
||||
from tinygrad.engine.schedule import schedule_cache
|
||||
from tinygrad.engine.realize import method_cache, get_program
|
||||
from tinygrad.schedule.indexing import apply_movement_op, _apply_reshape
|
||||
from tinygrad.uop.divandmod import fold_divmod_general
|
||||
|
||||
Vendored
+2
-2
@@ -5,7 +5,7 @@ from tinygrad.helpers import Context, getenv, from_mv
|
||||
from tinygrad.dtype import dtypes
|
||||
from tinygrad.tensor import Tensor, _to_np_dtype
|
||||
from tinygrad.engine.realize import BufferXfer, get_runner
|
||||
from tinygrad.schedule import ExecItem
|
||||
from tinygrad.engine.schedule import ExecItem
|
||||
from tinygrad.uop.ops import UOp, Ops
|
||||
from tinygrad.engine.jit import apply_graph_to_jit
|
||||
|
||||
@@ -85,7 +85,7 @@ def run_jit(jis, all_buffers, input_buffers, var_vals):
|
||||
with Context(DEBUG=0):
|
||||
for rawbuf in all_buffers:
|
||||
if rawbuf in input_buffers: continue
|
||||
mv = memoryview(bytearray(rawbuf.nbytes))
|
||||
mv = memoryview(bytearray(rawbuf.size * rawbuf.dtype.itemsize))
|
||||
ctypes.memset(from_mv(mv), 0, len(mv))
|
||||
rawbuf.copyin(mv)
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ class ProcessReplayWarning(Warning): pass
|
||||
# *** replay the function and convert return values to string
|
||||
|
||||
def replay_get_program(p:ProgramSpec, ast:UOp, renderer:Renderer, opts:list[Opt]|None=None) -> tuple[str, str, tuple[Any, ...]]:
|
||||
if ast.op is Ops.BEAM: ast = ast.src[0]
|
||||
# the ast.arg is non None if we are inside of search.py
|
||||
sink_arg = ast.arg or KernelInfo()
|
||||
if opts is not None: sink_arg = replace(sink_arg, opts_to_apply=tuple(opts))
|
||||
|
||||
@@ -4,7 +4,7 @@ Test with `pytest -n12 test/amd/`
|
||||
`DEV=AMD:LLVM pytest -n12 test/amd/`
|
||||
|
||||
* dsl.py -- helpers for the autogen instruction classes in `__init__.py`. should be standalone with init
|
||||
* test/mockgpu/amd/emu.py -- an emulator for RDNA that runs in tinygrad with `DEV=AMD MOCKGPU=1`
|
||||
* test/mockgpu/amd/emu.py -- an emulator for RDNA that runs in tinygrad with `DEV=AMD MOCKGPU=1 PYTHON_REMU=1`
|
||||
* generate.py -- extract assembly format + instruction pseudocode from AMD XML + PDF
|
||||
* test/mockgpu/amd/pcode.py -- pseudocode to UOp transformation
|
||||
* sqtt.py -- SQTT parser
|
||||
@@ -20,19 +20,20 @@ test_llvm.py tests asm/disasm on the LLVM tests, confirming it behaves the same
|
||||
|
||||
tinygrad's dtype tests should pass with and without LLVM. they run in about 12 seconds.
|
||||
|
||||
`DEV=AMD MOCKGPU=1 pytest -n=12 test/backend/test_dtype_alu.py test/backend/test_dtype.py`
|
||||
`DEV=AMD:LLVM MOCKGPU=1 pytest -n=12 test/backend/test_dtype_alu.py test/backend/test_dtype.py`
|
||||
`DEV=AMD PYTHON_REMU=1 MOCKGPU=1 pytest -n=12 test/backend/test_dtype_alu.py test/backend/test_dtype.py`
|
||||
`DEV=AMD:LLVM PYTHON_REMU=1 MOCKGPU=1 pytest -n=12 test/backend/test_dtype_alu.py test/backend/test_dtype.py`
|
||||
|
||||
The ops tests also pass, but they are very slow, so you should run them one at a time.
|
||||
|
||||
`SKIP_SLOW_TEST=1 DEV=AMD MOCKGPU=1 pytest -n=12 test/backend/test_ops.py`
|
||||
`SKIP_SLOW_TEST=1 DEV=AMD:LLVM MOCKGPU=1 pytest -n=12 test/backend/test_ops.py`
|
||||
`SKIP_SLOW_TEST=1 DEV=AMD PYTHON_REMU=1 MOCKGPU=1 pytest -n=12 test/backend/test_ops.py`
|
||||
`SKIP_SLOW_TEST=1 DEV=AMD:LLVM PYTHON_REMU=1 MOCKGPU=1 pytest -n=12 test/backend/test_ops.py`
|
||||
|
||||
When something is caught by main tinygrad tests, a local regression test should be added to `test/amd`.
|
||||
While working with tinygrad, you can dump the assembly with `DEBUG=7`. These tests all pass on real hardware
|
||||
If a test is failing with `DEV=AMD MOCKGPU=1` it's because an instruction is emulated incorrectly.
|
||||
If a test is failing with `DEV=AMD PYTHON_REMU=1 MOCKGPU=1` it's because an instruction is emulated incorrectly.
|
||||
You can test without `MOCKGPU=1` to test on real hardware, if it works on real hardware there's a bug in the emulator.
|
||||
IMPORTANT: if a test is failing in the emulator, it's an instruction bug. Use DEBUG=7, get the instructions, and debug.
|
||||
|
||||
Currently, only RDNA3 is well supported, but when finished, this will support RDNA3+RDNA4+CDNA in ~3000 lines.
|
||||
Get line count with `cloc --by-file tinygrad/renderer/amd/*.py`
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ctypes, time
|
||||
from dataclasses import replace
|
||||
from test.mockgpu.gpu import VirtGPU
|
||||
from test.mockgpu.helpers import PythonRemu
|
||||
from test.mockgpu.helpers import _try_dlopen_remu
|
||||
from tinygrad.helpers import getbits, to_mv, getenv, DEV
|
||||
from tinygrad.runtime.support import c
|
||||
|
||||
@@ -41,7 +41,7 @@ WAIT_REG_MEM_FUNCTION_EQ = 3 # ==
|
||||
WAIT_REG_MEM_FUNCTION_NEQ = 4 # !=
|
||||
WAIT_REG_MEM_FUNCTION_GEQ = 5 # >=
|
||||
|
||||
remu = PythonRemu()
|
||||
remu = _try_dlopen_remu()
|
||||
|
||||
def create_sdma_packets():
|
||||
# TODO: clean up this, if we want to keep it
|
||||
@@ -212,13 +212,13 @@ class PM4Executor(AMDQueue):
|
||||
scratch_size = wavesize * (16 if self.gpu.arch == "cdna" else 4) # per-thread scratch size in bytes
|
||||
|
||||
assert prg_sz > 0, "Invalid prg ptr (not found in mapped ranges)"
|
||||
# Pass valid memory ranges, rsrc2, scratch_size, arch, and user data registers to the emulator
|
||||
remu.valid_mem_ranges = self.gpu.mapped_ranges
|
||||
remu.rsrc2 = rsrc2
|
||||
remu.scratch_size = scratch_size
|
||||
remu.arch = self.gpu.arch
|
||||
remu.user_data = user_data
|
||||
err = remu.run_asm(prg_addr, prg_sz, gl[0], gl[1], gl[2], lc[0], lc[1], lc[2], args_addr)
|
||||
# Pass valid memory ranges, rsrc2, scratch_size, arch, and user data registers to Python emulator
|
||||
if hasattr(remu, 'valid_mem_ranges'): remu.valid_mem_ranges = self.gpu.mapped_ranges
|
||||
if hasattr(remu, 'rsrc2'): remu.rsrc2 = rsrc2
|
||||
if hasattr(remu, 'scratch_size'): remu.scratch_size = scratch_size
|
||||
if hasattr(remu, 'arch'): remu.arch = self.gpu.arch
|
||||
if hasattr(remu, 'user_data'): remu.user_data = user_data
|
||||
err = remu.run_asm(prg_addr, prg_sz, *gl, *lc, args_addr)
|
||||
if err != 0: raise RuntimeError("remu does not support the new instruction introduced in this kernel")
|
||||
|
||||
def _exec_indirect_buffer(self, n):
|
||||
|
||||
+24
-111
@@ -67,7 +67,6 @@ from tinygrad.runtime.autogen.amd.rdna4 import ins as ir4
|
||||
from tinygrad.runtime.autogen.amd.cdna import ins as irc
|
||||
from tinygrad.renderer.amd.dsl import VCC_LO, EXEC_LO, SCC, ttmp
|
||||
from tinygrad.runtime.autogen.amd.common import Fmt, OpType
|
||||
from test.amd.helpers import decode_dpp16
|
||||
from test.mockgpu.amd.pcode import parse_block, _FUNCS, _set_bits, _val_to_bits
|
||||
|
||||
MASK32 = 0xFFFFFFFF
|
||||
@@ -234,6 +233,7 @@ VOPD_TO_VOP2 = {
|
||||
ir4.VOPDOp.V_DUAL_DOT2ACC_F32_F16: ir3.VOP2Op.V_DOT2ACC_F32_F16_E32,
|
||||
}
|
||||
def _wave_size(arch: str) -> int: return 64 if arch.startswith("cdna") else 32
|
||||
WAVE_SIZE = 32 # default wave size for RDNA (exported for test_compare_emulators)
|
||||
# Special registers stored after inline constants (256-259)
|
||||
PC_LO_IDX, PC_HI_IDX, SCRATCH_STRIDE_IDX = 256, 257, 259
|
||||
# SGPR buffer: 0-127 = SGPRs, 128-255 = inline constants, 256-259 = special registers
|
||||
@@ -346,7 +346,7 @@ def parse_pcode(pcode: str, srcs: dict[str, UOp | int] | None = None) -> tuple[d
|
||||
# TODO: pcode.py should tokenize full pcode string instead of line-by-line, then this hack can be removed
|
||||
lines: list[str] = []
|
||||
for l in raw_lines:
|
||||
if lines and re.search(r'(&&|\|\||[&|+\-*/^])\s*$', lines[-1]): lines[-1] = lines[-1] + ' ' + l
|
||||
if lines and lines[-1].endswith('&&'): lines[-1] = lines[-1] + ' ' + l
|
||||
else: lines.append(l)
|
||||
_, final, _ = parse_block(lines, 0, env, assigns=assigns)
|
||||
sliced = set(d.split('[')[0] for d, _ in assigns if '[' in d)
|
||||
@@ -639,13 +639,11 @@ class _Ctx:
|
||||
src0_reg = (src0_off >= _c(256)).where(src0_off - _c(256), _c(0)) # VGPR index or 0
|
||||
src1_off = self.inst_field(type(inst).src1) if hasattr(type(inst), 'src1') else None
|
||||
src2_off = self.inst_field(type(inst).src2) if hasattr(type(inst), 'src2') else None
|
||||
src1_reg = (src1_off >= _c(256)).where(src1_off - _c(256), src1_off) if src1_off is not None else _c(0)
|
||||
src2_reg = (src2_off >= _c(256)).where(src2_off - _c(256), src2_off) if src2_off is not None else _c(0)
|
||||
exec_val = self.rexec()
|
||||
exec_lo = exec_val.cast(dtypes.uint32) if exec_val.dtype == dtypes.uint64 else exec_val
|
||||
srcs = {
|
||||
'SRC0': src0_reg, 'VDST': vdst_off, 'EXEC_LO': exec_lo, 'EXEC': exec_val if exec_val.dtype == dtypes.uint64 else exec_val.cast(dtypes.uint64),
|
||||
'_vgpr': self.vgpr, '_wave_size': self.wave_size, 'SRC1': src1_reg, 'SRC2': src2_reg,
|
||||
'_vgpr': self.vgpr, '_wave_size': self.wave_size,
|
||||
'S0': self.rsrc_dyn(src0_off, _c(0, dtypes.int)) if 'WRITELANE' in op_name else src0_reg,
|
||||
'S1': self.rsrc_dyn(src1_off, _c(0, dtypes.int)) if src1_off is not None else _c(0),
|
||||
'S2': self.rsrc_dyn(src2_off, _c(0, dtypes.int)) if src2_off is not None else _c(0),
|
||||
@@ -665,11 +663,10 @@ class _Ctx:
|
||||
vcc_reg = sdst_reg if sdst_reg is not None else VCC_LO.offset
|
||||
if 'VCC' not in srcs: srcs['VCC'] = self.rmask(_c(vcc_reg))
|
||||
srcs.update({'EXEC': exec_mask, 'SCC': self.rsgpr_dyn(_c(SCC.offset)), 'laneId': lane, 'VDST': vdst_reg,
|
||||
'ROUND_MODE': _c(0), 'ROUND_TOWARD_ZERO': _c(0), 'ROUND_NEAREST_EVEN': _c(0), '_vgpr': self.vgpr, '_wave_size': self.wave_size,
|
||||
'MAX_FLOAT_F32': UOp.const(dtypes.float32, 3.4028234663852886e38),
|
||||
# CDNA SDWA byte/word select constants (E32 always uses BYTE0/WORD0 defaults)
|
||||
'SDWA_SRC0_SEL': _c(0), 'BYTE0': _c(0), 'BYTE1': _c(1), 'BYTE2': _c(2), 'BYTE3': _c(3),
|
||||
'WORD0': _c(0), 'WORD1': _c(1)}) # rounding mode and SDWA constants
|
||||
'ROUND_MODE': _c(0), 'ROUND_TOWARD_ZERO': _c(0), 'ROUND_NEAREST_EVEN': _c(0), '_vgpr': self.vgpr, '_wave_size': self.wave_size,
|
||||
# CDNA SDWA byte/word select constants (E32 always uses BYTE0/WORD0 defaults)
|
||||
'SDWA_SRC0_SEL': _c(0), 'BYTE0': _c(0), 'BYTE1': _c(1), 'BYTE2': _c(2), 'BYTE3': _c(3),
|
||||
'WORD0': _c(0), 'WORD1': _c(1)}) # rounding mode and SDWA constants
|
||||
_, assigns = parse_pcode(pcode, srcs)
|
||||
|
||||
# For integer ops with clamp, compute overflow using wide arithmetic
|
||||
@@ -719,10 +716,6 @@ class _Ctx:
|
||||
new_vcc = _set_lane_bit(old_vcc, lane, val, exec_mask)
|
||||
raw_stores.extend([('vcc', s) for s in self.wmask(_c(VCC_LO.offset), new_vcc)])
|
||||
elif dest.startswith('D0'):
|
||||
dest_suffix = re.match(r'D0\.(\w+)', dest)
|
||||
if dest_suffix is not None:
|
||||
target_dt = {'u16': dtypes.uint16, 'i16': dtypes.int16, 'f16': dtypes.half}.get(dest_suffix.group(1))
|
||||
if target_dt is not None and val.dtype != target_dt: val = val.cast(target_dt)
|
||||
if (slice_match := re.match(r'D0\[(\d+)\s*:\s*(\d+)\]', dest)):
|
||||
d0_hi_bit, d0_lo_bit = int(slice_match.group(1)), int(slice_match.group(2))
|
||||
if d0_hi_bit != 31 or d0_lo_bit != 0:
|
||||
@@ -735,8 +728,7 @@ class _Ctx:
|
||||
# For integer ops with clamp, use pre-computed saturated value; for floats, clamp to [0,1]
|
||||
if int_saturate is not None: val = int_saturate
|
||||
elif clmp and val.dtype in (dtypes.float32, dtypes.half, dtypes.float64):
|
||||
clamped = val.maximum(UOp.const(val.dtype, 0.0)).minimum(UOp.const(val.dtype, 1.0))
|
||||
val = _FUNCS['isNAN'](val).where(UOp.const(val.dtype, 0.0), clamped)
|
||||
val = val.maximum(UOp.const(val.dtype, 0.0)).minimum(UOp.const(val.dtype, 1.0))
|
||||
if val.dtype in (dtypes.uint64, dtypes.int64, dtypes.float64):
|
||||
lo, hi = _split64(val)
|
||||
raw_stores.extend([('vgpr', self.wvgpr_dyn(vdst_reg, lane, lo, exec_mask)),
|
||||
@@ -924,49 +916,6 @@ def _sdwa_write(old: UOp, val: UOp, dst_sel: UOp, dst_unused: UOp) -> UOp:
|
||||
# For PAD and SEXT, unused bits are zero (PAD) or sign-extended (SEXT). For DWORD, just return val.
|
||||
return dst_sel.eq(_c(6)).where(val, dst_unused.eq(_c(2)).where(preserved, placed))
|
||||
|
||||
def _dpp_quad_sel(quad_lane: UOp, sels: tuple[int, int, int, int]) -> UOp:
|
||||
sel = _c(sels[0], dtypes.int)
|
||||
for i, src in enumerate(sels[1:], start=1): sel = quad_lane.eq(_c(i, dtypes.int)).where(_c(src, dtypes.int), sel)
|
||||
return sel
|
||||
|
||||
def _dpp16_ctrl(lane: UOp, dpp: int, row_mask: int, bank_mask: int, wave_size: int) -> tuple[UOp, UOp, UOp]:
|
||||
"""Return (src_lane, row/bank enabled, in-bounds) for a DPP16 swizzle."""
|
||||
lane_i = lane.cast(dtypes.int)
|
||||
row_base, lane_in_row = lane_i & _c(~15, dtypes.int), lane_i & _c(15, dtypes.int)
|
||||
row = lane_i // _c(16, dtypes.int)
|
||||
bank = lane_in_row >> _c(2, dtypes.int)
|
||||
enabled = (((_c(row_mask) >> row.cast(dtypes.uint32)) & _c(1)).ne(_c(0)) &
|
||||
(((_c(bank_mask) >> bank.cast(dtypes.uint32)) & _c(1)).ne(_c(0))))
|
||||
op, arg = decode_dpp16(dpp)
|
||||
src_lane, valid = lane_i, UOp.const(dtypes.bool, True)
|
||||
|
||||
if op == 'quad_perm':
|
||||
assert isinstance(arg, tuple)
|
||||
src_lane = (lane_i & _c(~3, dtypes.int)) + _dpp_quad_sel(lane_i & _c(3, dtypes.int), arg)
|
||||
else:
|
||||
assert isinstance(arg, int)
|
||||
if op == 'row_shl': src_lane, valid = row_base + lane_in_row + _c(arg, dtypes.int), lane_in_row <= _c(15 - arg, dtypes.int)
|
||||
elif op == 'row_shr': src_lane, valid = row_base + lane_in_row - _c(arg, dtypes.int), lane_in_row >= _c(arg, dtypes.int)
|
||||
elif op == 'row_ror': src_lane = row_base + ((lane_in_row - _c(arg, dtypes.int)) & _c(15, dtypes.int))
|
||||
elif op == 'row_mirror': src_lane = row_base + (_c(15, dtypes.int) - lane_in_row)
|
||||
elif op == 'row_half_mirror': src_lane = row_base + ((lane_in_row & _c(8, dtypes.int)) | (_c(7, dtypes.int) - (lane_in_row & _c(7, dtypes.int))))
|
||||
elif op == 'row_bcast': src_lane = row_base
|
||||
elif op == 'wave_shl': src_lane, valid = lane_i + _c(arg, dtypes.int), lane_i < _c(wave_size - arg, dtypes.int)
|
||||
elif op == 'wave_rol': src_lane = (lane_i + _c(arg, dtypes.int)) % _c(wave_size, dtypes.int)
|
||||
elif op == 'wave_shr': src_lane, valid = lane_i - _c(arg, dtypes.int), lane_i >= _c(arg, dtypes.int)
|
||||
elif op == 'wave_ror': src_lane = (lane_i - _c(arg, dtypes.int)) % _c(wave_size, dtypes.int)
|
||||
else: raise NotImplementedError(f"DPP16 control {dpp:#x} ({op}:{arg}) not implemented in emulator")
|
||||
return src_lane, enabled, valid
|
||||
|
||||
def _load_dpp16_src0(ctx: _Ctx, inst, lane: UOp, fallback: UOp) -> UOp:
|
||||
"""Load a DPP16-swizzled src0 value from vsrc0."""
|
||||
src_lane, enabled, valid = _dpp16_ctrl(lane, getattr(inst, 'dpp', 0) or 0, getattr(inst, 'row_mask', 0xf) or 0xf,
|
||||
getattr(inst, 'bank_mask', 0xf) or 0xf, ctx.wave_size)
|
||||
safe_src_lane = (enabled & valid).where(src_lane, _c(0, dtypes.int))
|
||||
swizzled = ctx.rvgpr_dyn(ctx.inst_field(type(inst).vsrc0), safe_src_lane)
|
||||
invalid = UOp.const(fallback.dtype, 0) if getattr(inst, 'bc', 0) else fallback
|
||||
return enabled.where(valid.where(swizzled, invalid), fallback)
|
||||
|
||||
def _compile_sdwa(inst: irc.VOP1_SDWA | irc.VOP2_SDWA | irc.VOP2_SDWA_SDST | irc.VOPC_SDWA_SDST, ctx: _Ctx) -> UOp:
|
||||
"""Compile CDNA SDWA (Sub-Dword Access) VOP1/VOP2/VOPC instructions."""
|
||||
is_vopc = isinstance(inst, irc.VOPC_SDWA_SDST)
|
||||
@@ -1050,43 +999,33 @@ def _compile_sdwa(inst: irc.VOP1_SDWA | irc.VOP2_SDWA | irc.VOP2_SDWA_SDST | irc
|
||||
return UOp.sink(UOp.sink(*stores).end(lane), *ctx.inc_pc())
|
||||
return UOp.sink(*ctx.inc_pc())
|
||||
|
||||
def _compile_vop12(inst: ir3.VOP1 | ir3.VOP1_SDST | ir3.VOP1_DPP16 | ir3.VOP2 | ir3.VOP2_DPP16 |
|
||||
ir4.VOP1 | ir4.VOP1_SDST | ir4.VOP1_DPP16 | ir4.VOP2 | ir4.VOP2_DPP16 |
|
||||
irc.VOP1 | irc.VOP1_DPP16 | irc.VOP2 | irc.VOP2_DPP16, ctx: _Ctx) -> UOp:
|
||||
def _compile_vop12(inst: ir3.VOP1 | ir3.VOP1_SDST | ir3.VOP2 | ir4.VOP1 | ir4.VOP1_SDST | ir4.VOP2 | irc.VOP1 | irc.VOP2, ctx: _Ctx) -> UOp:
|
||||
op_name = _op_name(inst)
|
||||
if op_name in ('V_READFIRSTLANE_B32_E32', 'V_PERMLANE64_B32_E32'): return ctx.compile_lane_pcode(inst.op, inst)
|
||||
# v_accvgpr_mov_b32: ACCVGPR[vdst] = ACCVGPR[src0] (VOP1 encoding, no pcode)
|
||||
if 'ACCVGPR_MOV' in op_name:
|
||||
lane, exec_mask = ctx.range(), ctx.rexec()
|
||||
vdst_reg = ctx.inst_field(type(inst).vdst) # VGPRField: raw ACCVGPR index (0-255)
|
||||
acc_src0_off = ctx.inst_field(type(inst).src0) # SrcField: raw 256 + ACCVGPR index
|
||||
val = ctx.raccvgpr_dyn(acc_src0_off - _c(256), lane)
|
||||
src0_off = ctx.inst_field(type(inst).src0) # SrcField: raw 256 + ACCVGPR index
|
||||
val = ctx.raccvgpr_dyn(src0_off - _c(256), lane)
|
||||
return UOp.sink(ctx.waccvgpr_dyn(vdst_reg, lane, val, exec_mask).end(lane), *ctx.inc_pc())
|
||||
lane, exec_mask, bits = ctx.range(), ctx.rexec(), inst.canonical_op_bits
|
||||
literal = ctx.inst_field(type(inst).literal) if hasattr(type(inst), 'literal') else None # type: ignore[union-attr]
|
||||
is_f64 = 'F64' in op_name and 'B64' not in op_name
|
||||
is_float = any(x in op_name for x in ('F16', 'F32', 'F64'))
|
||||
is_dpp16 = hasattr(type(inst), 'dpp') and hasattr(type(inst), 'vsrc0')
|
||||
vdst_reg = ctx.inst_field(type(inst).vdst)
|
||||
write_hi_half = bits['d'] == 16 and (vdst_reg >= _c(128))
|
||||
if isinstance(write_hi_half, UOp): vdst_reg = write_hi_half.where(vdst_reg - _c(128), vdst_reg)
|
||||
elif write_hi_half: vdst_reg -= 128
|
||||
src0_off: UOp | None = None
|
||||
if isinstance(inst, (ir3.VOP1, ir4.VOP1, irc.VOP1)):
|
||||
# Handle VOP1 hi-half source operand (src0 >= v[128] for 16-bit ops)
|
||||
d0 = _cond_hi16(write_hi_half, ctx.rvgpr_dyn(vdst_reg, lane))
|
||||
if is_dpp16:
|
||||
s0 = _load_dpp16_src0(ctx, inst, lane, d0)
|
||||
else:
|
||||
src0_off = ctx.inst_field(type(inst).src0)
|
||||
s0 = ctx.rsrc_dyn(src0_off, lane, bits['s0'], literal, is_f64)
|
||||
if bits['s0'] == 16 and not is_dpp16:
|
||||
src0_off = ctx.inst_field(type(inst).src0)
|
||||
s0 = ctx.rsrc_dyn(src0_off, lane, bits['s0'], literal, is_f64)
|
||||
if bits['s0'] == 16:
|
||||
src0_hi = src0_off >= _c(384)
|
||||
# Only compute hi-half when src0_off >= 384, use guarded index to prevent OOB access
|
||||
src0_reg = src0_hi.where(src0_off - _c(384), _c(0))
|
||||
s0 = src0_hi.where(_hi16(ctx.rvgpr_dyn(src0_reg, lane)), s0)
|
||||
if is_dpp16 and is_float:
|
||||
s0 = _apply_src_mods(s0, 0, 1 if getattr(inst, 'src0_abs', 0) else 0, 1 if getattr(inst, 'src0_neg', 0) else 0, bits['s0'])
|
||||
d0 = _cond_hi16(write_hi_half, ctx.rvgpr_dyn(vdst_reg, lane))
|
||||
srcs:dict[str, UOp | int] = {'S0': s0, 'D0': d0}
|
||||
else:
|
||||
vsrc1_reg = ctx.inst_field(type(inst).vsrc1)
|
||||
@@ -1099,19 +1038,13 @@ def _compile_vop12(inst: ir3.VOP1 | ir3.VOP1_SDST | ir3.VOP1_DPP16 | ir3.VOP2 |
|
||||
s1 = _cond_hi16(vsrc1_hi, ctx.rvgpr_dyn(vsrc1_actual, lane))
|
||||
d0 = _cond_hi16(write_hi_half, ctx.rvgpr_dyn(vdst_reg, lane)) # FMAC/FMAMK hi-half dest needs hi-half accumulator
|
||||
# Handle VOP2 hi-half src0 operand (src0 >= v[128] for 16-bit ops)
|
||||
if is_dpp16:
|
||||
s0 = _load_dpp16_src0(ctx, inst, lane, d0)
|
||||
else:
|
||||
src0_off = ctx.inst_field(type(inst).src0)
|
||||
s0 = ctx.rsrc_dyn(src0_off, lane, bits['s0'], literal, is_f64)
|
||||
if bits['s0'] == 16 and not is_dpp16:
|
||||
src0_off = ctx.inst_field(type(inst).src0)
|
||||
s0 = ctx.rsrc_dyn(src0_off, lane, bits['s0'], literal, is_f64)
|
||||
if bits['s0'] == 16:
|
||||
src0_hi = src0_off >= _c(384)
|
||||
# Only compute hi-half when src0_off >= 384, use guarded index to prevent OOB access
|
||||
src0_reg = src0_hi.where(src0_off - _c(384), _c(0))
|
||||
s0 = src0_hi.where(_hi16(ctx.rvgpr_dyn(src0_reg, lane)), s0)
|
||||
if is_dpp16 and is_float:
|
||||
s0 = _apply_src_mods(s0, 0, 1 if getattr(inst, 'src0_abs', 0) else 0, 1 if getattr(inst, 'src0_neg', 0) else 0, bits['s0'])
|
||||
s1 = _apply_src_mods(s1, 0, 1 if getattr(inst, 'src1_abs', 0) else 0, 1 if getattr(inst, 'src1_neg', 0) else 0, bits['s1'])
|
||||
srcs = {'S0': s0, 'S1': s1, 'D0': d0}
|
||||
# FMAAK_(DTYPE)_E32 series
|
||||
if 'V_FMAA' in _op_name(inst) or 'V_FMAM' in _op_name(inst):
|
||||
@@ -1119,11 +1052,10 @@ def _compile_vop12(inst: ir3.VOP1 | ir3.VOP1_SDST | ir3.VOP1_DPP16 | ir3.VOP2 |
|
||||
srcs['SIMM32'] = literal
|
||||
return ctx.compile_vop_pcode(inst.op, srcs, lane, vdst_reg, exec_mask, opsel_dst_hi=write_hi_half, src0_off=src0_off)
|
||||
|
||||
def _compile_vopc(inst: ir3.VOPC|ir3.VOPC_DPP16|ir3.VOP3|ir4.VOPC|ir4.VOPC_DPP16|ir4.VOP3|irc.VOPC|irc.VOP3, ctx: _Ctx,
|
||||
def _compile_vopc(inst: ir3.VOPC|ir3.VOP3|ir4.VOPC|ir4.VOP3|irc.VOPC|irc.VOP3, ctx: _Ctx,
|
||||
opsel: int = 0, abs_bits: int = 0, neg_bits: int = 0) -> UOp:
|
||||
exec_mask, op_name, bits = ctx.rexec(), _op_name(inst), inst.canonical_op_bits
|
||||
is_cmpx, is_vopc = 'CMPX' in op_name, hasattr(inst, 'vsrc1') # is_vopc: e32 vs e64
|
||||
is_dpp16 = hasattr(type(inst), 'dpp') and hasattr(type(inst), 'vsrc0')
|
||||
|
||||
# Handle both VOPC (vsrc1) and VOP3 (src1) instruction formats - read operands dynamically
|
||||
if is_vopc:
|
||||
@@ -1146,14 +1078,11 @@ def _compile_vopc(inst: ir3.VOPC|ir3.VOPC_DPP16|ir3.VOP3|ir4.VOPC|ir4.VOPC_DPP16
|
||||
is_float, is_f64, pcode = any(x in op_name for x in ('_F32', '_F64', '_F16')), '_F64' in op_name, get_pcode(inst.op)
|
||||
def get_cmp_bit(lane) -> UOp:
|
||||
lc = lane.cast(dtypes.int) if isinstance(lane, UOp) else _c(lane, dtypes.int)
|
||||
s0 = _load_dpp16_src0(ctx, inst, lc, _c(0)) if is_dpp16 else ctx.rsrc_dyn(src0_off, lc, bits['s0'], literal, is_f64)
|
||||
s0 = ctx.rsrc_dyn(src0_off, lc, bits['s0'], literal, is_f64)
|
||||
s1 = _cond_hi16(vsrc1_hi, ctx.rsrc_dyn(src1_off, lc, bits['s1'], literal, is_f64)) if bits['s0'] == 16 \
|
||||
else ctx.rsrc_dyn(src1_off, lc, bits['s1'], literal, is_f64)
|
||||
if bits['s0'] == 16 and opsel: s0, s1 = _apply_opsel(s0, 0, opsel), _apply_opsel(s1, 1, opsel)
|
||||
if is_float:
|
||||
if is_dpp16:
|
||||
s0 = _apply_src_mods(s0, 0, 1 if getattr(inst, 'src0_abs', 0) else 0, 1 if getattr(inst, 'src0_neg', 0) else 0, bits['s0'])
|
||||
s1 = _apply_src_mods(s1, 0, 1 if getattr(inst, 'src1_abs', 0) else 0, 1 if getattr(inst, 'src1_neg', 0) else 0, bits['s1'])
|
||||
s0 = _apply_src_mods(s0, 0, abs_bits, neg_bits, bits['s0'])
|
||||
s1 = _apply_src_mods(s1, 1, abs_bits, neg_bits, bits['s1'])
|
||||
for dest, val in parse_pcode(pcode, {'S0': s0, 'S1': s1, 'laneId': lc, 'D0': UOp.const(dtypes.uint64, 0)})[1]:
|
||||
@@ -1248,19 +1177,6 @@ def _compile_vop3(inst: ir3.VOP3 | ir4.VOP3 | irc.VOP3, ctx: _Ctx) -> UOp:
|
||||
opsel_dst_hi = bool(opsel & 0b1000) and bits['d'] == 16
|
||||
return ctx.compile_vop_pcode(inst.op, srcs, lane, vdst_reg, exec_mask, opsel_dst_hi=opsel_dst_hi, clmp=getattr(inst, 'clmp', 0))
|
||||
|
||||
def _compile_vinterp(inst: ir3.VINTERP | ir4.VINTERP, ctx: _Ctx) -> UOp:
|
||||
lane, exec_mask = ctx.range(), ctx.rexec()
|
||||
inst_type = type(inst)
|
||||
vdst_reg = ctx.inst_field(inst_type.vdst)
|
||||
src0_off, src1_off, src2_off = ctx.inst_field(inst_type.src0), ctx.inst_field(inst_type.src1), ctx.inst_field(inst_type.src2)
|
||||
src0_reg = (src0_off >= _c(256)).where(src0_off - _c(256), src0_off)
|
||||
src2_reg = (src2_off >= _c(256)).where(src2_off - _c(256), src2_off)
|
||||
srcs = {
|
||||
'SRC0': src0_reg, 'SRC2': src2_reg,
|
||||
'S0': ctx.rsrc_dyn(src0_off, lane), 'S1': ctx.rsrc_dyn(src1_off, lane), 'S2': ctx.rsrc_dyn(src2_off, lane),
|
||||
}
|
||||
return ctx.compile_vop_pcode(inst.op, srcs, lane, vdst_reg, exec_mask)
|
||||
|
||||
def _compile_vop3sd(inst: ir3.VOP3SD | ir4.VOP3SD | irc.VOP3SD, ctx: _Ctx) -> UOp:
|
||||
exec_mask = ctx.rexec()
|
||||
bits, pcode, ops = inst.canonical_op_bits, get_pcode(inst.op), inst.canonical_operands
|
||||
@@ -1872,7 +1788,7 @@ def _compile_mem_op(inst: ir3.DS|ir3.FLAT|ir3.GLOBAL|ir3.SCRATCH|ir4.DS|ir4.VFLA
|
||||
'DATA2': _u64(ctx.rvgpr_dyn(data1_reg, lane), ctx.rvgpr_dyn(data1_reg + _c(1), lane)) if has_data1 else UOp.const(dtypes.uint64, 0)}
|
||||
# RDNA3 uses ADDR/OFFSET, RDNA4 uses vgpr_a/offset (lowercase) + CalcDsAddr function
|
||||
return {'ADDR': addr, 'ADDR_BASE': addr, 'OFFSET': offset, 'OFFSET0': offset0, 'OFFSET1': offset1, '_lds': mem, 'laneId': lane,
|
||||
'vgpr_a': ctx.rvgpr_dyn(addr_reg, lane), 'offset': offset, 'offset0': offset0, 'offset1': offset1, **data}
|
||||
'vgpr_a': ctx.rvgpr_dyn(addr_reg, lane), 'offset': offset, **data}
|
||||
active = _lane_active(exec_mask, lane)
|
||||
# saddr < 124 means valid SGPR pair, otherwise use 0 (NULL means no saddr contribution)
|
||||
use_saddr = (saddr_reg < _c(124)) if saddr_reg is not None else UOp.const(dtypes.bool, False)
|
||||
@@ -2021,20 +1937,17 @@ def _compile_mubuf(inst: irc.MUBUF, ctx: _Ctx) -> UOp:
|
||||
# Dispatch table: instruction type -> handler function
|
||||
_INST_HANDLERS: dict[type, Callable[..., UOp]] = {
|
||||
ir3.SOPP: _compile_sopp, ir3.SMEM: _compile_smem, ir3.SOP1: _compile_sop, ir3.SOP2: _compile_sop, ir3.SOPC: _compile_sop, ir3.SOPK: _compile_sop,
|
||||
ir3.VOP1: _compile_vop12, ir3.VOP1_SDST: _compile_vop12, ir3.VOP1_DPP16: _compile_vop12, ir3.VOP2: _compile_vop12, ir3.VOP2_DPP16: _compile_vop12,
|
||||
ir3.VOPC: _compile_vopc, ir3.VOPC_DPP16: _compile_vopc, ir3.VOP3: _compile_vop3, ir3.VINTERP: _compile_vinterp,
|
||||
ir3.VOP1: _compile_vop12, ir3.VOP1_SDST: _compile_vop12, ir3.VOP2: _compile_vop12, ir3.VOPC: _compile_vopc, ir3.VOP3: _compile_vop3,
|
||||
ir3.VOP3_SDST: _compile_vop3, ir3.VOP3SD: _compile_vop3sd, ir3.VOP3P: _compile_vop3p, ir3.VOPD: _compile_vopd,
|
||||
ir3.DS: _compile_mem_op, ir3.FLAT: _compile_mem_op, ir3.GLOBAL: _compile_mem_op, ir3.SCRATCH: _compile_mem_op,
|
||||
# RDNA4 instruction classes
|
||||
ir4.SOPP: _compile_sopp, ir4.SMEM: _compile_smem, ir4.SOP1: _compile_sop, ir4.SOP2: _compile_sop, ir4.SOPC: _compile_sop, ir4.SOPK: _compile_sop,
|
||||
ir4.VOP1: _compile_vop12, ir4.VOP1_SDST: _compile_vop12, ir4.VOP1_DPP16: _compile_vop12, ir4.VOP2: _compile_vop12, ir4.VOP2_DPP16: _compile_vop12,
|
||||
ir4.VOPC: _compile_vopc, ir4.VOPC_DPP16: _compile_vopc, ir4.VOP3: _compile_vop3, ir4.VINTERP: _compile_vinterp,
|
||||
ir4.VOP1: _compile_vop12, ir4.VOP1_SDST: _compile_vop12, ir4.VOP2: _compile_vop12, ir4.VOPC: _compile_vopc, ir4.VOP3: _compile_vop3,
|
||||
ir4.VOP3_SDST: _compile_vop3, ir4.VOP3SD: _compile_vop3sd, ir4.VOP3P: _compile_vop3p, ir4.VOPD: _compile_vopd,
|
||||
ir4.DS: _compile_mem_op, ir4.VFLAT: _compile_mem_op, ir4.VGLOBAL: _compile_mem_op, ir4.VSCRATCH: _compile_mem_op,
|
||||
# CDNA instruction classes
|
||||
irc.SOPP: _compile_sopp, irc.SMEM: _compile_smem, irc.SOP1: _compile_sop, irc.SOP2: _compile_sop, irc.SOPC: _compile_sop, irc.SOPK: _compile_sop,
|
||||
irc.VOP1: _compile_vop12, irc.VOP1_DPP16: _compile_vop12, irc.VOP2: _compile_vop12, irc.VOP2_DPP16: _compile_vop12,
|
||||
irc.VOPC: _compile_vopc, irc.VOP3: _compile_vop3,
|
||||
irc.VOP1: _compile_vop12, irc.VOP2: _compile_vop12, irc.VOPC: _compile_vopc, irc.VOP3: _compile_vop3,
|
||||
irc.VOP3_SDST: _compile_vop3, irc.VOP3SD: _compile_vop3sd, irc.VOP3P: _compile_vop3p,
|
||||
irc.VOP1_SDWA: _compile_sdwa, irc.VOP2_SDWA: _compile_sdwa, irc.VOP2_SDWA_SDST: _compile_sdwa, irc.VOPC_SDWA_SDST: _compile_sdwa,
|
||||
irc.DS: _compile_mem_op, irc.FLAT: _compile_mem_op, irc.GLOBAL: _compile_mem_op, irc.SCRATCH: _compile_mem_op,
|
||||
|
||||
+19
-40
@@ -4,7 +4,7 @@ from tinygrad.dtype import dtypes
|
||||
from tinygrad.uop.ops import Ops, UOp
|
||||
from tinygrad.uop.decompositions import f2f
|
||||
|
||||
# Type alias for vars dict: stores UOps and tuples for lambda definitions
|
||||
# Type alias for vars dict: stores UOps for variables and tuples for lambda definitions
|
||||
VarVal = UOp | tuple[str, list[str], str]
|
||||
|
||||
def _const(dt, v): return UOp.const(dt, v)
|
||||
@@ -50,22 +50,6 @@ def _extract_bits(val: UOp, hi: int, lo: int) -> UOp:
|
||||
if result.dtype != target_dt: result = result.cast(target_dt)
|
||||
return result
|
||||
|
||||
def _expr_bits(v: UOp) -> int:
|
||||
if v.dtype == dtypes.bool: return 1
|
||||
if v.op in (Ops.AND, Ops.XOR):
|
||||
widths: list[int] = []
|
||||
for src in v.src:
|
||||
if src.op == Ops.CONST and isinstance(src.arg, int) and src.arg > 0 and (src.arg & (src.arg + 1)) == 0:
|
||||
widths.append(src.arg.bit_length())
|
||||
if widths: return max(widths)
|
||||
return v.dtype.bitsize
|
||||
|
||||
def _countbits(v: UOp) -> UOp:
|
||||
dt = dtypes.uint64 if _expr_bits(v) > 32 or v.dtype in (dtypes.uint64, dtypes.int64) else dtypes.uint32
|
||||
vv, out = v.cast(dt), _u32(0)
|
||||
for i in range(_expr_bits(v)): out = out + ((vv >> _const(dt, i)) & _const(dt, 1)).cast(dtypes.uint32)
|
||||
return out
|
||||
|
||||
def _set_bit(old, pos, val):
|
||||
mask = _u32(1) << pos
|
||||
return (old & (mask ^ _u32(0xFFFFFFFF))) | ((val.cast(dtypes.uint32) & _u32(1)) << pos)
|
||||
@@ -351,7 +335,6 @@ _FUNCS: dict[str, Callable[..., UOp]] = {
|
||||
# System NOPs - these are scheduling hints, no effect on emulation
|
||||
'MIN': lambda a, b: (a < b).where(a, b),
|
||||
's_nop': lambda a: _u32(0),
|
||||
'countbits': _countbits,
|
||||
# Address calculation for memory operations
|
||||
'CalcDsAddr': lambda a, o, *r: a.cast(dtypes.uint32) + o.cast(dtypes.uint32),
|
||||
'CalcGlobalAddr': lambda v, s, *r: v.cast(dtypes.uint64) + s.cast(dtypes.uint64),
|
||||
@@ -406,7 +389,7 @@ def tokenize(s: str) -> list[Token]:
|
||||
if c.isspace():
|
||||
i += 1
|
||||
continue
|
||||
if i + 1 < n and s[i:i+2] in ('+=', '-=', '|=', '&=', '^='):
|
||||
if i + 1 < n and s[i:i+2] in ('+=', '-='):
|
||||
tokens.append(Token('ASSIGN_OP', s[i:i+2]))
|
||||
i += 2
|
||||
continue
|
||||
@@ -520,7 +503,7 @@ class Parser:
|
||||
def unary(self) -> UOp:
|
||||
if self.try_eat_val('~', 'OP'):
|
||||
inner = self.unary()
|
||||
return inner ^ _const(inner.dtype, (1 << _expr_bits(inner)) - 1)
|
||||
return inner ^ _const(inner.dtype, (1 << (inner.dtype.itemsize * 8)) - 1)
|
||||
if self.try_eat_val('!', 'OP'):
|
||||
inner = self.unary()
|
||||
return inner.eq(_const(inner.dtype, 0))
|
||||
@@ -556,10 +539,7 @@ class Parser:
|
||||
self.eat('COMMA')
|
||||
lo = self.parse()
|
||||
self.eat('RBRACE')
|
||||
lo_bits, hi_bits = _expr_bits(lo), _expr_bits(hi)
|
||||
total_bits = lo_bits + hi_bits
|
||||
dt = _BITS_DT.get(total_bits, dtypes.uint32 if total_bits <= 32 else dtypes.uint64)
|
||||
return (hi.cast(dt) << _const(dt, lo_bits)) | lo.cast(dt)
|
||||
return (hi.cast(dt:=_BITS_DT.get((s:=lo.dtype.bitsize) * 2, dtypes.uint64)) << _const(dt, s)) | lo.cast(dt)
|
||||
if self.at('NUM'):
|
||||
num = self.eat('NUM').val
|
||||
if self.try_eat('QUOTE'):
|
||||
@@ -596,8 +576,8 @@ class Parser:
|
||||
if name == 'OVERFLOW_F32': return _const(dtypes.uint32, 0x7F7FFFFF).bitcast(dtypes.float32)
|
||||
if name == 'UNDERFLOW_F64': return _const(dtypes.uint64, 1).bitcast(dtypes.float64)
|
||||
if name == 'OVERFLOW_F64': return _const(dtypes.uint64, 0x7FEFFFFFFFFFFFFF).bitcast(dtypes.float64)
|
||||
if name.lower() == 'wave32': return _const(dtypes.bool, self.vars.get('_wave_size', 32) <= 32)
|
||||
if name.lower() == 'wave64': return _const(dtypes.bool, self.vars.get('_wave_size', 32) > 32)
|
||||
if name == 'WAVE32': return _const(dtypes.bool, self.vars.get('_wave_size', 32) <= 32)
|
||||
if name == 'WAVE64': return _const(dtypes.bool, self.vars.get('_wave_size', 32) > 32)
|
||||
if name == 'WAVE_MODE' and self.try_eat('DOT') and self.try_eat_val('IEEE', 'IDENT'): return _u32(1)
|
||||
if self.try_eat('LBRACE'):
|
||||
idx = self.eat('NUM').val
|
||||
@@ -705,7 +685,7 @@ class Parser:
|
||||
dt = dtypes.uint64 if base.dtype in (dtypes.uint64, dtypes.int64) else dtypes.uint32
|
||||
base_cast = base.cast(dt) if base.dtype != dt else base
|
||||
result = ((base_cast >> _const(dt, idx)) & _const(dt, 1))
|
||||
return _cast_to(result, dt_suffix) if dt_suffix else result.cast(dtypes.bool)
|
||||
return _cast_to(result, dt_suffix) if dt_suffix else result
|
||||
if var_name:
|
||||
idx_u32 = _to_u32(first)
|
||||
elems = [(i, self.vars[f'{var_name}@{i}']) for i in range(256) if f'{var_name}@{i}' in self.vars]
|
||||
@@ -719,7 +699,7 @@ class Parser:
|
||||
dt = dtypes.uint64 if base.dtype in (dtypes.uint64, dtypes.int64) else dtypes.uint32
|
||||
base_cast = base.cast(dt) if base.dtype != dt else base
|
||||
result = (base_cast >> first.cast(dt)) & _const(dt, 1)
|
||||
return _cast_to(result, dt_suffix) if dt_suffix else result.cast(dtypes.bool)
|
||||
return _cast_to(result, dt_suffix) if dt_suffix else result
|
||||
|
||||
def _handle_brace_index(self, base) -> UOp:
|
||||
self.eat('LBRACE')
|
||||
@@ -865,7 +845,7 @@ class Parser:
|
||||
hi = mem.index(safe_idx_hi, *gate)
|
||||
combined = val.cast(dtypes.uint64) | (hi.cast(dtypes.uint64) << UOp.const(dtypes.uint64, 32))
|
||||
val = is_unaligned.where((combined >> (byte_off.cast(dtypes.uint64) * UOp.const(dtypes.uint64, 8))).cast(dtypes.uint32), val)
|
||||
return _cast_to(val, dt)
|
||||
return val
|
||||
|
||||
def _coerce_cmp(self, l: UOp, r: UOp) -> tuple[UOp, UOp]:
|
||||
if l.dtype != r.dtype:
|
||||
@@ -1064,12 +1044,14 @@ def parse_block(lines: list[str], start: int, env: dict[str, VarVal], funcs: dic
|
||||
elif j < len(toks) and toks[j].type == 'EQUALS': j += 1
|
||||
rhs = parse_tokens(toks[j:], env, funcs)
|
||||
if compound_op:
|
||||
old = Parser([Token('EOF', '')], env, funcs)._handle_mem_load(addr, dt)
|
||||
if compound_op == '+=': rhs = old + rhs
|
||||
elif compound_op == '-=': rhs = old - rhs
|
||||
elif compound_op == '|=': rhs = old | rhs
|
||||
elif compound_op == '&=': rhs = old & rhs
|
||||
elif compound_op == '^=': rhs = old ^ rhs
|
||||
mem = env.get('_vmem') if '_vmem' in env else env.get('_lds')
|
||||
if isinstance(mem, UOp):
|
||||
adt = dtypes.uint64 if addr.dtype == dtypes.uint64 else dtypes.uint32
|
||||
idx = (addr >> _const(adt, 2)).cast(dtypes.int)
|
||||
old = mem.index(idx)
|
||||
if dt in (dtypes.uint64, dtypes.int64, dtypes.float64):
|
||||
old = old.cast(dtypes.uint64) | (mem.index(((addr + _const(adt, 4)) >> _const(adt, 2)).cast(dtypes.int)).cast(dtypes.uint64) << _u64(32))
|
||||
rhs = (old + rhs) if compound_op == '+=' else (old - rhs)
|
||||
if assigns is not None: assigns.append((f'MEM[{_tok_str(addr_toks)}].{dt_name}', (addr, rhs)))
|
||||
i += 1
|
||||
continue
|
||||
@@ -1206,11 +1188,7 @@ def parse_block(lines: list[str], start: int, env: dict[str, VarVal], funcs: dic
|
||||
old = block_assigns.get(var, env.get(var, _u32(0)))
|
||||
rhs = parse_tokens(toks[assign_op+1:], env, funcs)
|
||||
if rhs.dtype != old.dtype: rhs = rhs.cast(old.dtype)
|
||||
if toks[assign_op].val == '+=': block_assigns[var] = env[var] = old + rhs
|
||||
elif toks[assign_op].val == '-=': block_assigns[var] = env[var] = old - rhs
|
||||
elif toks[assign_op].val == '|=': block_assigns[var] = env[var] = old | rhs
|
||||
elif toks[assign_op].val == '&=': block_assigns[var] = env[var] = old & rhs
|
||||
elif toks[assign_op].val == '^=': block_assigns[var] = env[var] = old ^ rhs
|
||||
block_assigns[var] = env[var] = (old + rhs) if toks[assign_op].val == '+=' else (old - rhs)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
@@ -1357,3 +1335,4 @@ def parse_block(lines: list[str], start: int, env: dict[str, VarVal], funcs: dic
|
||||
|
||||
def parse_expr(expr: str, env: dict[str, VarVal], funcs: dict | None = None) -> UOp:
|
||||
return parse_tokens(tokenize(expr.strip().rstrip(';')), env, funcs)
|
||||
|
||||
|
||||
+19
-1
@@ -1,4 +1,5 @@
|
||||
import ctypes, ctypes.util
|
||||
from tinygrad.helpers import getenv
|
||||
|
||||
def _try_dlopen_gpuocelot():
|
||||
GPUOCELOT_PATHS = [ctypes.util.find_library("gpuocelot")] if ctypes.util.find_library("gpuocelot") is not None else []
|
||||
@@ -15,7 +16,7 @@ def _try_dlopen_gpuocelot():
|
||||
return None
|
||||
|
||||
class PythonRemu:
|
||||
"""Python RDNA3/RDNA4 emulator wrapper used by mockgpu."""
|
||||
"""Python RDNA3/RDNA4 emulator wrapper that matches the libremu.so interface."""
|
||||
valid_mem_ranges: set[tuple[int, int]] = set()
|
||||
rsrc2: int = 0x19c # Default: USER_SGPR_COUNT=14, enable X and Y workgroup IDs
|
||||
scratch_size: int = 0 # private_segment_fixed_size from kernel descriptor
|
||||
@@ -25,3 +26,20 @@ class PythonRemu:
|
||||
def run_asm(self, lib: int, lib_sz: int, gx: int, gy: int, gz: int, lx: int, ly: int, lz: int, args_ptr: int) -> int:
|
||||
from test.mockgpu.amd.emu import run_asm
|
||||
return run_asm(lib, lib_sz, gx, gy, gz, lx, ly, lz, args_ptr, self.rsrc2, self.scratch_size, self.arch, self.user_data)
|
||||
|
||||
def _try_dlopen_remu():
|
||||
# Use Python emulator only if PYTHON_REMU=1
|
||||
if int(getenv("PYTHON_REMU", "1")):
|
||||
return PythonRemu()
|
||||
REMU_PATHS = ["extra/remu/target/release/libremu.so", "libremu.so", "/usr/local/lib/libremu.so",
|
||||
"extra/remu/target/release/libremu.dylib", "libremu.dylib", "/usr/local/lib/libremu.dylib", "/opt/homebrew/lib/libremu.dylib"]
|
||||
for path in REMU_PATHS:
|
||||
try:
|
||||
remu = ctypes.CDLL(path)
|
||||
remu.run_asm.restype = ctypes.c_int32
|
||||
remu.run_asm.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_uint32,
|
||||
ctypes.c_uint32, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_void_p]
|
||||
except OSError: pass
|
||||
else: return remu
|
||||
print("Could not find libremu.so")
|
||||
return None
|
||||
|
||||
+89
-78
@@ -1,6 +1,7 @@
|
||||
import ctypes, struct, subprocess, tempfile, unittest
|
||||
from typing import Annotated
|
||||
from tinygrad.helpers import OSX, WIN
|
||||
from tinygrad.runtime.support.c import DLL, record, Field
|
||||
from tinygrad.runtime.support.c import DLL, record, init_records
|
||||
from tinygrad.runtime.support import c
|
||||
from tinygrad.runtime.support.autogen import gen
|
||||
|
||||
@@ -13,9 +14,10 @@ class TestC(unittest.TestCase):
|
||||
|
||||
def test_struct_array_init(self):
|
||||
@record
|
||||
class Foo(c.Struct):
|
||||
class Foo:
|
||||
SIZE = 12
|
||||
a = Field(ctypes.c_int * 3, 0)
|
||||
a: Annotated[ctypes.c_int * 3, 0]
|
||||
init_records()
|
||||
|
||||
f = Foo((1,2,3))
|
||||
assert f.a[0] == 1
|
||||
@@ -28,10 +30,11 @@ class TestC(unittest.TestCase):
|
||||
|
||||
def test_field_ranges(self):
|
||||
@record
|
||||
class Foo(c.Struct):
|
||||
class Foo:
|
||||
SIZE = 2
|
||||
s = Field(ctypes.c_int8, 0)
|
||||
u = Field(ctypes.c_uint8, 1)
|
||||
s: Annotated[ctypes.c_int8, 0]
|
||||
u: Annotated[ctypes.c_uint8, 1]
|
||||
init_records()
|
||||
|
||||
f = Foo()
|
||||
f.s = -1
|
||||
@@ -42,9 +45,10 @@ class TestC(unittest.TestCase):
|
||||
# this syntax is inherited from ctypes, but it seems a bit nonsensical?
|
||||
def test_voidp_none(self):
|
||||
@record
|
||||
class Foo(c.Struct):
|
||||
class Foo:
|
||||
SIZE = 8
|
||||
p = Field(ctypes.c_void_p, 0)
|
||||
p: Annotated[ctypes.c_void_p, 0]
|
||||
init_records()
|
||||
|
||||
f = Foo(None)
|
||||
assert f.p is None
|
||||
@@ -55,12 +59,13 @@ class TestC(unittest.TestCase):
|
||||
|
||||
def test_packed_struct(self):
|
||||
@record
|
||||
class Baz(c.Struct):
|
||||
class Baz:
|
||||
SIZE = 8
|
||||
a = Field(ctypes.c_uint, 0, 30)
|
||||
b = Field(ctypes.c_uint, 3, 30, 6)
|
||||
c = Field(ctypes.c_uint, 7, 2, 4)
|
||||
d = Field(ctypes.c_uint, 7, 2, 6)
|
||||
a: Annotated[ctypes.c_uint, 0, 30]
|
||||
b: Annotated[ctypes.c_uint, 3, 30, 6]
|
||||
c: Annotated[ctypes.c_uint, 7, 2, 4]
|
||||
d: Annotated[ctypes.c_uint, 7, 2, 6]
|
||||
init_records()
|
||||
|
||||
b = Baz(0x3AAADEAD, 0xBEEF, 1, 0)
|
||||
assert b.a == 0x3AAADEAD
|
||||
@@ -76,12 +81,13 @@ class TestC(unittest.TestCase):
|
||||
|
||||
def test_packed_struct_interop(self):
|
||||
@record
|
||||
class Baz(c.Struct):
|
||||
class Baz:
|
||||
SIZE = 8
|
||||
a = Field(ctypes.c_int, 0, 30)
|
||||
b = Field(ctypes.c_int, 3, 30, 6)
|
||||
c = Field(ctypes.c_int, 7, 2, 4)
|
||||
d = Field(ctypes.c_int, 7, 2, 6)
|
||||
a: Annotated[ctypes.c_int, 0, 30]
|
||||
b: Annotated[ctypes.c_int, 3, 30, 6]
|
||||
c: Annotated[ctypes.c_int, 7, 2, 4]
|
||||
d: Annotated[ctypes.c_int, 7, 2, 6]
|
||||
init_records()
|
||||
|
||||
src = '''
|
||||
struct __attribute__((packed)) baz {
|
||||
@@ -97,23 +103,24 @@ class TestC(unittest.TestCase):
|
||||
'''
|
||||
dll = self.compile(src)
|
||||
b = Baz(0xAA000, 0x00BB0, 0, 1)
|
||||
@dll.bind(ctypes.c_int, Baz)
|
||||
@dll.bind
|
||||
def test(x:Baz) -> ctypes.c_int: ...
|
||||
self.assertEqual(test(b), b.a + b.b + b.c + b.d)
|
||||
|
||||
# https://github.com/python/cpython/issues/90914
|
||||
def test_bitfield_interop(self):
|
||||
@record
|
||||
class Baz(c.Struct):
|
||||
class Baz:
|
||||
SIZE = 1
|
||||
a = Field(ctypes.c_bool, 0, 1, 0)
|
||||
b = Field(ctypes.c_bool, 0, 1, 1)
|
||||
c = Field(ctypes.c_bool, 0, 1, 2)
|
||||
d = Field(ctypes.c_bool, 0, 1, 3)
|
||||
e = Field(ctypes.c_bool, 0, 1, 4)
|
||||
f = Field(ctypes.c_bool, 0, 1, 5)
|
||||
g = Field(ctypes.c_bool, 0, 1, 6)
|
||||
h = Field(ctypes.c_bool, 0, 1, 7)
|
||||
a: Annotated[ctypes.c_bool, 0, 1, 0]
|
||||
b: Annotated[ctypes.c_bool, 0, 1, 1]
|
||||
c: Annotated[ctypes.c_bool, 0, 1, 2]
|
||||
d: Annotated[ctypes.c_bool, 0, 1, 3]
|
||||
e: Annotated[ctypes.c_bool, 0, 1, 4]
|
||||
f: Annotated[ctypes.c_bool, 0, 1, 5]
|
||||
g: Annotated[ctypes.c_bool, 0, 1, 6]
|
||||
h: Annotated[ctypes.c_bool, 0, 1, 7]
|
||||
init_records()
|
||||
src = '''#include <stdbool.h>
|
||||
struct baz {
|
||||
bool a:1, b:1, c:1, d:1, e:1, f:1, g:1, h:1;
|
||||
@@ -124,22 +131,23 @@ class TestC(unittest.TestCase):
|
||||
}
|
||||
'''
|
||||
dll = self.compile(src)
|
||||
@dll.bind(ctypes.c_int, Baz)
|
||||
@dll.bind
|
||||
def test(x:Baz) -> ctypes.c_int: ...
|
||||
for i in range(8): self.assertEqual(test(Baz(*(j==i for j in range(8)))), i==2)
|
||||
|
||||
def test_struct_interop(self):
|
||||
@record
|
||||
class Baz(c.Struct):
|
||||
class Baz:
|
||||
SIZE = 32
|
||||
a = Field(ctypes.c_int, 0)
|
||||
b = Field(ctypes.c_int, 4)
|
||||
c = Field(ctypes.c_int, 8)
|
||||
d = Field(ctypes.c_int, 12)
|
||||
e = Field(ctypes.c_int, 16)
|
||||
f = Field(ctypes.c_int, 20)
|
||||
g = Field(ctypes.c_int, 24)
|
||||
h = Field(ctypes.c_int, 28)
|
||||
a: Annotated[ctypes.c_int, 0]
|
||||
b: Annotated[ctypes.c_int, 4]
|
||||
c: Annotated[ctypes.c_int, 8]
|
||||
d: Annotated[ctypes.c_int, 12]
|
||||
e: Annotated[ctypes.c_int, 16]
|
||||
f: Annotated[ctypes.c_int, 20]
|
||||
g: Annotated[ctypes.c_int, 24]
|
||||
h: Annotated[ctypes.c_int, 28]
|
||||
init_records()
|
||||
src = '''#include <stdio.h>
|
||||
struct baz {
|
||||
int a, b, c, d, e, f, g, h;
|
||||
@@ -150,15 +158,16 @@ class TestC(unittest.TestCase):
|
||||
}
|
||||
'''
|
||||
dll = self.compile(src)
|
||||
@dll.bind(Baz, Baz)
|
||||
@dll.bind
|
||||
def test(x:Baz) -> Baz: ...
|
||||
self.assertEqual(bytes(test(Baz(*range(8)))), struct.pack("8i", *range(7, -1, -1)))
|
||||
|
||||
def test_aos_interop(self):
|
||||
@record
|
||||
class Item(c.Struct):
|
||||
class Item:
|
||||
SIZE = 4
|
||||
val = Field(ctypes.c_int, 0)
|
||||
val: Annotated[ctypes.c_int, 0]
|
||||
init_records()
|
||||
src = """
|
||||
struct item { int val; };
|
||||
int test(struct item arr[3]) {
|
||||
@@ -168,15 +177,16 @@ class TestC(unittest.TestCase):
|
||||
}
|
||||
"""
|
||||
dll = self.compile(src)
|
||||
@dll.bind(ctypes.c_int, Item * 3)
|
||||
@dll.bind
|
||||
def test(arr:(Item * 3)) -> ctypes.c_int: ...
|
||||
self.assertEqual(test((Item * 3)(Item(10), Item(20), Item(30))), 60)
|
||||
|
||||
def test_soa_interop(self):
|
||||
@record
|
||||
class Row(c.Struct):
|
||||
class Row:
|
||||
SIZE = 16
|
||||
data = Field(ctypes.c_int * 3, 0)
|
||||
data: Annotated[ctypes.c_int * 3, 0]
|
||||
init_records()
|
||||
src = """
|
||||
struct row { int data[3]; };
|
||||
struct row test(struct row x) {
|
||||
@@ -184,7 +194,7 @@ class TestC(unittest.TestCase):
|
||||
}
|
||||
"""
|
||||
dll = self.compile(src)
|
||||
@dll.bind(Row, Row)
|
||||
@dll.bind
|
||||
def test(x:Row) -> Row: ...
|
||||
r = test(Row((ctypes.c_int * 3)(10, 20, 30)))
|
||||
self.assertIsInstance(r, Row)
|
||||
@@ -194,9 +204,10 @@ class TestC(unittest.TestCase):
|
||||
|
||||
def test_soa_ptr_interop(self):
|
||||
@record
|
||||
class Row(c.Struct):
|
||||
class Row:
|
||||
SIZE = 8
|
||||
data = Field(c.POINTER[ctypes.c_int], 0)
|
||||
data: Annotated[c.POINTER[ctypes.c_int], 0]
|
||||
init_records()
|
||||
src = """
|
||||
struct row { int *data; };
|
||||
int test(struct row x) {
|
||||
@@ -204,20 +215,21 @@ class TestC(unittest.TestCase):
|
||||
}
|
||||
"""
|
||||
dll = self.compile(src)
|
||||
@dll.bind(ctypes.c_int, Row)
|
||||
@dll.bind
|
||||
def test(x:Row) -> ctypes.c_int: ...
|
||||
assert test(Row((ctypes.c_int * 3)(10, 20, 30))) == 60
|
||||
|
||||
def test_nested_struct_interop(self):
|
||||
@record
|
||||
class Inner(c.Struct):
|
||||
class Inner:
|
||||
SIZE = 4
|
||||
a = Field(ctypes.c_int, 0)
|
||||
a: Annotated[ctypes.c_int, 0]
|
||||
@record
|
||||
class Outer(c.Struct):
|
||||
class Outer:
|
||||
SIZE = 8
|
||||
inner = Field(Inner, 0)
|
||||
b = Field(ctypes.c_int, 4)
|
||||
inner: Annotated[Inner, 0]
|
||||
b: Annotated[ctypes.c_int, 4]
|
||||
init_records()
|
||||
src = """
|
||||
struct i { int a; };
|
||||
struct o { struct i i; int b; };
|
||||
@@ -226,7 +238,7 @@ class TestC(unittest.TestCase):
|
||||
}
|
||||
"""
|
||||
dll = self.compile(src)
|
||||
@dll.bind(Outer, Outer)
|
||||
@dll.bind
|
||||
def test(x:Outer) -> Outer: ...
|
||||
o = test(Outer(Inner(10), 20))
|
||||
self.assertEqual(o.inner.a, 20)
|
||||
@@ -234,10 +246,11 @@ class TestC(unittest.TestCase):
|
||||
|
||||
def test_struct_pointer_interop(self):
|
||||
@record
|
||||
class Foo(c.Struct):
|
||||
class Foo:
|
||||
SIZE = 8
|
||||
a = Field(ctypes.c_int, 0)
|
||||
b = Field(ctypes.c_int, 4)
|
||||
a: Annotated[ctypes.c_int, 0]
|
||||
b: Annotated[ctypes.c_int, 4]
|
||||
init_records()
|
||||
src = """
|
||||
struct foo { int a, b; };
|
||||
struct foo *test(struct foo *f) {
|
||||
@@ -248,7 +261,7 @@ class TestC(unittest.TestCase):
|
||||
}
|
||||
"""
|
||||
dll = self.compile(src)
|
||||
@dll.bind(ctypes.POINTER(Foo), ctypes.POINTER(Foo))
|
||||
@dll.bind
|
||||
def test(f:ctypes.POINTER(Foo)) -> ctypes.POINTER(Foo): ...
|
||||
inp = ctypes.pointer(Foo(10, 20))
|
||||
out = test(inp)
|
||||
@@ -260,15 +273,16 @@ class TestC(unittest.TestCase):
|
||||
# Mimics how mesa.struct_lp_build_tgsi_params.mask is used
|
||||
from tinygrad.runtime.support.c import POINTER
|
||||
@record
|
||||
class Inner(c.Struct):
|
||||
class Inner:
|
||||
SIZE = 8
|
||||
value = Field(ctypes.c_int, 0)
|
||||
flag = Field(ctypes.c_int, 4)
|
||||
value: Annotated[ctypes.c_int, 0]
|
||||
flag: Annotated[ctypes.c_int, 4]
|
||||
@record
|
||||
class Outer(c.Struct):
|
||||
class Outer:
|
||||
SIZE = 16
|
||||
x = Field(ctypes.c_int, 0)
|
||||
inner_ptr = Field(POINTER[Inner], 8)
|
||||
x: Annotated[ctypes.c_int, 0]
|
||||
inner_ptr: Annotated[POINTER[Inner], 8]
|
||||
init_records()
|
||||
|
||||
src = """
|
||||
struct inner { int value; int flag; };
|
||||
@@ -278,7 +292,7 @@ class TestC(unittest.TestCase):
|
||||
}
|
||||
"""
|
||||
dll = self.compile(src)
|
||||
@dll.bind(ctypes.c_int, ctypes.POINTER(Inner))
|
||||
@dll.bind
|
||||
def test(p:POINTER[Inner]) -> ctypes.c_int: ...
|
||||
|
||||
inner = Inner(value=42, flag=10)
|
||||
@@ -292,16 +306,17 @@ class TestC(unittest.TestCase):
|
||||
# This causes the pointed-to object to be garbage collected, leading to use-after-free.
|
||||
from tinygrad.runtime.support.c import POINTER
|
||||
@record
|
||||
class MaskContext(c.Struct):
|
||||
class MaskContext:
|
||||
SIZE = 16
|
||||
value = Field(ctypes.c_int, 0)
|
||||
initialized = Field(ctypes.c_int, 4)
|
||||
ptr = Field(ctypes.c_void_p, 8)
|
||||
value: Annotated[ctypes.c_int, 0]
|
||||
initialized: Annotated[ctypes.c_int, 4]
|
||||
ptr: Annotated[ctypes.c_void_p, 8]
|
||||
@record
|
||||
class Params(c.Struct):
|
||||
class Params:
|
||||
SIZE = 16
|
||||
x = Field(ctypes.c_int, 0)
|
||||
mask = Field(POINTER[MaskContext], 8)
|
||||
x: Annotated[ctypes.c_int, 0]
|
||||
mask: Annotated[POINTER[MaskContext], 8]
|
||||
init_records()
|
||||
|
||||
src = """
|
||||
struct mask_ctx { int value; int initialized; void *ptr; };
|
||||
@@ -309,9 +324,9 @@ class TestC(unittest.TestCase):
|
||||
int mask_end(struct mask_ctx *m) { return m->value + m->initialized; }
|
||||
"""
|
||||
dll = self.compile(src)
|
||||
@dll.bind(None, ctypes.POINTER(MaskContext), ctypes.c_int)
|
||||
@dll.bind
|
||||
def mask_begin(m:POINTER[MaskContext], val:ctypes.c_int) -> None: ...
|
||||
@dll.bind(ctypes.c_int, ctypes.POINTER(MaskContext))
|
||||
@dll.bind
|
||||
def mask_end(m:POINTER[MaskContext]) -> ctypes.c_int: ...
|
||||
|
||||
# When MaskContext() is created inline, it gets garbage collected after the pointer
|
||||
@@ -429,10 +444,6 @@ typedef struct
|
||||
self.assertTrue(hasattr(rect, 'height'))
|
||||
self.assertTrue(hasattr(rect, 'color'))
|
||||
|
||||
p2 = Point(10, 20)
|
||||
self.assertEqual(p2.x, 10)
|
||||
self.assertEqual(p2.y, 20)
|
||||
|
||||
def test_struct_ordering(self):
|
||||
namespace = self.run_gen("""
|
||||
struct A;
|
||||
|
||||
@@ -26,17 +26,8 @@ class TestDevice(unittest.TestCase):
|
||||
|
||||
@unittest.skipIf(Device.DEFAULT != "CPU", "only run on CPU")
|
||||
def test_nonexistent_renderer(self):
|
||||
with self.assertRaisesRegex(RuntimeError, "has no renderer"):
|
||||
with self.assertRaisesRegex(AssertionError, "No renderer"):
|
||||
with Context(DEV="CPU:TYPO"): Device[Device.DEFAULT].renderer
|
||||
with self.assertRaisesRegex(RuntimeError, "did you mean: 'CLANGJIT'"):
|
||||
with Context(DEV="CPU:CLANG"): Device[Device.DEFAULT].renderer
|
||||
|
||||
@unittest.skipIf(Device.DEFAULT != "AMD", "only run on AMD")
|
||||
def test_nonexistent_iface(self):
|
||||
result = subprocess.run(['python3', '-c', 'from tinygrad import Device; Device[Device.DEFAULT].iface'],
|
||||
env={**os.environ, "DEV":"USA+AMD"}, capture_output=True)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn(b"did you mean: 'USB'", result.stderr)
|
||||
|
||||
def test_lowercase_canonicalizes(self):
|
||||
device = Device.DEFAULT
|
||||
@@ -127,11 +118,10 @@ class TestDevVar(unittest.TestCase):
|
||||
("AMD:LLVM:gfx1100", Target(device="AMD", renderer="LLVM", arch="gfx1100")), ("::gfx1100", Target(arch="gfx1100")),
|
||||
("USB+", Target(interface="USB")), ("USB+AMD", Target(device="AMD", interface="USB")),
|
||||
("PCI:0+AMD", Target(device="AMD", interface="PCI", indices="0")), (":0+AMD", Target(device="AMD", indices="0")),
|
||||
("PCI:0,1+AMD", Target(device="AMD", interface="PCI", indices="0,1")),
|
||||
("QCOM;USB+AMD", [Target(device="QCOM"), Target(device="AMD", interface="USB")])]:
|
||||
("PCI:0,1+AMD", Target(device="AMD", interface="PCI", indices="0,1"))]:
|
||||
with Context(DEV=d):
|
||||
self.assertEqual(DEV.value, t if isinstance(t, list) else [t])
|
||||
self.assertEqual(str(DEV), d)
|
||||
self.assertEqual(DEV.value, t)
|
||||
self.assertEqual(str(DEV.value), d)
|
||||
|
||||
def test_target(self):
|
||||
with Context(DEV="CPU"): self.assertEqual(DEV.target("CPU"), Target("CPU"))
|
||||
@@ -139,10 +129,6 @@ class TestDevVar(unittest.TestCase):
|
||||
with Context(DEV=":LLVM"): self.assertEqual(DEV.target("CPU"), Target("CPU", "LLVM"))
|
||||
with Context(DEV="AMD:LLVM"): self.assertEqual(DEV.target("CPU"), Target("CPU"))
|
||||
with Context(DEV=""): self.assertEqual(DEV.target("CPU"), Target("CPU"))
|
||||
with Context(DEV="QCOM:IR3;AMD:LLVM"):
|
||||
self.assertEqual(DEV.target("QCOM"), Target("QCOM", "IR3"))
|
||||
self.assertEqual(DEV.target("AMD"), Target("AMD", "LLVM"))
|
||||
self.assertEqual(DEV.target("CPU"), Target("CPU"))
|
||||
|
||||
def test_dev_arch_override(self):
|
||||
with Context(DEV="NULL:HIP:gfx1100"):
|
||||
|
||||
@@ -46,18 +46,6 @@ class TestLLMTokenizer(unittest.TestCase):
|
||||
def test_llama_repeat(self): self._test_coding(self.llama_tok, "00000000000000000", [ 931, 931, 931, 931, 931, 410 ])
|
||||
def test_llama_pat(self): self._test_coding(self.llama_tok, "today\n \n", [ 31213, 14211 ])
|
||||
|
||||
def test_tekken_from_gguf_kv(self):
|
||||
kv = {
|
||||
"tokenizer.ggml.tokens": ["<unk>", "<s>", "</s>", "[INST]", "[/INST]", "hello"],
|
||||
"tokenizer.ggml.token_type": [3, 3, 3, 3, 3, 1],
|
||||
"tokenizer.ggml.pre": "tekken",
|
||||
}
|
||||
tok = SimpleTokenizer.from_gguf_kv(kv)
|
||||
self.assertEqual(tok.role("user"), [3])
|
||||
self.assertEqual(tok.encode("hello"), [5])
|
||||
self.assertEqual(tok.end_turn(2), [4])
|
||||
self.assertEqual(tok.role("assistant"), [])
|
||||
|
||||
def test_stream_decoder(self):
|
||||
"""stream_decoder buffers incomplete UTF-8: token 25677 has 3/4 of emoji, token 138 completes it."""
|
||||
bs = [*range(33, 127), *range(161, 173), *range(174, 256)]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import unittest
|
||||
from tinygrad import dtypes
|
||||
from tinygrad.uop.ops import UOp, Ops
|
||||
from tinygrad.schedule.memory import memory_plan_rewrite
|
||||
from tinygrad.engine.memory import memory_plan_rewrite
|
||||
|
||||
global_map = {}
|
||||
held_bufs: set[UOp] = set()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import gc, unittest
|
||||
from tinygrad import Tensor, GlobalCounters, dtypes
|
||||
from tinygrad.engine.jit import TinyJit
|
||||
from tinygrad.helpers import Context
|
||||
|
||||
class TestMultiRamUsage(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@@ -140,19 +139,6 @@ class TestMultiRamUsage(unittest.TestCase):
|
||||
mem_4 = run_layers(4)
|
||||
self.assertEqual(mem_2, mem_4, f"graph memory should not grow with layers: 2 layers={mem_2}, 4 layers={mem_4}")
|
||||
|
||||
def test_allreduce_cast_dtype_memory(self):
|
||||
N = 32
|
||||
devices_2 = ("NULL:1", "NULL:2")
|
||||
mem = {}
|
||||
for allreduce_cast in (0, 1):
|
||||
GlobalCounters.reset()
|
||||
with Context(ALLREDUCE_CAST=allreduce_cast, SCACHE=0):
|
||||
x = Tensor.empty((N, N), dtype=dtypes.bfloat16, device="NULL:1").shard(devices_2, axis=0)
|
||||
x.sum(0).realize()
|
||||
mem[allreduce_cast] = GlobalCounters.global_mem
|
||||
# with ALLREDUCE_CAST, allreduce copies happen in bf16 (2 bytes) instead of fp32 (4 bytes)
|
||||
self.assertLess(mem[1], mem[0])
|
||||
|
||||
class TestMultiAxis(unittest.TestCase):
|
||||
def test_reshape_shard_invalid(self):
|
||||
devices = ("NULL:0", "NULL:1")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import unittest
|
||||
from tinygrad import Tensor, Device, Context
|
||||
from tinygrad import Tensor, Device
|
||||
from tinygrad.engine.realize import get_program
|
||||
from tinygrad.codegen.opt import Opt, OptOps
|
||||
from test.external.process_replay.process_replay import replay_get_program
|
||||
@@ -30,12 +30,5 @@ class TestProcessReplay(unittest.TestCase):
|
||||
good, compare, _ = replay_get_program(p, self.ast, self.renderer, opts=opts)
|
||||
self.assertEqual(good, compare)
|
||||
|
||||
@Context(BEAM=1)
|
||||
def test_beam(self):
|
||||
si = (Tensor.empty(N, N) @ Tensor.empty(N, N)).schedule()[-1]
|
||||
p = get_program(si.ast, self.renderer)
|
||||
good, compare, _ = replay_get_program(p, self.ast, self.renderer)
|
||||
self.assertEqual(good, compare)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# schedule tests that pass on NULL backend (no copyout needed)
|
||||
import gc, unittest, time
|
||||
from tinygrad import nn, dtypes, Device, Tensor
|
||||
from tinygrad.uop.ops import UOp, Ops, GroupOp, UPat, KernelInfo
|
||||
from tinygrad.uop.ops import UOp, Ops, GroupOp, UPat
|
||||
from tinygrad.helpers import DEBUG, GlobalCounters, Context
|
||||
from tinygrad.engine.realize import CompiledRunner, run_schedule
|
||||
|
||||
@@ -143,36 +143,6 @@ class TestSimpleSchedule(unittest.TestCase):
|
||||
self.assertEqual(len(Tensor.schedule(a1, a2)), 1)
|
||||
|
||||
class TestSchedule(unittest.TestCase):
|
||||
def test_create_schedule_handles_multi_kernel_after_and_after_deps(self):
|
||||
def named_copy(name:str):
|
||||
def fxn(out:UOp, src:UOp) -> UOp:
|
||||
i = UOp.range(src.shape[0], 0)
|
||||
return out[i].store(src[i]).end(i).sink(arg=KernelInfo(name=name))
|
||||
return fxn
|
||||
|
||||
src = Tensor.zeros(4, dtype=dtypes.float).contiguous().realize()
|
||||
dep = Tensor.zeros(4, dtype=dtypes.float).contiguous().realize()
|
||||
out = Tensor.zeros(4, dtype=dtypes.float).contiguous().realize()
|
||||
ones = Tensor.ones(4, dtype=dtypes.float).contiguous().realize()
|
||||
twos = Tensor.full((4,), 2.0, dtype=dtypes.float).contiguous().realize()
|
||||
threes = Tensor.full((4,), 3.0, dtype=dtypes.float).contiguous().realize()
|
||||
|
||||
ka = Tensor.custom_kernel(src, ones, fxn=named_copy("ka"))[0]
|
||||
kb = Tensor.custom_kernel(src, twos, fxn=named_copy("kb"))[0]
|
||||
src_after = Tensor(src.uop.after(*ka.uop.src[1:], *kb.uop.src[1:]))
|
||||
|
||||
kd = Tensor.custom_kernel(dep, threes, fxn=named_copy("kd"))[0]
|
||||
kc = Tensor.custom_kernel(out, src_after, fxn=named_copy("kc"))[0]
|
||||
out_after = Tensor(kc.uop.src[0].after(*kc.uop.src[1:], kd.uop))
|
||||
|
||||
schedule = out_after.schedule()
|
||||
names = [si.ast.arg.name for si in schedule]
|
||||
self.assertEqual(set(names), {"ka", "kb", "kc", "kd"})
|
||||
self.assertEqual(names[-1], "kc")
|
||||
self.assertLess(names.index("ka"), names.index("kc"))
|
||||
self.assertLess(names.index("kb"), names.index("kc"))
|
||||
self.assertLess(names.index("kd"), names.index("kc"))
|
||||
|
||||
@unittest.skipIf(Device.DEFAULT == "CPU", "devices must mismatch")
|
||||
def test_error_on_device_mismatch(self):
|
||||
a = Tensor.empty(10)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import unittest
|
||||
from tinygrad import Tensor, Variable, Context
|
||||
from tinygrad.helpers import cpu_events
|
||||
from tinygrad.schedule import schedule_cache
|
||||
from tinygrad.engine.schedule import schedule_cache
|
||||
|
||||
def schedule_one():
|
||||
Tensor([1]).schedule()
|
||||
|
||||
@@ -97,16 +97,5 @@ class TestSymbolicShrink(unittest.TestCase):
|
||||
t = Tensor.rand(3, 5).shrink(((0, 2), (vi, vi+1)))
|
||||
assert t.shape == (2, 1)
|
||||
|
||||
class TestSymbolicContiguousViewOffset(unittest.TestCase):
|
||||
def test_shrink_from_start(self):
|
||||
v = Variable("v", 1, 10).bind(5)
|
||||
t = Tensor.rand(10).realize().shrink(((0, v),))
|
||||
self.assertEqual(t.uop.contiguous_view_offset(), 0)
|
||||
|
||||
def test_shrink_with_offset(self):
|
||||
v = Variable("v", 1, 7).bind(4)
|
||||
t = Tensor.rand(10).realize().shrink(((3, 3+v),))
|
||||
self.assertEqual(t.uop.contiguous_view_offset(), 3)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -2,7 +2,7 @@ import unittest
|
||||
from tinygrad import Tensor, dtypes
|
||||
from tinygrad.tensor import _METADATA
|
||||
from tinygrad.engine.realize import capturing
|
||||
from tinygrad.schedule import linear_to_schedule
|
||||
from tinygrad.engine.schedule import linear_to_schedule
|
||||
from tinygrad.helpers import Context
|
||||
|
||||
@unittest.skip("tensor metadata is no longer supported")
|
||||
|
||||
@@ -1,74 +1,82 @@
|
||||
import math, unittest
|
||||
from tinygrad import Tensor
|
||||
|
||||
# TODO: make all the expectedFailure cases pass — i.e. UOp.__getitem__ should produce the same UOp graph as
|
||||
# Tensor.__getitem__ for every view-returning index pattern.
|
||||
|
||||
def _t(*shape):
|
||||
return Tensor.arange(math.prod(shape)).reshape(*shape)
|
||||
|
||||
# Tensor().func().uop should be the same as UOp.func()
|
||||
def _check(tc: unittest.TestCase, t: Tensor, fn):
|
||||
tc.assertIs(fn(t).uop, fn(t.uop), f"\ntensor.uop = {fn(t).uop}\nuop = {fn(t.uop)}")
|
||||
|
||||
class TestTensorUOpGetitem(unittest.TestCase):
|
||||
"""For each pattern, check that `Tensor(x)[idx].uop` equals `x.uop[idx]`."""
|
||||
|
||||
def _check(self, t: Tensor, idx):
|
||||
via_tensor = t[idx].uop
|
||||
via_uop = t.uop[idx]
|
||||
self.assertIs(via_tensor, via_uop, f"\nidx={idx!r}\ntensor.uop = {via_tensor}\nuop[idx] = {via_uop}")
|
||||
|
||||
# ---- pure slice patterns ----
|
||||
def test_slice_full(self): _check(self, _t(4), lambda x: x[slice(None)])
|
||||
def test_slice_positive(self): _check(self, _t(8), lambda x: x[1:5])
|
||||
def test_slice_open_start(self): _check(self, _t(8), lambda x: x[:5])
|
||||
def test_slice_open_stop(self): _check(self, _t(8), lambda x: x[3:])
|
||||
def test_slice_negative_start(self): _check(self, _t(8), lambda x: x[-3:])
|
||||
def test_slice_negative_stop(self): _check(self, _t(8), lambda x: x[:-2])
|
||||
def test_slice_both_negative(self): _check(self, _t(8), lambda x: x[-5:-1])
|
||||
def test_slice_full(self): self._check(_t(4), slice(None))
|
||||
def test_slice_positive(self): self._check(_t(8), slice(1, 5))
|
||||
def test_slice_open_start(self): self._check(_t(8), slice(None, 5))
|
||||
def test_slice_open_stop(self): self._check(_t(8), slice(3, None))
|
||||
@unittest.expectedFailure
|
||||
def test_slice_negative_start(self): self._check(_t(8), slice(-3, None))
|
||||
@unittest.expectedFailure
|
||||
def test_slice_negative_stop(self): self._check(_t(8), slice(None, -2))
|
||||
@unittest.expectedFailure
|
||||
def test_slice_both_negative(self): self._check(_t(8), slice(-5, -1))
|
||||
|
||||
# ---- slice with stride ----
|
||||
def test_slice_stride(self): _check(self, _t(6), lambda x: x[::2])
|
||||
def test_slice_start_stop_stride(self): _check(self, _t(6), lambda x: x[1:5:2])
|
||||
def test_slice_reverse(self): _check(self, _t(6), lambda x: x[::-1])
|
||||
def test_slice_singleton_negative_step(self): _check(self, _t(8), lambda x: x[3:2:-1])
|
||||
@unittest.expectedFailure
|
||||
def test_slice_stride(self): self._check(_t(6), slice(None, None, 2))
|
||||
@unittest.expectedFailure
|
||||
def test_slice_start_stop_stride(self): self._check(_t(6), slice(1, 5, 2))
|
||||
@unittest.expectedFailure
|
||||
def test_slice_reverse(self): self._check(_t(6), slice(None, None, -1))
|
||||
@unittest.expectedFailure
|
||||
def test_slice_singleton_negative_step(self): self._check(_t(8), slice(3, 2, -1))
|
||||
|
||||
# ---- empty / out-of-bounds slice ----
|
||||
def test_slice_empty(self): _check(self, _t(6), lambda x: x[3:1])
|
||||
def test_slice_oob_stop(self): _check(self, _t(6), lambda x: x[0:100])
|
||||
@unittest.expectedFailure
|
||||
def test_slice_empty(self): self._check(_t(6), slice(3, 1))
|
||||
@unittest.expectedFailure
|
||||
def test_slice_oob_stop(self): self._check(_t(6), slice(0, 100))
|
||||
|
||||
# ---- single int (reduces a dim) ----
|
||||
def test_int_positive(self): _check(self, _t(8), lambda x: x[3])
|
||||
def test_int_negative(self): _check(self, _t(8), lambda x: x[-1])
|
||||
@unittest.expectedFailure
|
||||
def test_int_positive(self): self._check(_t(8), 3)
|
||||
@unittest.expectedFailure
|
||||
def test_int_negative(self): self._check(_t(8), -1)
|
||||
|
||||
# ---- ellipsis ----
|
||||
def test_ellipsis_only(self): _check(self, _t(2, 3, 4), lambda x: x[...])
|
||||
def test_ellipsis_then_int(self): _check(self, _t(2, 3, 4), lambda x: x[..., -1])
|
||||
def test_ellipsis_then_slice(self): _check(self, _t(2, 3, 4), lambda x: x[..., 1:3])
|
||||
def test_ellipsis_then_none(self): _check(self, _t(2, 3), lambda x: x[..., None])
|
||||
def test_ellipsis_only(self): self._check(_t(2, 3, 4), (Ellipsis,))
|
||||
@unittest.expectedFailure
|
||||
def test_ellipsis_then_int(self): self._check(_t(2, 3, 4), (Ellipsis, -1))
|
||||
def test_ellipsis_then_slice(self): self._check(_t(2, 3, 4), (Ellipsis, slice(1, 3)))
|
||||
@unittest.expectedFailure
|
||||
def test_ellipsis_then_none(self): self._check(_t(2, 3), (Ellipsis, None))
|
||||
|
||||
# ---- None (unsqueeze) ----
|
||||
def test_none_front(self): _check(self, _t(4), lambda x: x[None])
|
||||
def test_none_back(self): _check(self, _t(4), lambda x: x[:, None])
|
||||
def test_none_middle(self): _check(self, _t(2, 3), lambda x: x[:, None, :])
|
||||
def test_multiple_none(self): _check(self, _t(2, 3), lambda x: x[None, :, None])
|
||||
@unittest.expectedFailure
|
||||
def test_none_front(self): self._check(_t(4), (None,))
|
||||
@unittest.expectedFailure
|
||||
def test_none_back(self): self._check(_t(4), (slice(None), None))
|
||||
@unittest.expectedFailure
|
||||
def test_none_middle(self): self._check(_t(2, 3), (slice(None), None, slice(None)))
|
||||
@unittest.expectedFailure
|
||||
def test_multiple_none(self): self._check(_t(2, 3), (None, slice(None), None))
|
||||
|
||||
# ---- mixed multi-dim ----
|
||||
def test_int_then_slice(self): _check(self, _t(2, 3), lambda x: x[1, :])
|
||||
def test_multi_int(self): _check(self, _t(2, 3, 4), lambda x: x[1, 2])
|
||||
def test_mixed_slice_int(self): _check(self, _t(2, 3, 4), lambda x: x[0:2, -1, 1:3])
|
||||
def test_mixed_slice_slice(self): _check(self, _t(3, 4, 5), lambda x: x[1:3, :, 0:2])
|
||||
def test_high_rank_combo(self): _check(self, _t(4, 5, 6), lambda x: x[1:3, :, -1, None])
|
||||
|
||||
class TestTensorUOpCumalu(unittest.TestCase):
|
||||
def test_cumsum_1d(self): _check(self, _t(5), lambda x: x.cumsum())
|
||||
def test_cumsum_2d(self): _check(self, _t(3, 4), lambda x: x.cumsum(1))
|
||||
def test_cumsum_non_last(self): _check(self, _t(3, 4), lambda x: x.cumsum(0))
|
||||
def test_cumsum_large(self): _check(self, _t(600), lambda x: x.cumsum()) # exercises _split_cumalu
|
||||
def test_cumprod(self): _check(self, _t(4), lambda x: x.cumprod(0))
|
||||
|
||||
class TestTensorUOpCat(unittest.TestCase):
|
||||
def test_cat_dim0(self): _check(self, _t(2, 3), lambda x: x.cat(x, dim=0))
|
||||
def test_cat_dim1(self): _check(self, _t(2, 3), lambda x: x.cat(x, dim=1))
|
||||
def test_cat_3tensors(self): _check(self, _t(2, 3), lambda x: x.cat(x, x, dim=0))
|
||||
def test_cat_neg_dim(self): _check(self, _t(2, 3, 4), lambda x: x.cat(x, dim=-1))
|
||||
|
||||
class TestTensorUOpStack(unittest.TestCase):
|
||||
def test_stack_dim0(self): _check(self, _t(2, 3), lambda x: x.stack(x, dim=0))
|
||||
def test_stack_dim1(self): _check(self, _t(2, 3), lambda x: x.stack(x, dim=1))
|
||||
def test_stack_3tensors(self): _check(self, _t(2, 3), lambda x: x.stack(x, x, dim=0))
|
||||
def test_stack_new_last(self): _check(self, _t(2, 3), lambda x: x.stack(x, dim=-1))
|
||||
@unittest.expectedFailure
|
||||
def test_int_then_slice(self): self._check(_t(2, 3), (1, slice(None)))
|
||||
@unittest.expectedFailure
|
||||
def test_multi_int(self): self._check(_t(2, 3, 4), (1, 2))
|
||||
@unittest.expectedFailure
|
||||
def test_mixed_slice_int(self): self._check(_t(2, 3, 4), (slice(0, 2), -1, slice(1, 3)))
|
||||
def test_mixed_slice_slice(self): self._check(_t(3, 4, 5), (slice(1, 3), slice(None), slice(0, 2)))
|
||||
@unittest.expectedFailure
|
||||
def test_high_rank_combo(self): self._check(_t(4, 5, 6), (slice(1, 3), slice(None), -1, None))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
+21
-21
@@ -10,7 +10,7 @@ from tinygrad.helpers import VIZ, cpu_profile, ProfilePointEvent, unwrap
|
||||
from tinygrad.device import Buffer
|
||||
|
||||
from tinygrad.uop.ops import tracked_keys, tracked_ctxs, uop_fields, active_rewrites, active_group, _name_cnt, RewriteTrace
|
||||
from tinygrad.viz.serve import load_rewrites, get_full_rewrite, uop_to_json, VizData
|
||||
from tinygrad.viz.serve import get_rewrites, get_full_rewrite, uop_to_json
|
||||
|
||||
@track_rewrites(name=True)
|
||||
def exec_rewrite(sink:UOp, pm_lst:list[PatternMatcher], names:None|list[str]=None) -> UOp:
|
||||
@@ -21,19 +21,19 @@ def exec_rewrite(sink:UOp, pm_lst:list[PatternMatcher], names:None|list[str]=Non
|
||||
# small container class for the viz server module
|
||||
class VizTrace:
|
||||
# loader init
|
||||
def __init__(self): self._data:VizData|None = None
|
||||
def __init__(self): self._trace:RewriteTrace|None = None
|
||||
@property
|
||||
def data(self) -> VizData: return unwrap(self._data)
|
||||
def set_data(self) -> None:
|
||||
data = VizData(RewriteTrace(tracked_keys.copy(), tracked_ctxs.copy(), uop_fields.copy()))
|
||||
load_rewrites(data)
|
||||
self._data = data
|
||||
def trace(self) -> RewriteTrace: return unwrap(self._trace)
|
||||
def set_trace(self) -> None:
|
||||
self._trace = RewriteTrace(tracked_keys.copy(), tracked_ctxs.copy(), uop_fields.copy())
|
||||
import tinygrad.viz.serve as serve_module
|
||||
serve_module.trace = self._trace
|
||||
# the API
|
||||
def list_items(self) -> list[dict]:
|
||||
return self.data.ctxs
|
||||
def list_items(self) -> list[dict]: return get_rewrites(self.trace)
|
||||
def get_details(self, rewrite_idx:int, step:int) -> Generator[dict, None, None]:
|
||||
assert len(self.data.trace.rewrites) > rewrite_idx, f"only loaded {len(self.data.trace.rewrites)} traces, expecting at least {rewrite_idx}"
|
||||
return get_full_rewrite(self.data, self.data.trace.rewrites[rewrite_idx][step])
|
||||
lst = self.list_items()
|
||||
assert len(lst) > rewrite_idx, f"only loaded {len(lst)} traces, expecting at least {rewrite_idx}"
|
||||
return get_full_rewrite(self.trace.rewrites[rewrite_idx][step])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def save_viz():
|
||||
@@ -52,7 +52,7 @@ def save_viz():
|
||||
try:
|
||||
yield viz
|
||||
finally:
|
||||
viz.set_data()
|
||||
viz.set_trace()
|
||||
TRACK_MATCH_STATS.value = prev_tms
|
||||
PROFILE.value = prev_profile
|
||||
VIZ.value = prev_viz
|
||||
@@ -194,7 +194,7 @@ class TestViz(unittest.TestCase):
|
||||
class TestStruct:
|
||||
colored_field: str
|
||||
a = UOp(Ops.CUSTOM, arg=TestStruct(colored("xyz", "magenta")+colored("12345", "blue")))
|
||||
a2 = uop_to_json(VizData(), a)[id(a)]
|
||||
a2 = uop_to_json(a)[id(a)]
|
||||
self.assertEqual(ansistrip(a2["label"]), f"CUSTOM\n{TestStruct.__qualname__}(colored_field='xyz12345')")
|
||||
|
||||
def test_colored_label_multiline(self):
|
||||
@@ -217,11 +217,11 @@ class TestViz(unittest.TestCase):
|
||||
# use smaller stack limit for faster test (default is 250000)
|
||||
with Context(REWRITE_STACK_LIMIT=100): self.assertRaises(RuntimeError, exec_rewrite, a, [pm])
|
||||
graphs = flatten(x["graph"].values() for x in viz.get_details(0, 0))
|
||||
self.assertEqual(graphs[0], uop_to_json(VizData(), a)[id(a)])
|
||||
self.assertEqual(graphs[1], uop_to_json(VizData(), b)[id(b)])
|
||||
self.assertEqual(graphs[0], uop_to_json(a)[id(a)])
|
||||
self.assertEqual(graphs[1], uop_to_json(b)[id(b)])
|
||||
# fallback to NOOP with the error message
|
||||
nop = UOp(Ops.NOOP, arg="infinite loop in fixed_point_rewrite")
|
||||
self.assertEqual(graphs[2], uop_to_json(VizData(), nop)[id(nop)])
|
||||
self.assertEqual(graphs[2], uop_to_json(nop)[id(nop)])
|
||||
|
||||
def test_const_node_visibility(self):
|
||||
with save_viz() as viz:
|
||||
@@ -241,7 +241,7 @@ class TestViz(unittest.TestCase):
|
||||
c = UOp.const(dtypes.float, 1.0, device="CPU", shape=(3,4)) # creates CONST->RESHAPE->EXPAND chain
|
||||
a = UOp(Ops.DEFINE_VAR, dtypes.float, arg=("a", 0.0, 10.0))
|
||||
alu = a + c
|
||||
graph = uop_to_json(VizData(), alu)
|
||||
graph = uop_to_json(alu)
|
||||
# the RESHAPE and EXPAND nodes from the const should not appear in the graph
|
||||
labels = {v["label"].split("\n")[0] for v in graph.values()}
|
||||
self.assertNotIn("RESHAPE", labels)
|
||||
@@ -335,7 +335,7 @@ class TestVizIntegration(unittest.TestCase):
|
||||
prg = get_program(ast, Device[Device.DEFAULT].renderer)
|
||||
lst = viz.list_items()
|
||||
self.assertEqual(len(lst), 3)
|
||||
self.assertEqual(lst[0]["name"], "Callify 1 Buffer n1")
|
||||
self.assertEqual(lst[0]["name"], "Process 1 Buffer n1")
|
||||
self.assertEqual(lst[1]["name"], "Schedule 1 Kernel n1")
|
||||
self.assertEqual(lst[2]["name"], prg.name)
|
||||
|
||||
@@ -417,7 +417,7 @@ from tinygrad.device import ProfileDeviceEvent, ProfileGraphEvent, ProfileGraphE
|
||||
from tinygrad.viz.serve import get_profile
|
||||
from extra.viz.cli import decode_profile
|
||||
|
||||
def load_profile(lst:list[ProfileEvent]) -> dict: return decode_profile(get_profile(VizData(), lst))
|
||||
def load_profile(lst:list[ProfileEvent]) -> dict: return decode_profile(get_profile(lst))
|
||||
|
||||
class TestVizProfiler(unittest.TestCase):
|
||||
def test_transfer_uses_copy_device(self):
|
||||
@@ -563,7 +563,7 @@ class TestVizProfiler(unittest.TestCase):
|
||||
step = 10
|
||||
n_events = 1_000
|
||||
prof = [ProfileRangeEvent("CPU", name="k_test", st=decimal.Decimal(ts:=i*step), en=decimal.Decimal(ts)+step) for i in range(n_events)]
|
||||
sz = len(get_profile(VizData(), prof))
|
||||
sz = len(get_profile(prof))
|
||||
self.assertLessEqual(sz/n_events, 26)
|
||||
|
||||
def test_calltrace(self):
|
||||
@@ -586,7 +586,7 @@ class TestVizProfiler(unittest.TestCase):
|
||||
step = decimal.Decimal(dur_mins*60*1e6//n_events)
|
||||
prof = [ProfileRangeEvent("CPU", name="k_test", st=decimal.Decimal(ts:=i*step), en=decimal.Decimal(ts)+step) for i in range(n_events)]
|
||||
with self.assertRaisesRegex(ValueError, "timestamp out of range"):
|
||||
get_profile(VizData(), prof)
|
||||
get_profile(prof)
|
||||
|
||||
def test_python_marker(self):
|
||||
with save_viz():
|
||||
|
||||
@@ -3,7 +3,7 @@ import unittest, math, time
|
||||
from tinygrad import Tensor, Device, dtypes, Context
|
||||
from tinygrad.uop.ops import UOp, Ops
|
||||
from tinygrad.engine.realize import get_runner
|
||||
from tinygrad.schedule import ExecItem
|
||||
from tinygrad.engine.schedule import ExecItem
|
||||
from tinygrad.engine.jit import TinyJit
|
||||
import numpy as np
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import unittest
|
||||
from tinygrad import Tensor, dtypes
|
||||
from tinygrad import Tensor
|
||||
from tinygrad.helpers import Context
|
||||
from tinygrad.uop.ops import Ops
|
||||
|
||||
@@ -25,28 +25,5 @@ class TestRingAllReduce(unittest.TestCase):
|
||||
out = t.sum(0)
|
||||
self.assertListEqual(out.tolist(), [4]*N*100)
|
||||
|
||||
class TestAllreduceCast(unittest.TestCase):
|
||||
def _get_copy_dtypes(self, dtype, allreduce_cast):
|
||||
ds = tuple(f"CPU:{i}" for i in range(2))
|
||||
with Context(ALLREDUCE_CAST=allreduce_cast, RING=0, SCACHE=0):
|
||||
t = Tensor.empty(4, 4, dtype=dtype).shard(ds, axis=0)
|
||||
schedules = t.sum(0).schedule_with_vars()[0]
|
||||
return {si.bufs[0].dtype.scalar() for si in schedules if si.ast.op is Ops.COPY}
|
||||
|
||||
def test_allreduce_cast_bf16(self):
|
||||
# with ALLREDUCE_CAST, allreduce copies stay in bfloat16 instead of promoting to float32
|
||||
self.assertNotIn(dtypes.float, self._get_copy_dtypes(dtypes.bfloat16, allreduce_cast=1))
|
||||
self.assertIn(dtypes.float, self._get_copy_dtypes(dtypes.bfloat16, allreduce_cast=0))
|
||||
|
||||
def test_allreduce_cast_half(self):
|
||||
self.assertNotIn(dtypes.float, self._get_copy_dtypes(dtypes.half, allreduce_cast=1))
|
||||
self.assertIn(dtypes.float, self._get_copy_dtypes(dtypes.half, allreduce_cast=0))
|
||||
|
||||
def test_allreduce_cast_float32_noop(self):
|
||||
# float32 should not be affected by ALLREDUCE_CAST (no promotion happens)
|
||||
dtypes_on = self._get_copy_dtypes(dtypes.float, allreduce_cast=1)
|
||||
dtypes_off = self._get_copy_dtypes(dtypes.float, allreduce_cast=0)
|
||||
self.assertEqual(dtypes_on, dtypes_off)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -947,38 +947,5 @@ class TestPartialAssignToSharedBuffer(unittest.TestCase):
|
||||
for v, s in zip(views, shapes):
|
||||
np.testing.assert_allclose(v.numpy(), np.ones(s))
|
||||
|
||||
|
||||
class TestAfterCachePatterns(unittest.TestCase):
|
||||
def test_double_store_after(self):
|
||||
a = Tensor.zeros(10).contiguous()
|
||||
b = Tensor.zeros(10).contiguous()
|
||||
c = Tensor.ones(10).contiguous()
|
||||
Tensor.realize(a, b, c)
|
||||
|
||||
a_store = a.uop.store(c.uop)
|
||||
b_store = b.uop.store(c.uop)
|
||||
|
||||
with self.assertRaises(AssertionError):
|
||||
a = Tensor(a.uop.after(a_store, b_store))
|
||||
a.realize()
|
||||
np.testing.assert_array_equal(a.numpy(), 1)
|
||||
np.testing.assert_array_equal(b.numpy(), 1)
|
||||
|
||||
def test_double_store_after_different_sizes(self):
|
||||
full = Tensor.zeros(2).contiguous()
|
||||
head = Tensor.zeros(1).contiguous()
|
||||
full_src = Tensor([1, 2], dtype=dtypes.float).contiguous()
|
||||
head_src = Tensor([3], dtype=dtypes.float).contiguous()
|
||||
Tensor.realize(full, head, full_src, head_src)
|
||||
|
||||
full_store = full.uop.store(full_src.uop)
|
||||
head_store = head.uop.store(head_src.uop)
|
||||
|
||||
with self.assertRaises(AssertionError):
|
||||
head = Tensor(head.uop.after(head_store, full_store))
|
||||
head.realize()
|
||||
np.testing.assert_array_equal(head.numpy(), [3])
|
||||
np.testing.assert_array_equal(full.numpy(), [1, 2])
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
+1
-137
@@ -1,10 +1,7 @@
|
||||
import unittest
|
||||
import numpy as np
|
||||
from tinygrad import Tensor, dtypes
|
||||
from tinygrad.apps.llm import (
|
||||
GatedDeltaNetBlock, SSMConfig, TransformerBlock, TransformerConfig,
|
||||
apply_rope as apply_rope_new, precompute_freqs_cis, pairwise_topk,
|
||||
)
|
||||
from tinygrad.apps.llm import TransformerBlock, TransformerConfig, apply_rope as apply_rope_new, precompute_freqs_cis, pairwise_topk
|
||||
|
||||
def apply_rope(x:Tensor, start_pos:int):
|
||||
B, H, T, Hd = x.shape
|
||||
@@ -40,139 +37,6 @@ class TestAttention(unittest.TestCase):
|
||||
expected = apply_rope_new(k[..., :rope_dim], block.freqs_cis[:seqlen]).cat(k[..., rope_dim:], dim=-1)
|
||||
np.testing.assert_allclose(block.cache_kv[0, :, :, :seqlen, :].numpy(), expected.numpy(), rtol=1e-5, atol=1e-5)
|
||||
|
||||
class TestGatedDeltaNetBlock(unittest.TestCase):
|
||||
def _tensor_linspace(self, start:float, stop:float, shape:tuple[int, ...]) -> Tensor:
|
||||
return Tensor.linspace(start, stop, int(np.prod(shape)), dtype=dtypes.float32).reshape(*shape)
|
||||
|
||||
def _make_config(self, **kwargs):
|
||||
return TransformerConfig(**({"num_blocks":1, "dim":4, "hidden_dim":8, "n_heads":1, "n_kv_heads":1,
|
||||
"norm_eps":1e-5, "vocab_size":32, "head_dim":4, "rope_theta":10000.0,
|
||||
"rope_dim":4, "v_head_dim":4, "max_context":4, "full_attention_interval":2,
|
||||
"ssm":SSMConfig(conv_kernel=2, state_size=2, group_count=1, time_step_rank=1, inner_size=2)} | kwargs))
|
||||
|
||||
def _make_block(self, config:TransformerConfig) -> GatedDeltaNetBlock:
|
||||
block = GatedDeltaNetBlock(config, config.ssm)
|
||||
block.attn_norm.weight = self._tensor_linspace(0.8, 1.2, (config.dim,))
|
||||
block.attn_qkv.weight = self._tensor_linspace(-0.15, 0.2, (block.conv_channels, config.dim))
|
||||
block.attn_gate.weight = self._tensor_linspace(-0.1, 0.15, (config.ssm.inner_size, config.dim))
|
||||
block.ssm_alpha.weight = self._tensor_linspace(-0.08, 0.12, (block.num_v_heads, config.dim))
|
||||
block.ssm_beta.weight = self._tensor_linspace(-0.12, 0.07, (block.num_v_heads, config.dim))
|
||||
block.ssm_conv1d["weight"] = self._tensor_linspace(-0.05, 0.05, (block.conv_channels, block.ssm_conv_kernel))
|
||||
block.ssm_dt["bias"] = self._tensor_linspace(-0.1, 0.1, (block.num_v_heads,))
|
||||
block.ssm_a = self._tensor_linspace(-0.1, -0.05, (block.num_v_heads,))
|
||||
block.ssm_norm.weight = self._tensor_linspace(0.9, 1.1, (block.head_v_dim,))
|
||||
block.ssm_out.weight = self._tensor_linspace(-0.2, 0.18, (config.dim, config.ssm.inner_size))
|
||||
return block
|
||||
|
||||
def _run_attention(self, block:GatedDeltaNetBlock, x:Tensor, start_pos:int):
|
||||
x_norm = block.attn_norm(x)
|
||||
block._init_state(x_norm)
|
||||
return block._attention(x_norm, start_pos).realize().numpy()
|
||||
|
||||
def _cache_views(self, block:GatedDeltaNetBlock) -> tuple[np.ndarray, np.ndarray]:
|
||||
conv_flat = (block.ssm_conv_kernel - 1) * block.conv_channels
|
||||
cache = block.delta_cache.numpy()
|
||||
conv_state = cache[:, :conv_flat].reshape(cache.shape[0], block.ssm_conv_kernel - 1, block.conv_channels)
|
||||
recurrent_state = cache[:, conv_flat:].reshape(cache.shape[0], block.num_v_heads, block.head_v_dim, block.head_v_dim)
|
||||
return conv_state, recurrent_state
|
||||
|
||||
def _linear_np(self, x:np.ndarray, weight:np.ndarray) -> np.ndarray:
|
||||
return x.astype(np.float32) @ weight.T.astype(np.float32)
|
||||
|
||||
def _rms_norm_np(self, x:np.ndarray, weight:np.ndarray, eps:float) -> np.ndarray:
|
||||
x_float = x.astype(np.float32)
|
||||
return (x_float / np.sqrt((x_float * x_float).mean(axis=-1, keepdims=True) + eps)) * weight.astype(np.float32)
|
||||
|
||||
def _normalize_np(self, x:np.ndarray, eps:float=1e-12) -> np.ndarray:
|
||||
return x / np.maximum(np.sqrt((x * x).sum(axis=-1, keepdims=True)), eps)
|
||||
|
||||
def _softplus_np(self, x:np.ndarray) -> np.ndarray:
|
||||
return np.log1p(np.exp(-np.abs(x))) + np.maximum(x, 0)
|
||||
|
||||
def _silu_np(self, x:np.ndarray) -> np.ndarray:
|
||||
return x / (1.0 + np.exp(-x))
|
||||
|
||||
def _naive_attention(self, block:GatedDeltaNetBlock, x:Tensor):
|
||||
x_np = x.numpy().astype(np.float32)
|
||||
B, T, _ = x_np.shape
|
||||
conv_state = np.zeros((B, block.ssm_conv_kernel - 1, block.conv_channels), dtype=np.float32)
|
||||
recurrent_state = np.zeros((B, block.num_v_heads, block.head_v_dim, block.head_v_dim), dtype=np.float32)
|
||||
conv_weight = block.ssm_conv1d["weight"].numpy().astype(np.float32).T[None, :, :]
|
||||
qkv_weight = block.attn_qkv.weight.numpy().astype(np.float32)
|
||||
gate_weight = block.attn_gate.weight.numpy().astype(np.float32)
|
||||
alpha_weight = block.ssm_alpha.weight.numpy().astype(np.float32)
|
||||
beta_weight = block.ssm_beta.weight.numpy().astype(np.float32)
|
||||
out_weight = block.ssm_out.weight.numpy().astype(np.float32)
|
||||
dt_bias = block.ssm_dt["bias"].numpy().astype(np.float32)
|
||||
ssm_a = block.ssm_a.numpy().astype(np.float32)
|
||||
attn_norm_weight = block.attn_norm.weight.numpy().astype(np.float32)
|
||||
ssm_norm_weight = block.ssm_norm.weight.numpy().astype(np.float32)
|
||||
outputs, conv_states, recurrent_states = [], [], []
|
||||
|
||||
for t in range(T):
|
||||
x_norm = self._rms_norm_np(x_np[:, t:t+1, :], attn_norm_weight, block.attn_norm.eps)
|
||||
x_half = x_norm.astype(np.float16)
|
||||
out_gate = self._linear_np(x_half, gate_weight).reshape(B, 1, block.num_v_heads, block.head_v_dim)
|
||||
beta = 1.0 / (1.0 + np.exp(-self._linear_np(x_half, beta_weight))).reshape(B, block.num_v_heads, 1, 1)
|
||||
alpha = np.exp((self._softplus_np(self._linear_np(x_half, alpha_weight) + dt_bias)).reshape(B, block.num_v_heads, 1, 1) *
|
||||
ssm_a.reshape(1, block.num_v_heads, 1, 1))
|
||||
conv_window = np.concatenate([conv_state, self._linear_np(x_half, qkv_weight)], axis=1)
|
||||
conv_out = self._silu_np((conv_window * conv_weight).sum(axis=1))
|
||||
q, k, v = np.split(conv_out, [block.q_dim, 2 * block.q_dim], axis=-1)
|
||||
q = self._normalize_np(q.reshape(B, block.num_k_heads, block.head_k_dim))
|
||||
k = self._normalize_np(k.reshape(B, block.num_k_heads, block.head_k_dim))
|
||||
v = v.reshape(B, block.num_v_heads, block.head_v_dim)
|
||||
if block.num_v_heads != block.num_k_heads:
|
||||
k_repeat = block.num_v_heads // block.num_k_heads
|
||||
q = np.repeat(q[:, None, :, :], k_repeat, axis=1).reshape(B, block.num_v_heads, block.head_k_dim)
|
||||
k = np.repeat(k[:, None, :, :], k_repeat, axis=1).reshape(B, block.num_v_heads, block.head_k_dim)
|
||||
q, k, v = (q * (block.head_k_dim ** -0.5))[..., None], k[..., None], v[..., None]
|
||||
recurrent_state = recurrent_state * alpha
|
||||
recurrent_state = recurrent_state + np.matmul((v - np.matmul(recurrent_state, k)) * beta, np.swapaxes(k, -1, -2))
|
||||
core_attn_out = np.matmul(recurrent_state, q).squeeze(-1).reshape(B, 1, block.num_v_heads, block.head_v_dim)
|
||||
core_attn_out = self._rms_norm_np(core_attn_out, ssm_norm_weight, block.ssm_norm.eps)
|
||||
out = self._linear_np((core_attn_out * self._silu_np(out_gate)).reshape(B, 1, -1).astype(np.float16), out_weight)
|
||||
conv_state = conv_window[:, 1:, :]
|
||||
outputs.append(out)
|
||||
conv_states.append(conv_state.copy())
|
||||
recurrent_states.append(recurrent_state.copy())
|
||||
|
||||
return outputs, conv_states, recurrent_states
|
||||
|
||||
def test_gatedeltanet_reference_and_reset(self):
|
||||
config = self._make_config(max_context=3)
|
||||
block = self._make_block(config)
|
||||
x = Tensor.linspace(-1.0, 1.0, 3 * config.dim, dtype=dtypes.float32).reshape(1, 3, config.dim)
|
||||
|
||||
expected_outs, expected_conv, expected_recurrent = self._naive_attention(block, x)
|
||||
|
||||
for step in range(x.shape[1]):
|
||||
out = self._run_attention(block, x[:, step:step+1], step)
|
||||
conv_state, recurrent_state = self._cache_views(block)
|
||||
np.testing.assert_allclose(out, expected_outs[step], rtol=1e-3, atol=1e-3,
|
||||
err_msg=f"GatedDeltaNet output mismatch at step {step}")
|
||||
np.testing.assert_allclose(conv_state, expected_conv[step], rtol=1e-3, atol=1e-3,
|
||||
err_msg=f"GatedDeltaNet conv cache mismatch at step {step}")
|
||||
np.testing.assert_allclose(recurrent_state, expected_recurrent[step], rtol=1e-3, atol=1e-3,
|
||||
err_msg=f"GatedDeltaNet recurrent cache mismatch at step {step}")
|
||||
|
||||
warmup = Tensor.linspace(-0.5, 0.5, 2 * config.dim, dtype=dtypes.float32).reshape(1, 2, config.dim)
|
||||
prompt = Tensor.linspace(0.75, -0.75, 2 * config.dim, dtype=dtypes.float32).reshape(1, 2, config.dim)
|
||||
|
||||
for i in range(warmup.shape[1]): self._run_attention(block, warmup[:, i:i+1], i)
|
||||
Tensor.realize(*block._state_reset_ops())
|
||||
expected_outs, expected_conv, expected_recurrent = self._naive_attention(block, prompt)
|
||||
|
||||
for step in range(prompt.shape[1]):
|
||||
out = self._run_attention(block, prompt[:, step:step+1], step)
|
||||
conv_state, recurrent_state = self._cache_views(block)
|
||||
np.testing.assert_allclose(out, expected_outs[step], rtol=1e-3, atol=1e-3,
|
||||
err_msg=f"GatedDeltaNet reset output mismatch at step {step}")
|
||||
np.testing.assert_allclose(conv_state, expected_conv[step], rtol=1e-3, atol=1e-3,
|
||||
err_msg=f"GatedDeltaNet reset conv cache mismatch at step {step}")
|
||||
np.testing.assert_allclose(recurrent_state, expected_recurrent[step], rtol=1e-3, atol=1e-3,
|
||||
err_msg=f"GatedDeltaNet reset recurrent cache mismatch at step {step}")
|
||||
|
||||
class TestPairwiseTopk(unittest.TestCase):
|
||||
def test_basic_topk(self):
|
||||
x = Tensor([[[1.0, 3.0, 2.0, 5.0, 4.0]]])
|
||||
|
||||
@@ -418,8 +418,8 @@ class TestFunctionTuple(unittest.TestCase):
|
||||
|
||||
def test_custom_kernel_save_unused_output(self):
|
||||
def my_kernel(C:UOp, D:UOp, A:UOp) -> UOp:
|
||||
i = UOp.range(A.shape[0], 0)
|
||||
j = UOp.range(D.shape[0], 1)
|
||||
i = UOp.range(A.size, 0)
|
||||
j = UOp.range(D.size, 1)
|
||||
store_c = C[i].store(A[i] * 2.0).end(i)
|
||||
store_d = D[j].store(A[j]).end(j)
|
||||
return UOp.group(store_c, store_d).sink(arg=KernelInfo(name="my_kernel"))
|
||||
@@ -444,7 +444,7 @@ class TestFunctionTuple(unittest.TestCase):
|
||||
|
||||
def test_custom_kernel_both_outputs_used(self):
|
||||
def my_kernel(C:UOp, D:UOp, A:UOp) -> UOp:
|
||||
i = UOp.range(A.shape[0], 0)
|
||||
i = UOp.range(A.size, 0)
|
||||
store_c = C[i].store(A[i] * 2.0)
|
||||
store_d = D[i].store(A[i] * 3.0)
|
||||
return UOp.group(store_c, store_d).end(i).sink(arg=KernelInfo(name="my_kernel"))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
from tinygrad import Tensor, UOp
|
||||
from tinygrad.schedule import schedule_cache
|
||||
from tinygrad.engine.schedule import schedule_cache
|
||||
from tinygrad.apps.llm import Transformer, TransformerConfig
|
||||
|
||||
TEST_CONFIG = TransformerConfig(num_blocks=1, dim=64, hidden_dim=128, n_heads=2, n_kv_heads=2,
|
||||
|
||||
@@ -2,7 +2,7 @@ import unittest
|
||||
import functools
|
||||
from tinygrad import Tensor, Variable, UOp
|
||||
from tinygrad.uop.ops import KernelInfo
|
||||
from tinygrad.schedule import schedule_cache
|
||||
from tinygrad.engine.schedule import schedule_cache
|
||||
|
||||
def custom_set0_kernel(A:UOp, num:int) -> UOp:
|
||||
return A[0].set(num).sink(arg=KernelInfo(f"custom_set0_{num}"))
|
||||
|
||||
+253
-71
@@ -9,7 +9,7 @@ from tinygrad.viz.serve import TCPServerWithReuse, HTTPRequestHandler
|
||||
class SimpleTokenizer:
|
||||
def __init__(self, normal_tokens:dict[str, int], special_tokens:dict[str, int], preset:str="llama3"):
|
||||
preset = {"qwen35":"qwen2","qwen35moe":"qwen2"}.get(preset, preset)
|
||||
if preset not in ("llama3","llama-v3","llama-bpe","qwen2","olmo","kimi-k2","tekken"): raise ValueError(f"Invalid tokenizer preset '{preset}'")
|
||||
if preset not in ("llama3","llama-v3","llama-bpe","qwen2","olmo","kimi-k2","gemma4"): raise ValueError(f"Invalid tokenizer preset '{preset}'")
|
||||
# https://github.com/openai/gpt-2/blob/9b63575ef42771a015060c964af2c3da4cf7c8ab/src/encoder.py#L9
|
||||
bs = [*range(33, 127), *range(161, 173), *range(174, 256)] # bytes that map to themselves
|
||||
self._byte_decoder = {chr(b): b for b in bs} | {chr(256+i): b for i,b in enumerate(b for b in range(256) if b not in bs)}
|
||||
@@ -22,9 +22,11 @@ class SimpleTokenizer:
|
||||
f"[^\\r\\n{r_p_N}{r_p_L}]?[{r_p_L}]+|[{r_p_N}]{{1,3}}| ?[^{r_ws}{r_p_N}{r_p_L}]+[\\r\\n]*|[{r_ws}]*[\\r\\n]+|[{r_ws}]+(?![^{r_ws}])|[{r_ws}]+")
|
||||
self._split_to_sentence = re.compile("|".join(re.escape(tok) for tok in special_tokens.keys()) if special_tokens else r"(?!)")
|
||||
|
||||
self._normal_tokens = {bytes(self._byte_decoder[c] for c in tok): tid for tok, tid in normal_tokens.items()}
|
||||
tok_bytes = (lambda tok: tok.replace("▁", " ").encode()) if preset == "gemma4" else (lambda tok: bytes(self._byte_decoder[c] for c in tok))
|
||||
self._normal_tokens = {tok_bytes(tok): tid for tok, tid in normal_tokens.items()}
|
||||
self._special_tokens = special_tokens
|
||||
self._tok2bytes = {tid: tok for tok, tid in self._normal_tokens.items()} | {tid: tok.encode() for tok, tid in self._special_tokens.items()}
|
||||
self._tok2bytes = {tid: tok for tok, tid in self._normal_tokens.items()} | {
|
||||
tid: (b'' if preset == "gemma4" else tok.encode()) for tok, tid in self._special_tokens.items()}
|
||||
self.preset = preset
|
||||
|
||||
@staticmethod
|
||||
@@ -32,7 +34,9 @@ class SimpleTokenizer:
|
||||
# https://github.com/ggml-org/llama.cpp/blob/94933c8c2eeaa9a7983e3f6c08af76bd86724094/src/llama-vocab.cpp#L1818-L1820
|
||||
vocab: typing.Iterable[tuple[str, int]] = ((tok, idx) for idx, tok in enumerate(kv["tokenizer.ggml.tokens"]))
|
||||
normal_tokens, special_tokens = partition(vocab, lambda e: kv["tokenizer.ggml.token_type"][e[1]] == 1)
|
||||
return SimpleTokenizer(dict(normal_tokens), dict(special_tokens), kv["tokenizer.ggml.pre"])
|
||||
return SimpleTokenizer(
|
||||
dict(normal_tokens), dict(special_tokens),
|
||||
kv.get("tokenizer.ggml.pre") or kv.get("tokenizer.ggml.model", "llama3"))
|
||||
|
||||
def _encode_word(self, word:bytes) -> list[int]:
|
||||
if (early_token:=self._normal_tokens.get(word)) is not None: return [early_token]
|
||||
@@ -63,16 +67,13 @@ class SimpleTokenizer:
|
||||
if self.preset == 'olmo': return self.encode("<|" + role + "|>\n") # OLMoE Instruct format
|
||||
if self.preset == 'kimi-k2': return self.encode("<|im_" + role + "|>" + role + "<|im_middle|>")
|
||||
if self.preset == 'qwen2': return self.encode("<|im_start|>" + role + "\n")
|
||||
if self.preset == 'tekken':
|
||||
if role == 'user': return self.encode("[INST]")
|
||||
if role == 'assistant': return []
|
||||
raise ValueError(f"Unsupported role '{role}' for tokenizer preset '{self.preset}'")
|
||||
if self.preset == 'gemma4': return self.encode("<|turn>" + ("model" if role == "assistant" else role) + "\n")
|
||||
return self.encode("<|start_header_id|>" + role + "<|end_header_id|>\n\n")
|
||||
def end_turn(self, eos_id:int):
|
||||
if self.preset == 'olmo': return self.encode("\n")
|
||||
if self.preset == 'kimi-k2': return [eos_id]
|
||||
if self.preset == 'qwen2': return [eos_id] + self.encode("\n")
|
||||
if self.preset == 'tekken': return self.encode("[/INST]")
|
||||
if self.preset == 'gemma4': return self.encode("<turn|>\n")
|
||||
return [eos_id]
|
||||
|
||||
@functools.cache
|
||||
@@ -95,6 +96,27 @@ def apply_rope(x:Tensor, freqs_cis:Tensor) -> Tensor:
|
||||
x1, x2 = x.chunk(2, dim=-1)
|
||||
return (x1 * cos - x2 * sin).cat(x2 * cos + x1 * sin, dim=-1)
|
||||
|
||||
class ScaledLinear:
|
||||
def __init__(self, in_features:int, out_features:int):
|
||||
self.weight = Tensor.zeros(out_features, in_features)
|
||||
self.scale = Tensor.ones(in_features)
|
||||
def __call__(self, x:Tensor) -> Tensor: return (x * self.scale) @ self.weight.transpose(-1, -2)
|
||||
|
||||
class ScaledExpertWeights(ExpertWeights):
|
||||
def __init__(self, num_experts:int, in_features:int, out_features:int):
|
||||
super().__init__(num_experts, in_features, out_features)
|
||||
self.scale = Tensor.ones(num_experts)
|
||||
|
||||
class ScalarWeight:
|
||||
def __init__(self): self.weight = Tensor.ones(1)
|
||||
|
||||
def rms_norm_no_weight(x:Tensor, eps:float) -> Tensor:
|
||||
return x * (x.square().mean(axis=-1, keepdim=True) + eps).rsqrt()
|
||||
|
||||
def repeat_kv(x:Tensor, n_rep:int) -> Tensor:
|
||||
return x if n_rep == 1 else x.unsqueeze(2).expand(
|
||||
x.shape[0], x.shape[1], n_rep, x.shape[2], x.shape[3]).reshape(x.shape[0], x.shape[1] * n_rep, x.shape[2], x.shape[3])
|
||||
|
||||
def pairwise_topk(x: Tensor, k: int) -> tuple[Tensor, Tensor]:
|
||||
n = x.shape[-1]
|
||||
vals = Tensor.arange(n).reshape(1,1,n).cast(x.dtype).expand(x.shape)
|
||||
@@ -115,17 +137,17 @@ class SSMConfig:
|
||||
class TransformerConfig:
|
||||
num_blocks: int
|
||||
dim: int
|
||||
hidden_dim: int
|
||||
hidden_dim: int|tuple[int, ...]
|
||||
n_heads: int
|
||||
n_kv_heads: int
|
||||
n_kv_heads: int|tuple[int, ...]
|
||||
norm_eps: float
|
||||
vocab_size: int
|
||||
head_dim: int
|
||||
rope_theta: float
|
||||
head_dim: int|tuple[int, ...]
|
||||
rope_theta: float|tuple[float, ...]
|
||||
rope_dim: int
|
||||
v_head_dim: int
|
||||
max_context: int = 0
|
||||
qk_norm: int = 0
|
||||
qk_norm: int|tuple[int, ...] = 0
|
||||
num_experts: int = 0
|
||||
num_experts_per_tok: int = 0
|
||||
norm_topk_prob: bool = False
|
||||
@@ -138,36 +160,66 @@ class TransformerConfig:
|
||||
leading_dense_blocks: int = 0
|
||||
dense_hidden_dim: int = 0
|
||||
routed_scaling_factor: float = 1.0
|
||||
sliding_window: int = 0
|
||||
sliding_window_pattern: tuple[bool, ...] = ()
|
||||
per_layer_input_dim: int = 0
|
||||
final_logit_softcap: float = 0.0
|
||||
num_kv_shared_layers: int = 0
|
||||
gemma4: bool = False
|
||||
expert_hidden_dim: int = 0
|
||||
|
||||
class FFNBlock:
|
||||
def __init__(self, config:TransformerConfig):
|
||||
self.config = config
|
||||
self.hidden_dim = config.hidden_dim
|
||||
gemma_moe = config.gemma4 and config.num_experts > 0
|
||||
|
||||
# --- RMSNorms --------------------------------------------------------
|
||||
self.attn_norm = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
self.ffn_norm = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
|
||||
# --- feed-forward (MoE or dense) -------------------------------------
|
||||
if config.num_experts > 0:
|
||||
self.ffn_gate_inp: nn.Linear|ScaledLinear
|
||||
self.ffn_down_exps: ExpertWeights|ScaledExpertWeights
|
||||
if gemma_moe or config.num_experts == 0:
|
||||
self.ffn_gate = nn.Linear(config.dim, self.hidden_dim, bias=False)
|
||||
self.ffn_up = nn.Linear(config.dim, self.hidden_dim, bias=False)
|
||||
self.ffn_down = nn.Linear(self.hidden_dim, config.dim, bias=False)
|
||||
if gemma_moe:
|
||||
self.ffn_gate_inp = ScaledLinear(config.dim, config.num_experts)
|
||||
self.ffn_gate_up_exps = ExpertWeights(config.num_experts, config.dim, config.expert_hidden_dim * 2)
|
||||
self.ffn_down_exps = ScaledExpertWeights(config.num_experts, config.expert_hidden_dim, config.dim)
|
||||
self.post_ffw_norm_1 = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
self.pre_ffw_norm_2 = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
self.post_ffw_norm_2 = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
elif config.num_experts > 0:
|
||||
self.ffn_gate_inp = nn.Linear(config.dim, config.num_experts, bias=False) # router
|
||||
if config.kv_lora_rank > 0: self.exp_probs_b = {"bias": Tensor.zeros(config.num_experts)}
|
||||
self.ffn_gate_exps = ExpertWeights(config.num_experts, config.dim, config.hidden_dim)
|
||||
self.ffn_up_exps = ExpertWeights(config.num_experts, config.dim, config.hidden_dim)
|
||||
self.ffn_down_exps = ExpertWeights(config.num_experts, config.hidden_dim, config.dim)
|
||||
self.ffn_gate_exps = ExpertWeights(config.num_experts, config.dim, self.hidden_dim)
|
||||
self.ffn_up_exps = ExpertWeights(config.num_experts, config.dim, self.hidden_dim)
|
||||
self.ffn_down_exps = ExpertWeights(config.num_experts, self.hidden_dim, config.dim)
|
||||
if config.shared_expert_dim > 0:
|
||||
self.ffn_gate_shexp = nn.Linear(config.dim, config.shared_expert_dim, bias=False)
|
||||
self.ffn_up_shexp = nn.Linear(config.dim, config.shared_expert_dim, bias=False)
|
||||
self.ffn_down_shexp = nn.Linear(config.shared_expert_dim, config.dim, bias=False)
|
||||
if config.shared_expert_gate: self.ffn_gate_inp_shexp = {"weight": Tensor.zeros(config.dim)}
|
||||
else:
|
||||
self.ffn_gate = nn.Linear(config.dim, config.hidden_dim, bias=False)
|
||||
self.ffn_up = nn.Linear(config.dim, config.hidden_dim, bias=False)
|
||||
self.ffn_down = nn.Linear(config.hidden_dim, config.dim, bias=False)
|
||||
|
||||
def _feed_forward(self, x:Tensor) -> Tensor:
|
||||
h_norm = self.ffn_norm(x) if self.config.gemma4 else x
|
||||
if self.config.gemma4 and self.config.num_experts > 0:
|
||||
ffn_gate_inp = typing.cast(ScaledLinear, self.ffn_gate_inp)
|
||||
ffn_down_exps = typing.cast(ScaledExpertWeights, self.ffn_down_exps)
|
||||
dense = self.post_ffw_norm_1(self.ffn_down((self.ffn_gate(h_norm).gelu().contiguous()) * self.ffn_up(h_norm)))
|
||||
router_probs = (
|
||||
rms_norm_no_weight(x, self.config.norm_eps) * (self.config.dim ** -0.5) * ffn_gate_inp.scale
|
||||
) @ ffn_gate_inp.weight.transpose(-1, -2)
|
||||
vals, sel = pairwise_topk(router_probs.softmax(-1), self.config.num_experts_per_tok)
|
||||
probs = vals / vals.sum(axis=-1, keepdim=True) * ffn_down_exps.scale[sel]
|
||||
gate, up = self.ffn_gate_up_exps(sel, self.pre_ffw_norm_2(x).unsqueeze(2)).chunk(2, dim=-1)
|
||||
return dense + self.post_ffw_norm_2((ffn_down_exps(sel, gate.gelu().contiguous() * up) * probs.unsqueeze(-1)).sum(axis=2))
|
||||
if hasattr(self, 'ffn_gate_exps'):
|
||||
h = x.unsqueeze(2) # (B, T, 1, D) - add expert dim for broadcasting
|
||||
logits = self.ffn_gate_inp(x)
|
||||
h = h_norm.unsqueeze(2) # (B, T, 1, D) - add expert dim for broadcasting
|
||||
logits = self.ffn_gate_inp(h_norm)
|
||||
if hasattr(self, 'exp_probs_b'):
|
||||
probs = logits.sigmoid()
|
||||
_, sel = pairwise_topk(probs + self.exp_probs_b["bias"], self.config.num_experts_per_tok)
|
||||
@@ -180,12 +232,13 @@ class FFNBlock:
|
||||
x_down = self.ffn_down_exps(sel, self.ffn_gate_exps(sel, h).silu() * self.ffn_up_exps(sel, h)) # (B, T, k, D)
|
||||
out = (x_down * probs.unsqueeze(-1)).sum(axis=2) # (B, T, D)
|
||||
if hasattr(self, 'ffn_gate_shexp'):
|
||||
shexp = self.ffn_down_shexp(self.ffn_gate_shexp(x).silu().contiguous() * self.ffn_up_shexp(x))
|
||||
if hasattr(self, 'ffn_gate_inp_shexp'): shexp = shexp * (x * self.ffn_gate_inp_shexp["weight"]).sum(axis=-1, keepdim=True).sigmoid()
|
||||
shexp = self.ffn_down_shexp(self.ffn_gate_shexp(h_norm).silu().contiguous() * self.ffn_up_shexp(h_norm))
|
||||
if hasattr(self, 'ffn_gate_inp_shexp'): shexp = shexp * (h_norm * self.ffn_gate_inp_shexp["weight"]).sum(axis=-1, keepdim=True).sigmoid()
|
||||
out = out + shexp
|
||||
return out
|
||||
# TODO: remove the need for this contiguous
|
||||
return self.ffn_down(self.ffn_gate(x).silu().contiguous() * self.ffn_up(x))
|
||||
act = self.ffn_gate(h_norm).gelu() if self.config.gemma4 else self.ffn_gate(h_norm).silu()
|
||||
return self.ffn_down(act.contiguous() * self.ffn_up(h_norm))
|
||||
|
||||
# given the token-prefix match, return how much cached state this block can still reuse
|
||||
def _reusable_prefix_len(self, prefix_len:int, cached_len:int) -> int: return prefix_len
|
||||
@@ -206,29 +259,78 @@ class FFNBlock:
|
||||
class TransformerBlock(FFNBlock):
|
||||
def __init__(self, config:TransformerConfig):
|
||||
super().__init__(config)
|
||||
assert config.v_head_dim == config.head_dim, "TransformerBlock requires v_head_dim == head_dim"
|
||||
self.head_dim = config.head_dim
|
||||
self.rope_theta = config.rope_theta
|
||||
self.qk_norm = config.qk_norm
|
||||
self.n_kv_heads = config.n_kv_heads
|
||||
self.is_sliding = config.sliding_window > 0 and bool(config.sliding_window_pattern) and config.sliding_window_pattern[0]
|
||||
self.use_alternative_attention = config.gemma4 and config.num_experts > 0 and not self.is_sliding
|
||||
self.store_full_length_kv = False
|
||||
self.shared_kv_src_idx: int|None = None
|
||||
self.full_kv_cache: Tensor|None = None
|
||||
if not config.gemma4: assert config.v_head_dim == self.head_dim, "TransformerBlock requires v_head_dim == head_dim"
|
||||
|
||||
# --- attention projections (all linear, bias-free) ------------------
|
||||
q_proj_out = config.head_dim * config.n_heads * (2 if config.attn_output_gate else 1)
|
||||
kv_proj_out = config.head_dim * config.n_kv_heads
|
||||
q_proj_out = self.head_dim * config.n_heads * (2 if config.attn_output_gate else 1)
|
||||
kv_proj_out = self.head_dim * self.n_kv_heads
|
||||
self.attn_q = nn.Linear(config.dim, q_proj_out, bias=False)
|
||||
self.attn_k = nn.Linear(config.dim, kv_proj_out, bias=False)
|
||||
self.attn_v = nn.Linear(config.dim, kv_proj_out, bias=False)
|
||||
self.attn_output = nn.Linear(config.head_dim * config.n_heads, config.dim, bias=False)
|
||||
if config.qk_norm: self.attn_q_norm, self.attn_k_norm = nn.RMSNorm(config.qk_norm, config.norm_eps), nn.RMSNorm(config.qk_norm, config.norm_eps)
|
||||
if not self.use_alternative_attention: self.attn_v = nn.Linear(config.dim, kv_proj_out, bias=False)
|
||||
self.attn_output = nn.Linear(self.head_dim * config.n_heads, config.dim, bias=False)
|
||||
if self.qk_norm: self.attn_q_norm, self.attn_k_norm = nn.RMSNorm(self.qk_norm, config.norm_eps), nn.RMSNorm(self.qk_norm, config.norm_eps)
|
||||
if config.gemma4:
|
||||
self.post_attention_norm = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
self.post_ffw_norm = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
self.layer_output_scale = ScalarWeight()
|
||||
if config.per_layer_input_dim:
|
||||
self.inp_gate = nn.Linear(config.dim, config.per_layer_input_dim, bias=False)
|
||||
self.proj = nn.Linear(config.per_layer_input_dim, config.dim, bias=False)
|
||||
self.post_norm = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
|
||||
def _attention(self, x:Tensor, start_pos:int|UOp, shared_kv_cache:Tensor|None=None) -> Tensor:
|
||||
if self.config.gemma4:
|
||||
x_norm = self.attn_norm(x)
|
||||
q, k = self.attn_q(x_norm), self.attn_k(x_norm)
|
||||
if self.qk_norm and self.qk_norm != self.head_dim: q, k = self.attn_q_norm(q), self.attn_k_norm(k)
|
||||
|
||||
B, T, _ = x.shape
|
||||
q = q.reshape(B, T, self.config.n_heads, self.head_dim).transpose(1, 2)
|
||||
if self.qk_norm == self.head_dim: q = self.attn_q_norm(q)
|
||||
q = apply_rope(q, self.freqs_cis[start_pos:start_pos+T])
|
||||
if shared_kv_cache is not None:
|
||||
k = shared_kv_cache[0, :, :, 0:start_pos+T, :]
|
||||
v = shared_kv_cache[1, :, :, 0:start_pos+T, :]
|
||||
else:
|
||||
raw_k = k.reshape(B, T, self.n_kv_heads, self.head_dim)
|
||||
k = raw_k.transpose(1, 2)
|
||||
if self.qk_norm == self.head_dim: k = self.attn_k_norm(k)
|
||||
raw_v = raw_k if self.use_alternative_attention else self.attn_v(x_norm).reshape(B, T, self.n_kv_heads, self.head_dim)
|
||||
v = rms_norm_no_weight(raw_v, self.config.norm_eps).transpose(1, 2)
|
||||
k = apply_rope(k, self.freqs_cis[start_pos:start_pos+T])
|
||||
assigned_kv = Tensor(self.cache_kv.uop.after(self.cache_kv[:, :, :, start_pos:start_pos+T, :].uop.store(Tensor.stack(k, v).uop)))
|
||||
if self.store_full_length_kv: self.full_kv_cache = assigned_kv
|
||||
k = assigned_kv[0, :, :, 0:start_pos+T, :]
|
||||
v = assigned_kv[1, :, :, 0:start_pos+T, :]
|
||||
|
||||
mask = None
|
||||
if resolve(T != 1) or self.is_sliding:
|
||||
mask = Tensor.full((1, 1, T, start_pos+T), float("-inf"), dtype=x.dtype, device=x.device).triu(start_pos+1)
|
||||
if self.is_sliding:
|
||||
mask = mask + Tensor.full((1, 1, T, start_pos+T), float("-inf"), dtype=x.dtype, device=x.device).tril(start_pos-self.config.sliding_window)
|
||||
k, v = repeat_kv(k, self.config.n_heads // self.n_kv_heads), repeat_kv(v, self.config.n_heads // self.n_kv_heads)
|
||||
return self.attn_output((((q @ k.transpose(-1, -2)) + (mask if mask is not None else 0)).softmax(-1) @ v).transpose(1, 2).reshape(B, T, -1))
|
||||
|
||||
def _attention(self, x:Tensor, start_pos:int|UOp) -> Tensor:
|
||||
q, k, v = self.attn_q(x), self.attn_k(x), self.attn_v(x)
|
||||
if self.config.qk_norm and self.config.qk_norm != self.config.head_dim: q, k = self.attn_q_norm(q), self.attn_k_norm(k)
|
||||
if self.qk_norm and self.qk_norm != self.head_dim: q, k = self.attn_q_norm(q), self.attn_k_norm(k)
|
||||
|
||||
B, T, _ = x.shape
|
||||
if self.config.attn_output_gate:
|
||||
qg = q.reshape(B, T, self.config.n_heads, 2, self.config.head_dim)
|
||||
q, gate = qg[:, :, :, 0, :], qg[:, :, :, 1, :].reshape(B, T, self.config.n_heads * self.config.head_dim)
|
||||
q = q.reshape(B, T, self.config.n_heads, self.config.head_dim).transpose(1, 2) # (B,H,T,Hd)
|
||||
k = k.reshape(B, T, self.config.n_kv_heads, self.config.head_dim).transpose(1, 2) # (B,KvH,T,Hd)
|
||||
v = v.reshape(B, T, self.config.n_kv_heads, self.config.head_dim).transpose(1, 2) # (B,KvH,T,Hd)
|
||||
if self.config.qk_norm == self.config.head_dim: q, k = self.attn_q_norm(q), self.attn_k_norm(k)
|
||||
qg = q.reshape(B, T, self.config.n_heads, 2, self.head_dim)
|
||||
q, gate = qg[:, :, :, 0, :], qg[:, :, :, 1, :].reshape(B, T, self.config.n_heads * self.head_dim)
|
||||
q = q.reshape(B, T, self.config.n_heads, self.head_dim).transpose(1, 2) # (B,H,T,Hd)
|
||||
k = k.reshape(B, T, self.n_kv_heads, self.head_dim).transpose(1, 2) # (B,KvH,T,Hd)
|
||||
v = v.reshape(B, T, self.n_kv_heads, self.head_dim).transpose(1, 2) # (B,KvH,T,Hd)
|
||||
if self.qk_norm == self.head_dim: q, k = self.attn_q_norm(q), self.attn_k_norm(k)
|
||||
|
||||
q = apply_rope(q[..., :self.config.rope_dim], self.freqs_cis[start_pos:start_pos+T]).cat(q[..., self.config.rope_dim:], dim=-1)
|
||||
k = apply_rope(k[..., :self.config.rope_dim], self.freqs_cis[start_pos:start_pos+T]).cat(k[..., self.config.rope_dim:], dim=-1)
|
||||
@@ -252,8 +354,19 @@ class TransformerBlock(FFNBlock):
|
||||
def _init_state(self, x:Tensor):
|
||||
if not hasattr(self, "cache_kv"):
|
||||
# TODO: how is the dtype of this determined?
|
||||
self.cache_kv = Tensor.empty(2, x.shape[0], self.config.n_kv_heads, self.config.max_context, self.config.head_dim, device=x.device)
|
||||
self.freqs_cis = precompute_freqs_cis(self.config.rope_dim, self.config.max_context, self.config.rope_theta)
|
||||
self.cache_kv = Tensor.empty(2, x.shape[0], self.n_kv_heads, self.config.max_context, self.head_dim, device=x.device)
|
||||
self.freqs_cis = precompute_freqs_cis(self.head_dim if self.config.gemma4 else self.config.rope_dim, self.config.max_context, self.rope_theta)
|
||||
|
||||
def __call__(self, x: Tensor, start_pos: int|UOp, per_layer_input:Tensor|None=None, shared_kv_cache:Tensor|None=None):
|
||||
if not self.config.gemma4: return super().__call__(x, start_pos)
|
||||
self._init_state(x)
|
||||
@function(precompile=True, allow_implicit=True)
|
||||
def _run(x:Tensor, start_pos:int|UOp, per_layer_input:Tensor|None=None, shared_kv_cache:Tensor|None=None):
|
||||
h = x + self.post_attention_norm(self._attention(x, start_pos, shared_kv_cache))
|
||||
h = h + self.post_ffw_norm(self._feed_forward(h))
|
||||
if per_layer_input is not None: h = h + self.post_norm(self.proj(self.inp_gate(h).gelu() * per_layer_input))
|
||||
return (h * self.layer_output_scale.weight).contiguous()
|
||||
return _run(x, start_pos, per_layer_input, shared_kv_cache)
|
||||
|
||||
class MLATransformerBlock(FFNBlock):
|
||||
def __init__(self, config:TransformerConfig):
|
||||
@@ -301,7 +414,6 @@ class GatedDeltaNetBlock(FFNBlock):
|
||||
def __init__(self, config:TransformerConfig, ssm:SSMConfig):
|
||||
super().__init__(config)
|
||||
self.head_k_dim, self.num_k_heads, self.num_v_heads = ssm.state_size, ssm.group_count, ssm.time_step_rank
|
||||
assert self.num_v_heads % self.num_k_heads == 0
|
||||
self.head_v_dim, self.ssm_conv_kernel = ssm.inner_size // ssm.time_step_rank, ssm.conv_kernel
|
||||
self.conv_channels, self.q_dim = ssm.inner_size + 2*ssm.group_count*ssm.state_size, ssm.state_size*ssm.group_count
|
||||
self.attn_qkv, self.attn_gate = nn.Linear(config.dim, self.conv_channels, bias=False), nn.Linear(config.dim, ssm.inner_size, bias=False)
|
||||
@@ -314,36 +426,29 @@ class GatedDeltaNetBlock(FFNBlock):
|
||||
def _attention(self, x:Tensor, start_pos:int|UOp) -> Tensor:
|
||||
B, T, _ = x.shape
|
||||
assert T == 1, "GatedDeltaNetBlock currently only supports T=1"
|
||||
|
||||
# input processing
|
||||
x = x.half()
|
||||
out_gate = self.attn_gate(x).reshape(B, 1, self.num_v_heads, self.head_v_dim)
|
||||
beta = self.ssm_beta(x).sigmoid().reshape(B, self.num_v_heads, 1, 1)
|
||||
alpha = ((self.ssm_alpha(x).float() + self.ssm_dt["bias"]).softplus() * self.ssm_a).reshape(B, self.num_v_heads, 1, 1).exp()
|
||||
|
||||
# conv
|
||||
conv_flat = (self.ssm_conv_kernel - 1) * self.conv_channels
|
||||
ssm_flat = self.num_v_heads * self.head_v_dim * self.head_v_dim
|
||||
conv_state = self.delta_cache[:, :conv_flat].reshape(B, self.ssm_conv_kernel - 1, self.conv_channels)
|
||||
recurrent_state = self.delta_cache[:, conv_flat:conv_flat + ssm_flat].reshape(B, self.num_v_heads, self.head_v_dim, self.head_v_dim)
|
||||
conv_window = conv_state.cat(self.attn_qkv(x), dim=1)
|
||||
conv_out = (conv_window * self.ssm_conv1d["weight"].T.unsqueeze(0)).sum(1).silu()
|
||||
|
||||
# qkv
|
||||
q, k, v = conv_out.split([self.q_dim, self.q_dim, self.conv_channels - 2*self.q_dim], dim=-1)
|
||||
q = q.reshape(B, self.num_k_heads, self.head_k_dim).normalize(dim=-1).repeat(1, self.num_v_heads//self.num_k_heads, 1)
|
||||
k = k.reshape(B, self.num_k_heads, self.head_k_dim).normalize(dim=-1).repeat(1, self.num_v_heads//self.num_k_heads, 1)
|
||||
q, k = q.reshape(B, self.num_k_heads, self.head_k_dim).normalize(dim=-1), k.reshape(B, self.num_k_heads, self.head_k_dim).normalize(dim=-1)
|
||||
v = v.reshape(B, self.num_v_heads, self.head_v_dim)
|
||||
q, k, v = q.mul(self.head_k_dim**-0.5).unsqueeze(-1), k.unsqueeze(-1), v.unsqueeze(-1)
|
||||
|
||||
# recurrent
|
||||
ssm_flat = self.num_v_heads * self.head_v_dim * self.head_v_dim
|
||||
recurrent_state = self.delta_cache[:, conv_flat:conv_flat + ssm_flat].reshape(B, self.num_v_heads, self.head_v_dim, self.head_v_dim)
|
||||
if self.num_v_heads != self.num_k_heads:
|
||||
k_repeat = self.num_v_heads // self.num_k_heads
|
||||
q = q.unsqueeze(1).expand(B, k_repeat, self.num_k_heads, self.head_k_dim).reshape(B, self.num_v_heads, self.head_k_dim)
|
||||
k = k.unsqueeze(1).expand(B, k_repeat, self.num_k_heads, self.head_k_dim).reshape(B, self.num_v_heads, self.head_k_dim)
|
||||
q, k, v = (q * self.head_k_dim**-0.5).unsqueeze(-1), k.unsqueeze(-1), v.unsqueeze(-1)
|
||||
recurrent_state = recurrent_state * alpha
|
||||
recurrent_state = recurrent_state + ((v - recurrent_state@k) * beta)@k.transpose(-1, -2)
|
||||
new_cache = conv_window[:, 1:, :].reshape(B, -1).cat(recurrent_state.reshape(B, -1), dim=-1).contiguous()
|
||||
assigned = self.delta_cache.uop.after(self.delta_cache.uop.store(new_cache.cast(self.delta_cache.dtype).uop))
|
||||
cache_tensor = Tensor(assigned, device=self.delta_cache.device)
|
||||
|
||||
# final
|
||||
final_state = cache_tensor[:, conv_flat:conv_flat + ssm_flat].reshape(B, self.num_v_heads, self.head_v_dim, self.head_v_dim)
|
||||
core_attn_out = self.ssm_norm((final_state@q).squeeze(-1).reshape(B, 1, self.num_v_heads, self.head_v_dim))
|
||||
return self.ssm_out((core_attn_out * out_gate.silu()).reshape(B, 1, -1).cast(x.dtype))
|
||||
@@ -360,15 +465,48 @@ class GatedDeltaNetBlock(FFNBlock):
|
||||
|
||||
class Transformer:
|
||||
def __init__(self, config:TransformerConfig):
|
||||
dense_config = replace(config, num_experts=0, num_experts_per_tok=0, shared_expert_dim=0, hidden_dim=config.dense_hidden_dim or config.hidden_dim)
|
||||
if config.ssm: config = replace(config, qk_norm=config.head_dim)
|
||||
block_cls = MLATransformerBlock if config.kv_lora_rank > 0 else TransformerBlock
|
||||
self.blk:list[FFNBlock] = [GatedDeltaNetBlock(config, config.ssm) if config.ssm and (i+1) % config.full_attention_interval != 0 else
|
||||
block_cls(dense_config if i < config.leading_dense_blocks else config) for i in range(config.num_blocks)]
|
||||
self.config = config
|
||||
def layer_config(i:int) -> TransformerConfig:
|
||||
return replace(
|
||||
config,
|
||||
hidden_dim=config.hidden_dim[i] if isinstance(config.hidden_dim, tuple) else config.hidden_dim,
|
||||
n_kv_heads=config.n_kv_heads[i] if isinstance(config.n_kv_heads, tuple) else config.n_kv_heads,
|
||||
head_dim=config.head_dim[i] if isinstance(config.head_dim, tuple) else config.head_dim,
|
||||
rope_theta=config.rope_theta[i] if isinstance(config.rope_theta, tuple) else config.rope_theta,
|
||||
qk_norm=config.qk_norm[i] if isinstance(config.qk_norm, tuple) else config.qk_norm,
|
||||
sliding_window_pattern=(config.sliding_window_pattern[i],) if config.sliding_window_pattern else ())
|
||||
if config.gemma4:
|
||||
self.blk = [TransformerBlock(layer_config(i)) for i in range(config.num_blocks)]
|
||||
else:
|
||||
dense_config = replace(
|
||||
config, num_experts=0, num_experts_per_tok=0, shared_expert_dim=0,
|
||||
hidden_dim=config.dense_hidden_dim or config.hidden_dim)
|
||||
block_cls = MLATransformerBlock if config.kv_lora_rank > 0 else TransformerBlock
|
||||
self.blk:list[FFNBlock] = [GatedDeltaNetBlock(config, config.ssm) if config.ssm and (i+1) % config.full_attention_interval != 0 else
|
||||
block_cls(dense_config if i < config.leading_dense_blocks else config) for i in range(config.num_blocks)]
|
||||
self.token_embd = nn.Embedding(config.vocab_size, config.dim)
|
||||
self.output_norm = nn.RMSNorm(config.dim, config.norm_eps)
|
||||
self.output = nn.Linear(config.dim, config.vocab_size, bias=False)
|
||||
if config.per_layer_input_dim:
|
||||
self.per_layer_model_proj = nn.Linear(config.dim, config.num_blocks * config.per_layer_input_dim, bias=False)
|
||||
self.per_layer_proj_norm = nn.RMSNorm(config.per_layer_input_dim, config.norm_eps)
|
||||
self.per_layer_token_embd = nn.Embedding(config.vocab_size, config.num_blocks * config.per_layer_input_dim)
|
||||
self.max_context = config.max_context
|
||||
self.embed_scale = config.dim ** 0.5 if config.gemma4 else 1.0
|
||||
self.per_layer_embed_scale = config.per_layer_input_dim ** 0.5 if config.per_layer_input_dim else 1.0
|
||||
self.per_layer_input_scale = 2 ** -0.5
|
||||
self.per_layer_model_projection_scale = config.dim ** -0.5 if config.gemma4 else 1.0
|
||||
self.final_logit_softcap = config.final_logit_softcap
|
||||
if config.num_kv_shared_layers:
|
||||
first_shared = config.num_blocks - config.num_kv_shared_layers
|
||||
last_of_type = {
|
||||
False: max(i for i in range(first_shared) if not config.sliding_window_pattern[i]),
|
||||
True: max(i for i in range(first_shared) if config.sliding_window_pattern[i])}
|
||||
for idx, block in enumerate(self.blk[:first_shared]):
|
||||
if bool(config.sliding_window_pattern) and idx == last_of_type[config.sliding_window_pattern[idx]]: block.store_full_length_kv = True
|
||||
for idx, block in enumerate(self.blk[first_shared:], start=first_shared):
|
||||
block.shared_kv_src_idx = last_of_type[config.sliding_window_pattern[idx]]
|
||||
self.has_recurrent_block = any(isinstance(b, GatedDeltaNetBlock) for b in self.blk)
|
||||
self._cached_tokens: list[int] = []
|
||||
# we specialize the JIT for prefill and rollout
|
||||
@@ -376,9 +514,23 @@ class Transformer:
|
||||
self.rollout_jit = TinyJit(self.forward)
|
||||
|
||||
def forward(self, tokens:Tensor, start_pos:int|UOp, temperature:Tensor) -> Tensor:
|
||||
x = self.token_embd(tokens).float() # (B, T, D)
|
||||
for block in self.blk: x = block(x, start_pos)
|
||||
x = self.token_embd(tokens).float() * self.embed_scale # (B, T, D)
|
||||
if not self.config.gemma4:
|
||||
for block in self.blk: x = block(x, start_pos)
|
||||
else:
|
||||
per_layer_inputs = None
|
||||
if hasattr(self, 'per_layer_token_embd'):
|
||||
B, T, _ = x.shape
|
||||
per_layer_inputs = self.per_layer_proj_norm(
|
||||
(self.per_layer_model_proj(x) * self.per_layer_model_projection_scale).reshape(B, T, len(self.blk), -1))
|
||||
per_layer_inputs = (
|
||||
per_layer_inputs + self.per_layer_token_embd(tokens).float().reshape(B, T, len(self.blk), -1) * self.per_layer_embed_scale
|
||||
) * self.per_layer_input_scale
|
||||
for i, block in enumerate(self.blk):
|
||||
shared_kv_cache = self.blk[block.shared_kv_src_idx].full_kv_cache if block.shared_kv_src_idx is not None else None
|
||||
x = block(x, start_pos, None if per_layer_inputs is None else per_layer_inputs[:,:,i,:], shared_kv_cache)
|
||||
logits = self.output(self.output_norm(x))[:, -1, :]
|
||||
if self.final_logit_softcap: logits = (logits / self.final_logit_softcap).tanh() * self.final_logit_softcap
|
||||
# Gumbel-max trick: argmax(logits/temp - log(-log(uniform))) is equivalent to sampling from softmax(logits/temp)
|
||||
return (logits / temperature.maximum(1e-12) - (Tensor.rand_like(logits).maximum(1e-12).log().neg()).log()).argmax(-1, keepdim=True)
|
||||
|
||||
@@ -420,17 +572,36 @@ class Transformer:
|
||||
state_dict[name] = w.rearrange("n (h two) d -> n (two h) d", two=2).reshape(-1, w.shape[-1])
|
||||
elif kv_lora_rank and 'attn_kv_a_mqa.weight' in name:
|
||||
state_dict[name] = state_dict[name][:kv_lora_rank].cat(state_dict[name][kv_lora_rank:].rearrange("(h two) d -> (two h) d", two=2), dim=0)
|
||||
hidden_dim = kv[f'{arch}.feed_forward_length'] if arch == 'gemma4' else \
|
||||
kv.get(f'{arch}.expert_feed_forward_length', kv.get(f'{arch}.feed_forward_length', 0))
|
||||
if arch == 'gemma4' and isinstance(hidden_dim, list): hidden_dim = tuple(hidden_dim)
|
||||
if arch == 'gemma4':
|
||||
sliding_window_pattern = tuple(kv[f'{arch}.attention.sliding_window_pattern'])
|
||||
n_kv_heads = tuple(n_kv_heads) if isinstance(n_kv_heads, list) else n_kv_heads
|
||||
head_dim = tuple(
|
||||
kv[f'{arch}.attention.key_length_swa'] if is_sliding else kv[f'{arch}.attention.key_length']
|
||||
for is_sliding in sliding_window_pattern)
|
||||
rope_theta = tuple(
|
||||
kv.get(f'{arch}.rope.freq_base_swa', kv[f'{arch}.rope.freq_base']) if is_sliding else kv[f'{arch}.rope.freq_base']
|
||||
for is_sliding in sliding_window_pattern)
|
||||
else:
|
||||
sliding_window_pattern = ()
|
||||
rope_theta = kv[f'{arch}.rope.freq_base']
|
||||
|
||||
config = TransformerConfig(
|
||||
num_blocks=kv[f'{arch}.block_count'], dim=kv[f'{arch}.embedding_length'],
|
||||
hidden_dim=kv.get(f'{arch}.expert_feed_forward_length', kv.get(f'{arch}.feed_forward_length', 0)),
|
||||
hidden_dim=hidden_dim,
|
||||
n_heads=n_heads, n_kv_heads=n_kv_heads, norm_eps=kv[f'{arch}.attention.layer_norm_rms_epsilon'],
|
||||
vocab_size=len(kv['tokenizer.ggml.tokens']),
|
||||
head_dim=head_dim,
|
||||
rope_theta=kv[f'{arch}.rope.freq_base'],
|
||||
rope_theta=rope_theta,
|
||||
rope_dim=rope_dim,
|
||||
v_head_dim=kv.get(f'{arch}.attention.value_length_mla', kv.get(f'{arch}.attention.value_length', head_dim)),
|
||||
v_head_dim=kv.get(
|
||||
f'{arch}.attention.value_length_mla',
|
||||
kv.get(f'{arch}.attention.value_length', head_dim if isinstance(head_dim, int) else head_dim[0])),
|
||||
max_context=max_context,
|
||||
qk_norm=int(state_dict['blk.0.attn_q_norm.weight'].shape[0]) if 'blk.0.attn_q_norm.weight' in state_dict else 0,
|
||||
qk_norm=head_dim if arch == 'gemma4' else (
|
||||
int(state_dict['blk.0.attn_q_norm.weight'].shape[0]) if 'blk.0.attn_q_norm.weight' in state_dict else 0),
|
||||
num_experts=kv.get(f'{arch}.expert_count', 0), num_experts_per_tok=kv.get(f'{arch}.expert_used_count', 0),
|
||||
norm_topk_prob=kv.get(f'{arch}.expert_weights_norm', arch in ('qwen3moe', 'qwen35moe')),
|
||||
kv_lora_rank=kv_lora_rank,
|
||||
@@ -440,8 +611,17 @@ class Transformer:
|
||||
kv.get(f'{arch}.expert_shared_count', 0) * kv.get(f'{arch}.expert_feed_forward_length', 0)),
|
||||
shared_expert_gate=f"blk.{kv.get(f'{arch}.leading_dense_block_count', 0)}.ffn_gate_inp_shexp.weight" in state_dict,
|
||||
dense_hidden_dim=kv.get(f'{arch}.feed_forward_length', 0) if kv.get(f'{arch}.leading_dense_block_count', 0) else 0,
|
||||
routed_scaling_factor=kv.get(f'{arch}.expert_weights_scale', 1.0), attn_output_gate=arch in ('qwen35', 'qwen35moe'), ssm=ssm,
|
||||
full_attention_interval=kv.get(f'{arch}.full_attention_interval', 0))
|
||||
routed_scaling_factor=kv.get(f'{arch}.expert_weights_scale', 1.0),
|
||||
full_attention_interval=kv.get(f'{arch}.full_attention_interval', 0),
|
||||
attn_output_gate=arch in ('qwen35', 'qwen35moe'),
|
||||
ssm=ssm,
|
||||
sliding_window=kv.get(f'{arch}.attention.sliding_window', 0),
|
||||
sliding_window_pattern=sliding_window_pattern,
|
||||
per_layer_input_dim=kv.get(f'{arch}.embedding_length_per_layer_input', 0),
|
||||
final_logit_softcap=kv.get(f'{arch}.final_logit_softcapping', 0.0),
|
||||
num_kv_shared_layers=kv.get(f'{arch}.attention.shared_kv_layers', 0),
|
||||
gemma4=arch == 'gemma4',
|
||||
expert_hidden_dim=kv.get(f'{arch}.expert_feed_forward_length', 0))
|
||||
model = Transformer(config)
|
||||
nn.state.load_state_dict(model, state_dict, verbose=False, consume=True, realize=False) # NOTE: rope_freqs.weight (32,) is unused
|
||||
# NOTE: without this contiguous, it unpacks the weights from the model every time. we shouldn't need this, but for now it's faster
|
||||
@@ -491,6 +671,8 @@ models = {
|
||||
"qwen3.5:9b": "https://huggingface.co/unsloth/Qwen3.5-9B-GGUF/resolve/main/Qwen3.5-9B-Q4_K_M.gguf",
|
||||
"qwen3.5:27b": "https://huggingface.co/unsloth/Qwen3.5-27B-GGUF/resolve/main/Qwen3.5-27B-Q4_K_M.gguf",
|
||||
"qwen3.5:35b-a3b": "https://huggingface.co/unsloth/Qwen3.5-35B-A3B-GGUF/resolve/main/Qwen3.5-35B-A3B-Q4_K_M.gguf",
|
||||
"gemma4:e2b-q4": "https://huggingface.co/unsloth/gemma-4-E2B-it-GGUF/resolve/main/gemma-4-E2B-it-Q4_K_M.gguf",
|
||||
"gemma4:26b-a4b-q4": "https://huggingface.co/unsloth/gemma-4-26B-A4B-it-GGUF/resolve/main/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf",
|
||||
"olmoe": "https://huggingface.co/allenai/OLMoE-1B-7B-0924-Instruct-GGUF/resolve/main/olmoe-1b-7b-0924-instruct-q4_k_m.gguf",
|
||||
"moonlight": "https://huggingface.co/gabriellarson/Moonlight-16B-A3B-Instruct-GGUF/resolve/main/Moonlight-16B-A3B-Instruct-Q4_K_M.gguf",
|
||||
}
|
||||
|
||||
+4
-3
@@ -5,7 +5,7 @@ from typing import Any, Generic, TypeVar, Iterator, Generator, TYPE_CHECKING
|
||||
import importlib, inspect, functools, pathlib, os, platform, contextlib, sys, re, atexit, pickle, decimal
|
||||
from tinygrad.helpers import BENCHMARKS, CI, OSX, LRU, getenv, diskcache_get, diskcache_put, DEBUG, GlobalCounters, flat_mv, PROFILE, temp, colored
|
||||
from tinygrad.helpers import Context, CCACHE, ALLOW_DEVICE_USAGE, MAX_BUFFER_SIZE, cpu_events, ProfileEvent, ProfilePointEvent, suppress_finalizing
|
||||
from tinygrad.helpers import select_by_name, select_first_inited, DEV, EMULATED_DTYPES, IMAGE, FLOAT16, TracingKey, size_to_str, Target
|
||||
from tinygrad.helpers import select_first_inited, DEV, EMULATED_DTYPES, IMAGE, FLOAT16, TracingKey, size_to_str, Target
|
||||
from tinygrad.dtype import DType, PtrDType, dtypes, _to_np_dtype
|
||||
if TYPE_CHECKING: from tinygrad.renderer import Renderer
|
||||
|
||||
@@ -292,8 +292,9 @@ class Compiled:
|
||||
assert (rn:=next((self._renderer_name(r) for r in self.renderers if getenv(f"{self.device}_{self._renderer_name(r)}")), None)) is None, \
|
||||
f"{self.device}_{rn}=1 is deprecated, use DEV={self.device}:{rn} or {self.device}_CC={rn} instead"
|
||||
t = DEV.target(self.device.split(':')[0], **({"arch":self.arch} if self.arch else {}))
|
||||
return select_first_inited(select_by_name(self.renderers, self._renderer_name, t.renderer, f"{self.device} has no renderer {t.renderer!r}"),
|
||||
f"No renderer for {self.device} is available", self.cached_renderer, target=t)
|
||||
renderers = [r for r in self.renderers if self._renderer_name(r) == t.renderer] if t.renderer else self.renderers
|
||||
assert renderers, f"No renderer for {self.device} " + (f"matches request {t.renderer!r}" if t.renderer else "is available")
|
||||
return select_first_inited(renderers, f"No renderer for {self.device} is available", self.cached_renderer, target=t)
|
||||
|
||||
def synchronize(self):
|
||||
"""
|
||||
|
||||
@@ -65,7 +65,7 @@ def _make_buffer_view(src:UOp) -> UOp|None:
|
||||
if (offset := src.contiguous_view_offset()) is None: return None
|
||||
buf = src.base
|
||||
if buf.op is Ops.BUFFER_VIEW: offset, buf = offset + buf.arg[1], buf.src[0]
|
||||
return UOp(Ops.BUFFER_VIEW, src.dtype, (buf,), (src.numel(), offset)).reshape(src.shape)
|
||||
return UOp(Ops.BUFFER_VIEW, src.dtype, (buf,), (src.size, offset)).reshape(src.shape)
|
||||
|
||||
def contiguous_mops_to_view(c:UOp, src:UOp):
|
||||
"""CONTIGUOUS(MOPS(BUFFER)) → CONTIGUOUS(BUFFER_VIEW) when movement ops collapse to a contiguous range."""
|
||||
@@ -94,13 +94,13 @@ def contiguous_mops_to_view(c:UOp, src:UOp):
|
||||
if (view := _make_buffer_view(src)) is None: return None
|
||||
return view.contiguous(tag=c.tag)
|
||||
|
||||
def transform_precompiled_function(c:UOp) -> UOp|None:
|
||||
def transform_precompiled_call(c:UOp) -> UOp|None:
|
||||
if not c.arg.precompile: return None
|
||||
if c.src[0].op is Ops.SINK: return None
|
||||
assert c.src[0].op is Ops.TUPLE, f"expected TUPLE body for precompiled function, got {c.src[0].op}"
|
||||
assert c.src[0].op is Ops.TUPLE, f"expected TUPLE body for precompiled call, got {c.src[0].op}"
|
||||
input_buffers = tuple(x.contiguous() if x.op not in {Ops.AFTER, Ops.BIND} else x for x in c.src[1:])
|
||||
|
||||
# add the outputs to the function
|
||||
# add the outputs to the call
|
||||
srcs = c.src[0].src
|
||||
resolved = [c.gettuple(i) for i in range(len(srcs))]
|
||||
outs = tuple(_buffer_like(r) for r in resolved)
|
||||
@@ -108,7 +108,7 @@ def transform_precompiled_function(c:UOp) -> UOp|None:
|
||||
fxn = UOp.sink(*[t.after(t.store(s)) for t,s in zip(targets, srcs)])
|
||||
|
||||
# create the new thing for the big graph
|
||||
new_call = c.replace(op=Ops.CALL, src=(fxn, *input_buffers, *outs), tag=None)
|
||||
new_call = c.replace(src=(fxn, *input_buffers, *outs), tag=None)
|
||||
rets = tuple(o.after(new_call) for o in outs)
|
||||
|
||||
# if the CALL has symbolic shapes, shrink the max-sized output to the actual symbolic shape
|
||||
@@ -119,8 +119,8 @@ def transform_precompiled_function(c:UOp) -> UOp|None:
|
||||
|
||||
# NOTE: adding rules to here is bad. these all need to run before the schedule cache
|
||||
pm_early_transform_tensor_graph = PatternMatcher([
|
||||
# transform precompiled FUNCTIONs -> CALLs
|
||||
(UPat(Ops.FUNCTION, name="c"), transform_precompiled_function),
|
||||
# transform precompiled CALLs
|
||||
(UPat(Ops.CALL, name="c"), transform_precompiled_call),
|
||||
|
||||
# resolve TUPLE+GETTUPLE (for precompiled calls)
|
||||
(UPat(Ops.GETTUPLE, src=(UPat(Ops.TUPLE, name="t"),), name="g"), lambda g,t: t.src[g.arg]),
|
||||
@@ -178,7 +178,7 @@ pm_replace_buf = PatternMatcher([
|
||||
(UPat(Ops.BIND, src=(UPat(Ops.DEFINE_VAR), UPat(Ops.CONST)), name="b"), replace_input_buffer),
|
||||
])
|
||||
|
||||
@track_rewrites(lambda _,ret: f"Callify {pluralize('Buffer', len(ret[1]))}")
|
||||
@track_rewrites(lambda _,ret: f"Process {pluralize('Buffer', len(ret[1]))}")
|
||||
def transform_to_call(big_sink:UOp) -> tuple[UOp, dict[UOp, UOp]]:
|
||||
if VIZ: graph_rewrite(big_sink, PatternMatcher([]), name="View Tensor Graph")
|
||||
# uop list is a list in the original_sink graph and we can map to the tags later
|
||||
@@ -6,8 +6,8 @@ from tinygrad.device import Buffer, Compiled, Device, MultiBuffer
|
||||
from tinygrad.dtype import DType, dtypes
|
||||
from tinygrad.uop.ops import UOp, PatternMatcher, Variable, sym_infer, Ops, buffers, track_rewrites, graph_rewrite
|
||||
from tinygrad.engine.realize import ExecItem, capturing, BufferCopy, BufferXfer, EncDec, CompiledRunner, Runner, Estimates
|
||||
from tinygrad.schedule.memory import memory_plan_rewrite, _collect_bufs
|
||||
from tinygrad.schedule import linear_to_schedule
|
||||
from tinygrad.engine.memory import memory_plan_rewrite, _collect_bufs
|
||||
from tinygrad.engine.schedule import linear_to_schedule
|
||||
from tinygrad.nn.state import get_parameters
|
||||
from tinygrad.schedule.rangeify import mop_cleanup
|
||||
from dataclasses import dataclass
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
import time, inspect
|
||||
from typing import cast
|
||||
from collections import deque
|
||||
from tinygrad.uop.ops import UOp, Ops, buffers, UOpMetaClass, track_rewrites, graph_rewrite, gate_kernel_sink, KernelInfo
|
||||
from tinygrad.uop.spec import type_verify, tensor_spec
|
||||
from tinygrad.device import Buffer, MultiBuffer
|
||||
from tinygrad.helpers import DEBUG, cpu_profile, TracingKey, SPEC, pluralize, SCACHE, BASEDIR, flatten, BEAM
|
||||
from tinygrad.engine.realize import ExecItem
|
||||
|
||||
# **** schedule linearizer
|
||||
|
||||
# unwrap VIEW/CAST/etc to find the actual data source (kernel output, buffer, or multi-device op)
|
||||
def _unwrap_src(s: UOp) -> UOp:
|
||||
while len(s.src) and s.op not in {Ops.AFTER, Ops.BUFFER, Ops.PARAM, Ops.MSELECT, Ops.MSTACK, Ops.BIND}: s = s.src[0]
|
||||
return s
|
||||
|
||||
def create_schedule(sched_sink:UOp) -> UOp:
|
||||
with cpu_profile(TracingKey("toposort sched_sink")):
|
||||
# build kernel dependency graph: edges from producer kernel to consumer kernels
|
||||
children: dict[UOp, list[UOp]] = {}
|
||||
in_degree: dict[UOp, int] = {}
|
||||
for u in sched_sink.toposort(gate_kernel_sink):
|
||||
if u.op is not Ops.AFTER: continue
|
||||
k = u.src[1]
|
||||
if k.op is Ops.STORE: continue # skip unprocessed STORE+AFTER inside precompiled CALL bodies
|
||||
assert k.op in {Ops.CALL, Ops.END}, f"AFTER src[1] should be CALL or END, not {k.op}"
|
||||
in_degree.setdefault(k, 0)
|
||||
if k.op is Ops.END: assert k.src[0].op is Ops.CALL, f"END src[0] should be KERNEL, not {k.src[0].op}"
|
||||
# WAR deps from rangeify are stored in AFTER src[2:]
|
||||
kernel_deps = k.src[0].src[1:] if k.op is Ops.END else k.src[1:]
|
||||
for s in kernel_deps + u.src[2:]:
|
||||
match (s := _unwrap_src(s)).op:
|
||||
case Ops.AFTER:
|
||||
children.setdefault(s.src[1], []).append(k)
|
||||
in_degree[k] += 1
|
||||
case Ops.MSELECT | Ops.MSTACK:
|
||||
for ss in s.src:
|
||||
if ss.op is Ops.MSELECT: ss = ss.src[0]
|
||||
if ss.op not in {Ops.BUFFER, Ops.PARAM}:
|
||||
assert ss.op is Ops.AFTER, f"ss.op is not AFTER, it's {ss.op}"
|
||||
children.setdefault(ss.src[1], []).append(k)
|
||||
in_degree[k] += 1
|
||||
case Ops.BUFFER | Ops.PARAM | Ops.BIND:
|
||||
pass # BUFFER/PARAM is already realized, BIND is a bound variable (not a buffer dependency)
|
||||
case _:
|
||||
raise RuntimeError(f"input to kernel must be AFTER, BUFFER, PARAM, MSELECT, MSTACK, or BIND, not {s.op}")
|
||||
|
||||
with cpu_profile(TracingKey("linearize schedule")):
|
||||
queue: deque[UOp] = deque(k for k,v in in_degree.items() if v == 0)
|
||||
linearized: list[UOp] = []
|
||||
while len(queue):
|
||||
rk = queue.popleft()
|
||||
if rk.op is Ops.LINEAR:
|
||||
linearized.extend(rk.src)
|
||||
else:
|
||||
k = rk.src[0] if rk.op is Ops.END else rk
|
||||
assert k.op is Ops.CALL, f"unexpected op in queue: {k.op}"
|
||||
buf_uops = tuple(_unwrap_src(s).buf_uop for s in k.src[1:] if s.op is not Ops.BIND)
|
||||
linearized.append(k.src[0].call(*buf_uops, metadata=k.arg.metadata))
|
||||
for x in children.get(rk, []):
|
||||
in_degree[x] -= 1
|
||||
if in_degree[x] == 0: queue.append(x)
|
||||
return UOp(Ops.LINEAR, src=tuple(linearized))
|
||||
|
||||
def linear_to_schedule(linear:UOp) -> list[ExecItem]:
|
||||
"""Convert a LINEAR UOp to a list of ExecItems."""
|
||||
schedule: list[ExecItem] = []
|
||||
for si in linear.src:
|
||||
ast, buf_uops = si.src[0], si.src[1:]
|
||||
# create subbuffers if needed
|
||||
if ast.op is Ops.BUFFER_VIEW:
|
||||
base = buf_uops[1].buffer
|
||||
assert isinstance(base, Buffer), "base can't be MultiBuffer"
|
||||
buffers[buf_uops[0]] = base.view(buf_uops[0].arg, ast.dtype, ast.arg[1]*base.dtype.itemsize)
|
||||
# wrap SINK with BEAM UOp when beam search is enabled
|
||||
if ast.op is Ops.SINK and BEAM >= 1: ast = UOp(Ops.BEAM, src=(ast,), arg=BEAM.value)
|
||||
ubufs = [b.buffer for b in buf_uops if b.op is not Ops.BIND]
|
||||
metadata = si.arg.metadata
|
||||
if ast.op is Ops.CUSTOM_FUNCTION and ast.arg == "graph":
|
||||
schedule.append(ExecItem(ast, flatten([b.bufs if isinstance(b, MultiBuffer) else [b] for b in ubufs]), metadata))
|
||||
elif any(isinstance(x, MultiBuffer) for x in ubufs):
|
||||
assert all(isinstance(x, MultiBuffer) for x in ubufs), "kernel must all be multibuffer"
|
||||
dnums = [x for x in ast.variables() if x.expr == '_device_num']
|
||||
for j, bufs in enumerate(zip(*[x.bufs for x in cast(tuple[MultiBuffer, ...], ubufs)])):
|
||||
schedule.append(ExecItem(ast, list(bufs), metadata, {dnums[0].expr:j} if len(dnums) else {}))
|
||||
else:
|
||||
schedule.append(ExecItem(ast, cast(list[Buffer|None], ubufs), metadata))
|
||||
return schedule
|
||||
|
||||
from tinygrad.engine.memory import memory_plan_rewrite
|
||||
from tinygrad.engine.realize import capturing
|
||||
from tinygrad.schedule.rangeify import get_kernel_graph
|
||||
from tinygrad.helpers import CAPTURING
|
||||
from tinygrad.uop.ops import PatternMatcher, UPat
|
||||
|
||||
def create_new_buffer(ctx:tuple[dict[UOp, UOp], tuple[UOp, ...]], b:UOp):
|
||||
if (ret:=ctx[0].get(b, None)) is None: ctx[0][b] = ret = UOp.new_buffer(b.device, b.arg, b.dtype)
|
||||
return ret
|
||||
|
||||
pm_post_sched_cache = PatternMatcher([
|
||||
(UPat(Ops.PARAM, name="x"), lambda ctx,x: ctx[1][x.arg]),
|
||||
# create new BUFFERs for LUNIQUE BUFFERs from rangeify
|
||||
(UPat(Ops.BUFFER, src=(UPat(Ops.LUNIQUE), UPat(Ops.DEVICE)), name="b"), create_new_buffer),
|
||||
])
|
||||
|
||||
pm_resolve_linear_call = PatternMatcher([
|
||||
# call LINEAR is resolved here
|
||||
(UPat(Ops.CALL, src=(UPat(Ops.LINEAR),), name="linear_call", allow_any_len=True), lambda linear_call:
|
||||
graph_rewrite(linear_call.src[0], pm_post_sched_cache, ctx=({}, linear_call.src[1:]), walk=True, name="params to buffers")),
|
||||
# LINEAR on LINEAR
|
||||
(UPat(Ops.LINEAR, custom_early_reject={Ops.LINEAR}, name="x"),
|
||||
lambda x: x.replace(src=tuple(flatten(x.src if x.op is Ops.LINEAR else (x,) for x in x.src)))),
|
||||
])
|
||||
|
||||
schedule_cache: dict[bytes, UOp] = {}
|
||||
# ctx is just for DEBUG on inner
|
||||
def lower_sink_to_linear(function:UOp) -> UOp|None:
|
||||
st = time.perf_counter()
|
||||
if isinstance(function.arg, KernelInfo): return None
|
||||
cache_key = function.key
|
||||
if not SCACHE or (sc_ret:=schedule_cache.get(cache_key, None)) is None:
|
||||
if SPEC: type_verify(function, tensor_spec)
|
||||
# support recursive CALLs
|
||||
linear = create_schedule(get_kernel_graph(function))
|
||||
if SCACHE: schedule_cache[cache_key] = linear
|
||||
else:
|
||||
# schedule cache hit
|
||||
linear = sc_ret
|
||||
if (DEBUG >= 1 and len(linear.src) > 1) or DEBUG >= 3:
|
||||
for frm in inspect.stack():
|
||||
if frm.filename == "<string>": continue
|
||||
if frm.filename.startswith(str(BASEDIR / "apps")): break
|
||||
if not frm.filename.startswith(str(BASEDIR)) and not frm.filename.endswith("/contextlib.py"): break
|
||||
else:
|
||||
frm = None
|
||||
print(f"scheduled {len(linear.src):5d} kernels in {(time.perf_counter()-st)*1000:8.2f} ms"+\
|
||||
f" | {' cache hit' if SCACHE and sc_ret is not None else 'CACHE MISS'} {cache_key.hex()[:8]}"+\
|
||||
f" | {len(UOpMetaClass.ucache):7d} uops in cache"+("" if frm is None else f" | {frm.filename}:{frm.lineno}"))
|
||||
return linear
|
||||
|
||||
pm_schedule = PatternMatcher([
|
||||
(UPat(Ops.SINK, name="function"), lower_sink_to_linear),
|
||||
])
|
||||
|
||||
@track_rewrites(lambda _,ret: f"Schedule {pluralize('Kernel', len(ret[0]))}")
|
||||
def complete_create_schedule_with_vars(big_sink:UOp) -> tuple[list[ExecItem], dict[str, int]]:
|
||||
# big_sink srcs are all the Tensors
|
||||
linear_call = graph_rewrite(big_sink, pm_schedule, name="schedule to linear", enter_calls=True)
|
||||
|
||||
# this recursively resolves the linear_call and allocates buffers
|
||||
linear = graph_rewrite(linear_call, pm_resolve_linear_call, name="resolve linear call")
|
||||
|
||||
# vars used in the schedule
|
||||
used_vars = set().union(*[{v.expr for v in si.src[0].variables()} for si in linear.src])
|
||||
# get var_vals
|
||||
var_vals: dict[str, int] = {}
|
||||
for b in big_sink.src[1:]:
|
||||
if b.op is Ops.BIND:
|
||||
nm = b.src[0].expr
|
||||
if nm not in used_vars: continue
|
||||
val = b.src[1].arg
|
||||
if var_vals.get(nm, val) != val: raise RuntimeError(f"bind mismatch on {nm}, {var_vals[nm]} != {val}")
|
||||
var_vals[nm] = val
|
||||
|
||||
# jit captures this schedule, no need to execute.
|
||||
if len(capturing) and CAPTURING:
|
||||
capturing[0].add_linear(linear, var_vals)
|
||||
return [], var_vals
|
||||
|
||||
held_bufs = ({b for b in linear_call.src[1:] if b.op is Ops.BUFFER} if linear_call.op is Ops.CALL else set())
|
||||
linear = memory_plan_rewrite(linear, held_bufs)
|
||||
|
||||
# convert LINEAR to ExecItems
|
||||
schedule: list[ExecItem] = linear_to_schedule(linear)
|
||||
return schedule, var_vals
|
||||
@@ -95,15 +95,15 @@ def compute_gradient(root:UOp, root_grad:UOp, targets:set[UOp]) -> dict[UOp, UOp
|
||||
if t0 not in grads or grads[t0].op is Ops.NOOP: continue
|
||||
# GETTUPLE: accumulate gradient into a TUPLE UOp on the CALL, process when we hit the CALL
|
||||
if t0.op is Ops.GETTUPLE:
|
||||
k = t0.src[0] # the FUNCTION
|
||||
assert k.op is Ops.FUNCTION and k.src[0].op is Ops.TUPLE
|
||||
k = t0.src[0] # the CALL
|
||||
assert k.op is Ops.CALL and k.src[0].op is Ops.TUPLE
|
||||
n_outputs = len(k.src[0].src)
|
||||
prev = grads[k].src if k in grads else tuple(UOp(Ops.NOOP) for _ in range(n_outputs))
|
||||
grads[k] = UOp.maketuple(*(prev[i] + grads[t0] if i == t0.arg and prev[i].op is not Ops.NOOP else
|
||||
grads[t0] if i == t0.arg else prev[i] for i in range(n_outputs)))
|
||||
continue
|
||||
# FUNCTION: pass needed param set so backward only computes required gradients
|
||||
if t0.op is Ops.FUNCTION:
|
||||
# CALL: pass needed param set so backward only computes required gradients
|
||||
if t0.op is Ops.CALL:
|
||||
needed = {i for i, arg in enumerate(t0.src[1:]) if arg in targets or in_target_path.get(arg, False)}
|
||||
lgrads:tuple[UOp|None, ...]|None = call_gradient(grads[t0], t0, needed)
|
||||
else:
|
||||
|
||||
+16
-17
@@ -3,7 +3,7 @@ import time
|
||||
START_TIME = time.perf_counter()
|
||||
import os, functools, platform, re, contextlib, operator, hashlib, pickle, sqlite3, tempfile, pathlib, string, ctypes, sys, gzip, getpass, gc
|
||||
from collections import defaultdict
|
||||
import subprocess, shutil, math, types, copyreg, inspect, importlib, decimal, itertools, difflib
|
||||
import subprocess, shutil, math, types, copyreg, inspect, importlib, decimal, itertools
|
||||
from dataclasses import dataclass, field, replace
|
||||
from typing import ClassVar, Iterable, Any, TypeVar, Callable, Sequence, TypeGuard, Iterator, Generic, Generator, cast, overload
|
||||
|
||||
@@ -121,11 +121,6 @@ def suppress_finalizing(func):
|
||||
if not getattr(sys, 'is_finalizing', lambda: True)(): raise # re-raise if not finalizing
|
||||
return wrapper
|
||||
|
||||
def select_by_name(candidates:Sequence[T], get_name:Callable[...,str], query:str, err_msg:str) -> list[T]:
|
||||
if len(ret:=[c for c in candidates if not query or get_name(c) == query]) == 0:
|
||||
raise RuntimeError(err_msg + (f", did you mean: {m[0]!r}?" if (m:=difflib.get_close_matches(query, map(get_name, candidates))) else ""))
|
||||
return ret
|
||||
|
||||
def select_first_inited(candidates:Sequence[Callable[...,T]], err_msg:str, cache:dict|None=None, **kwargs):
|
||||
excs = []
|
||||
for typ in candidates:
|
||||
@@ -135,7 +130,7 @@ def select_first_inited(candidates:Sequence[Callable[...,T]], err_msg:str, cache
|
||||
if cache is not None: cache[typ] = x
|
||||
return x
|
||||
except Exception as e: excs.append(e)
|
||||
raise excs[0] if len(excs) == 1 else ExceptionGroup(err_msg + " is available", excs)
|
||||
raise excs[0] if len(excs) == 1 else ExceptionGroup(err_msg, excs)
|
||||
|
||||
def pluralize(st:str, cnt:int): return f"{cnt} {st}"+('' if cnt == 1 else 's')
|
||||
|
||||
@@ -207,19 +202,20 @@ class Target:
|
||||
def replacedefault(self, **kwargs) -> Target: return replace(self, **{k:v for k,v in kwargs.items() if not getattr(self, k)})
|
||||
|
||||
class _DEV(ContextVar):
|
||||
_value: list[Target] = [Target()]
|
||||
_value = Target()
|
||||
@property
|
||||
def value(self) -> list[Target]: return self._value
|
||||
def value(self) -> Target: return self._value
|
||||
@value.setter
|
||||
def value(self, v:str|Target|list[Target]):
|
||||
self._value = v if isinstance(v, list) else [v] if isinstance(v, Target) else [Target.parse(t) for t in v.split(';')]
|
||||
def __repr__(self) -> str: return ";".join([repr(t) for t in self._value])
|
||||
def __getattr__(self, k): return getattr(self._value[0], k)
|
||||
def value(self, v:str|Target): self._value = v if isinstance(v, Target) else Target.parse(v)
|
||||
def __getattr__(self, k): return getattr(self.value, k)
|
||||
# get target for device string, kwargs are passed if not already specified
|
||||
def target(self, dev:str, **kwargs) -> Target:
|
||||
assert (v:=getenv(k:=f"{dev}_CC", "")) == "", \
|
||||
f"{k}={v} is deprecated, use DEV='{';'.join([repr(t) for t in self._value if t.device != dev] + [f'{dev}:{v}'])}' instead"
|
||||
return replace(next((t for t in self._value if not t.device or t.device == dev), Target(device=dev)).replacedefault(**kwargs), device=dev)
|
||||
t = self.value.replacedefault(**kwargs) if self.device == dev or not self.device else Target(device=dev, **kwargs)
|
||||
# TODO: remove this once DEV supports secondary targets
|
||||
if (cv:=ContextVar._cache.get(f"{dev}_CC", None)) is not None and cv.value:
|
||||
assert not t.renderer, f"renderer set in DEV and {dev}_CC"
|
||||
return replace(t, renderer=cv.value.upper())
|
||||
return replace(t, device=dev)
|
||||
|
||||
DEV, DEBUG, BEAM, NOOPT = _DEV("DEV", ""), ContextVar("DEBUG", 0), ContextVar("BEAM", 0), ContextVar("NOOPT", 0)
|
||||
IMAGE, FLOAT16, OPENPILOT_HACKS = ContextVar("IMAGE", 0), ContextVar("FLOAT16", 0), ContextVar("OPENPILOT_HACKS", 0)
|
||||
@@ -228,7 +224,7 @@ WINO, CAPTURING, TRACEMETA = ContextVar("WINO", 0), ContextVar("CAPTURING", 1),
|
||||
USE_TC, TC_SELECT, TC_OPT, AMX = ContextVar("TC", 1), ContextVar("TC_SELECT", -1), ContextVar("TC_OPT", 0), ContextVar("AMX", 0)
|
||||
TRANSCENDENTAL, NOLOCALS = ContextVar("TRANSCENDENTAL", 1), ContextVar("NOLOCALS", 0)
|
||||
SPLIT_REDUCEOP, NO_MEMORY_PLANNER, LRU = ContextVar("SPLIT_REDUCEOP", 1), ContextVar("NO_MEMORY_PLANNER", 0), ContextVar("LRU", 1)
|
||||
RING, ALL2ALL, ALLREDUCE_CAST = ContextVar("RING", 1), ContextVar("ALL2ALL", 0), ContextVar("ALLREDUCE_CAST", 1)
|
||||
RING, ALL2ALL = ContextVar("RING", 1), ContextVar("ALL2ALL", 0)
|
||||
CACHELEVEL, IGNORE_BEAM_CACHE, DEVECTORIZE = ContextVar("CACHELEVEL", 2), ContextVar("IGNORE_BEAM_CACHE", 0), ContextVar("DEVECTORIZE", 1)
|
||||
VALIDATE_WITH_CPU, DISABLE_FAST_IDIV = ContextVar("VALIDATE_WITH_CPU", 0), ContextVar("DISABLE_FAST_IDIV", 0)
|
||||
CORRECT_DIVMOD_FOLDING, FUSE_OPTIM = ContextVar("CORRECT_DIVMOD_FOLDING", 0), ContextVar("FUSE_OPTIM", 0)
|
||||
@@ -237,7 +233,10 @@ MAX_KERNEL_BUFFERS = ContextVar("MAX_KERNEL_BUFFERS", 0)
|
||||
EMULATED_DTYPES = ContextVar("EMULATED_DTYPES", "")
|
||||
CAPTURE_PROCESS_REPLAY = ContextVar("CAPTURE_PROCESS_REPLAY", 0)
|
||||
CPU_COUNT = ContextVar("CPU_COUNT", max(1, len(os.sched_getaffinity(0)) if hasattr(os, "sched_getaffinity") else (os.cpu_count() or 1)))
|
||||
# Compilers
|
||||
CPU_CC, NV_CC, CUDA_CC, NULL_CC = ContextVar("CPU_CC", ""), ContextVar("NV_CC", ""), ContextVar("CUDA_CC", ""), ContextVar("NULL_CC", "")
|
||||
NULL_ALLOW_COPYOUT = ContextVar("NULL_ALLOW_COPYOUT", 0)
|
||||
AMD_CC, QCOM_CC = ContextVar("AMD_CC", ""), ContextVar("QCOM_CC", "")
|
||||
# VIZ implies PROFILE, but you can run PROFILE without VIZ
|
||||
VIZ = ContextVar("VIZ", 0)
|
||||
PROFILE = ContextVar("PROFILE", abs(VIZ.value))
|
||||
|
||||
@@ -1,26 +1,15 @@
|
||||
import functools, itertools
|
||||
import functools
|
||||
from typing import Self, Sequence, Literal, get_args
|
||||
from tinygrad.mixin.elementwise import ElementwiseMixin
|
||||
from tinygrad.mixin.movement import MovementMixin
|
||||
from tinygrad.mixin.reduce import ReduceMixin
|
||||
from tinygrad.uop import Ops
|
||||
from tinygrad.uop.ops import _broadcast_shape, resolve, smax, smin, identity_element
|
||||
from tinygrad.uop.ops import _broadcast_shape, resolve
|
||||
from tinygrad.dtype import DTypeLike, dtypes, least_upper_dtype, sum_acc_dtype, to_dtype
|
||||
from tinygrad.helpers import argfix, flatten, prod, round_up
|
||||
from tinygrad.helpers import argfix, prod
|
||||
|
||||
ReductionStr = Literal["mean", "sum", "none"]
|
||||
|
||||
|
||||
class OpMixin(ElementwiseMixin, ReduceMixin):
|
||||
def _pad_constant(self, pX, value:float) -> Self:
|
||||
# shrink first for negative pads, then pad with only non-negative values
|
||||
pX = tuple((0, 0) if p is None else p for p in pX)
|
||||
has_neg = not all(resolve(p >= 0) for p in flatten(pX))
|
||||
X = self.shrink(tuple((-smin(pB,0),smin(pA+s,s)) for (pB,pA),s in zip(pX, self.shape))) if has_neg else self
|
||||
pads = tuple((smax(pB,0), smax(pA,0)) for pB,pA in pX) if has_neg else pX
|
||||
if value == 0: return MovementMixin.pad(X, pads)
|
||||
return MovementMixin.pad(X, pads) + MovementMixin.pad(X.ones_like(), pads).cast(dtypes.bool).where(0, value)
|
||||
|
||||
def _broadcasted(self, y, reverse=False) -> tuple[Self, Self]:
|
||||
if not isinstance(y, type(self)): y = self.ufix(y)
|
||||
x, y = (self, y) if not reverse else (y, self)
|
||||
@@ -260,90 +249,6 @@ class OpMixin(ElementwiseMixin, ReduceMixin):
|
||||
m = self.max(axis=axis, keepdim=True)
|
||||
return (self - m).exp().sum(axis=axis, keepdim=keepdim).log() + (m if keepdim else m.squeeze(axis))
|
||||
|
||||
def cat(self, *args:Self, dim:int=0) -> Self:
|
||||
"""
|
||||
Concatenates self with other tensors in `args` along an axis specified by `dim`.
|
||||
All tensors must have the same shape except in the concatenating dimension.
|
||||
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
t0, t1, t2 = Tensor([[1, 2]]), Tensor([[3, 4]]), Tensor([[5, 6]])
|
||||
print(t0.cat(t1, t2, dim=0).numpy())
|
||||
```
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
print(t0.cat(t1, t2, dim=1).numpy())
|
||||
```
|
||||
"""
|
||||
dim = self._resolve_dim(dim)
|
||||
for arg in args: assert arg.ndim==self.ndim and all(ti==ai for i,(ti,ai) in enumerate(zip(self.shape, arg.shape)) if i!=dim)
|
||||
tensors = [self, *args]
|
||||
dim_cumsum = list(itertools.accumulate([t.shape[dim] for t in tensors], initial=0))
|
||||
padded = [t.pad(tuple((dim_cumsum[i], dim_cumsum[-1]-dim_cumsum[i+1]) if j==dim else None for j in range(t.ndim))) for i,t in enumerate(tensors)]
|
||||
return padded[0].usum(*padded[1:])
|
||||
|
||||
def stack(self, *args:Self, dim:int=0) -> Self:
|
||||
"""
|
||||
Concatenates self with other tensors in `args` along a new dimension specified by `dim`.
|
||||
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
t0, t1, t2 = Tensor([1, 2]), Tensor([3, 4]), Tensor([5, 6])
|
||||
print(t0.stack(t1, t2, dim=0).numpy())
|
||||
```
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
print(t0.stack(t1, t2, dim=1).numpy())
|
||||
```
|
||||
"""
|
||||
# checks for shapes and number of dimensions delegated to cat
|
||||
unsqueezed = [t.unsqueeze(dim) for t in argfix(self, *args)]
|
||||
return unsqueezed[0].cat(*unsqueezed[1:], dim=dim)
|
||||
|
||||
def _cumalu(self, axis:int, op:Ops) -> Self:
|
||||
assert self.shape[axis] != 0 and op in (Ops.ADD, Ops.MAX, Ops.MUL)
|
||||
pads = (None,)*(self.ndim-1) + ((self.shape[axis]-1, 0),)
|
||||
pooled = self.transpose(axis,-1)._pad_constant(pads, identity_element(op, self.dtype))._pool((self.shape[axis],))
|
||||
return getattr(pooled, {Ops.ADD: "sum", Ops.MAX: "max", Ops.MUL: "prod"}[op])(-1).transpose(axis, -1)
|
||||
|
||||
def _split_cumalu(self, axis:int, op:Ops) -> Self:
|
||||
axis = self._resolve_dim(axis)
|
||||
if self.ndim == 0 or 0 in self.shape: return self
|
||||
# TODO: someday the optimizer will find this on its own
|
||||
# for now this is a two stage cumsum
|
||||
SPLIT = 256
|
||||
value = identity_element(op, self.dtype)
|
||||
if not isinstance(s:=self.shape[axis], int) or s <= SPLIT*2: return self._cumalu(axis, op)
|
||||
ret = self.transpose(axis,-1)._pad_constant((None,)*(self.ndim-1)+((round_up(s,SPLIT)-s,0),), value).unflatten(-1,(-1,SPLIT))._cumalu(-1, op)
|
||||
base = ret[..., -1]._cumalu(-1, op)._pad_constant((None,)*(ret.ndim-2) + ((1, -1),), value)
|
||||
base = base.unsqueeze(-1).expand(*base.shape, ret.shape[-1])
|
||||
def fix(x: Self) -> Self: return x.flatten(start_dim=-2)[..., -s:].transpose(axis,-1)
|
||||
return getattr(fix(ret), {Ops.ADD: "add", Ops.MAX: "maximum", Ops.MUL: "mul"}[op])(fix(base))
|
||||
|
||||
def cumsum(self, axis:int=0) -> Self:
|
||||
"""
|
||||
Computes the cumulative sum of the tensor along the specified `axis`.
|
||||
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
t = Tensor.ones(2, 3)
|
||||
print(t.numpy())
|
||||
```
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
print(t.cumsum(1).numpy())
|
||||
```
|
||||
"""
|
||||
return self._split_cumalu(axis, Ops.ADD)
|
||||
|
||||
def cumprod(self, axis:int) -> Self:
|
||||
"""
|
||||
Computes the cumulative product of the elements of the tensor along the specified `axis`.
|
||||
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
t = Tensor.arange(1, 7).reshape(2, 3)
|
||||
print(t.numpy())
|
||||
```
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
print(t.cumprod(axis=0).numpy())
|
||||
```
|
||||
"""
|
||||
return self._split_cumalu(axis, Ops.MUL)
|
||||
|
||||
# ***** functional nn ops *****
|
||||
|
||||
def linear(self, weight:Self, bias:Self|None=None, dtype:DTypeLike|None=None) -> Self:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, Self, Sequence
|
||||
from tinygrad.uop import Ops
|
||||
from tinygrad.helpers import prod, argfix, argsort, flatten, dedup, make_tuple, ceildiv, round_up, all_int
|
||||
from tinygrad.helpers import prod, argfix, argsort, flatten, dedup, make_tuple, ceildiv
|
||||
from tinygrad.uop.ops import resolve, smax, _align_left, _broadcast_shape
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -56,56 +56,6 @@ class MovementMixin:
|
||||
raise IndexError(f"{dim=} out of range {[-max(1, total), max(1, total) - 1]}")
|
||||
return dim + total if dim < 0 else dim
|
||||
|
||||
def _parse_view_index(self, index, size: sint) -> dict:
|
||||
# parses a single slice/int/None/sint index into {boundary, stride, size, collapse_dim}
|
||||
from tinygrad.uop.ops import UOp, sint
|
||||
match index:
|
||||
case None: return {"size":1, "boundary":(0,1), "stride":1, "collapse_dim":False}
|
||||
case int() | UOp(): # sint
|
||||
if resolve(index >= size, False) or resolve(index < -size, False): raise IndexError(f"{index=} is out of bounds with {size=}")
|
||||
# TODO: is this right for (negative) symbolic?
|
||||
b = index if resolve(index >= 0, False) else index + size
|
||||
return {"size":size, "boundary":(b, b+1), "stride":1, "collapse_dim":True}
|
||||
case slice():
|
||||
if not all(s is None or isinstance(s, sint) for s in (index.start, index.stop, index.step)):
|
||||
raise TypeError(f"slice {index=} is not supported")
|
||||
if resolve(index.step == 0, False): raise ValueError(f"{index=} cannot have 0 as step")
|
||||
start, stop = 0 if index.start is None else index.start, size if index.stop is None else index.stop
|
||||
step = 1 if index.step is None else index.step
|
||||
if all_int((start, stop, step)):
|
||||
# handle int slicing (resolve negative bounds, clamp, stride)
|
||||
*bound, stride = index.indices(int(size.vmax) if isinstance(size, UOp) else size)
|
||||
bound = [0, 0] if stride * (bound[1] - bound[0]) < 0 else ([bound[1]+1, bound[0]+1] if stride < 0 else bound)
|
||||
return {"size":ceildiv(bound[1]-bound[0], abs(stride)), "boundary":tuple(bound), "stride":stride, "collapse_dim":False}
|
||||
if resolve(step == 1, False) and resolve((stop-start) >= 0, False):
|
||||
return {"size":stop-start, "boundary":(start, stop), "stride":step, "collapse_dim":False}
|
||||
raise TypeError(f"slice {index=} is not supported")
|
||||
case _: raise IndexError(f"{type(index).__name__} indexing is not supported")
|
||||
|
||||
def _apply_view_ops(self, mops:list) -> Self:
|
||||
# applies shrink + flip + stride from a list of parsed view indices
|
||||
# flip negative strides
|
||||
x = self.shrink(tuple(m["boundary"] for m in mops)).flip(tuple(i for i, m in enumerate(mops) if m["stride"] < 0))
|
||||
strides = tuple(abs(m["stride"]) for m in mops)
|
||||
# apply stride
|
||||
if any(st != 1 for st in strides):
|
||||
if not all_int(x.shape): raise RuntimeError("symbolic shape not supported")
|
||||
x = x.pad_to(tuple(round_up(s, st) for s, st in zip(x.shape, strides)))
|
||||
x = x.reshape(tuple(flatten((s // st, st) for s, st in zip(x.shape, strides))))
|
||||
x = x.shrink_to(tuple(flatten((s, 1) for s in x.shape[::2]))).reshape(x.shape[::2])
|
||||
return x
|
||||
|
||||
def __getitem__(self, indices) -> Self:
|
||||
# wrap single index into a list
|
||||
if (isinstance(indices, list) and all_int(indices)) or not isinstance(indices, (tuple, list)): indices = [indices]
|
||||
indices_parsed, dim = [], 0
|
||||
for index in self._normalize_indices(list(indices)):
|
||||
indices_parsed.append({**self._parse_view_index(index, 1 if index is None else self.shape[dim]), "index":index})
|
||||
if index is not None: dim += 1
|
||||
x = self._apply_view_ops(mops) if (mops := [p for p in indices_parsed if p["index"] is not None]) else self
|
||||
# dim injection from None (size 1) and dim collapse from int indices
|
||||
return x.reshape(tuple(p["size"] for p in indices_parsed if not p["collapse_dim"]))
|
||||
|
||||
def _broadcast_to(self, new_shape: tuple[sint, ...]) -> Self:
|
||||
if self.shape == new_shape:
|
||||
return self
|
||||
|
||||
@@ -32,13 +32,11 @@ _FORMATS: dict[str, list[type[Inst]]] | None = None
|
||||
def _load_formats() -> dict[str, list[type[Inst]]]:
|
||||
global _FORMATS
|
||||
if _FORMATS is not None: return _FORMATS
|
||||
from tinygrad.runtime.autogen.amd.rdna3.ins import (VOP1, VOP1_SDST, VOP1_DPP16, VOP1_LIT, VOP2, VOP2_DPP16, VOP2_LIT, VOP3, VOP3_SDST,
|
||||
VOP3SD, VOP3P, VOPC, VOPC_DPP16, VOPD, VINTERP, SOP1, SOP1_LIT, SOP2, SOP2_LIT, SOPC, SOPK, SOPK_LIT, SOPP, SMEM, DS, FLAT, GLOBAL,
|
||||
SCRATCH)
|
||||
from tinygrad.runtime.autogen.amd.rdna4.ins import (VOP1 as R4_VOP1, VOP1_SDST as R4_VOP1_SDST, VOP1_DPP16 as R4_VOP1_DPP16,
|
||||
VOP1_LIT as R4_VOP1_LIT, VOP2 as R4_VOP2, VOP2_DPP16 as R4_VOP2_DPP16, VOP2_LIT as R4_VOP2_LIT, VOP3 as R4_VOP3,
|
||||
VOP3_SDST as R4_VOP3_SDST, VOP3SD as R4_VOP3SD, VOP3P as R4_VOP3P, VOPC as R4_VOPC, VOPC_DPP16 as R4_VOPC_DPP16,
|
||||
VOPD as R4_VOPD, VINTERP as R4_VINTERP, SOP1 as R4_SOP1, SOP1_LIT as R4_SOP1_LIT,
|
||||
from tinygrad.runtime.autogen.amd.rdna3.ins import (VOP1, VOP1_SDST, VOP1_LIT, VOP2, VOP2_LIT, VOP3, VOP3_SDST, VOP3SD, VOP3P, VOPC, VOPD,
|
||||
VINTERP, SOP1, SOP1_LIT, SOP2, SOP2_LIT, SOPC, SOPK, SOPK_LIT, SOPP, SMEM, DS, FLAT, GLOBAL, SCRATCH)
|
||||
from tinygrad.runtime.autogen.amd.rdna4.ins import (VOP1 as R4_VOP1, VOP1_SDST as R4_VOP1_SDST, VOP1_LIT as R4_VOP1_LIT,
|
||||
VOP2 as R4_VOP2, VOP2_LIT as R4_VOP2_LIT, VOP3 as R4_VOP3, VOP3_SDST as R4_VOP3_SDST, VOP3SD as R4_VOP3SD, VOP3P as R4_VOP3P,
|
||||
VOPC as R4_VOPC, VOPD as R4_VOPD, VINTERP as R4_VINTERP, SOP1 as R4_SOP1, SOP1_LIT as R4_SOP1_LIT,
|
||||
SOP2 as R4_SOP2, SOP2_LIT as R4_SOP2_LIT, SOPC as R4_SOPC, SOPC_LIT as R4_SOPC_LIT,
|
||||
SOPK as R4_SOPK, SOPK_LIT as R4_SOPK_LIT, SOPP as R4_SOPP,
|
||||
SMEM as R4_SMEM, DS as R4_DS, VFLAT as R4_FLAT, VGLOBAL as R4_GLOBAL, VSCRATCH as R4_SCRATCH)
|
||||
@@ -52,11 +50,10 @@ def _load_formats() -> dict[str, list[type[Inst]]]:
|
||||
# Order: base before _LIT (base matches regular ops, _LIT catches lit-only ops excluded from base)
|
||||
_FORMATS = {
|
||||
"rdna3": [VOPD, VOP3P, VINTERP, VOP3SD, VOP3_SDST, VOP3, DS, GLOBAL, SCRATCH, FLAT, SMEM,
|
||||
SOP1, SOP1_LIT, SOP2, SOP2_LIT, SOPC, SOPK, SOPK_LIT, SOPP, VOPC_DPP16, VOPC, VOP1_SDST, VOP1_DPP16, VOP1, VOP1_LIT,
|
||||
VOP2_DPP16, VOP2, VOP2_LIT],
|
||||
SOP1, SOP1_LIT, SOP2, SOP2_LIT, SOPC, SOPK, SOPK_LIT, SOPP, VOPC, VOP1_SDST, VOP1, VOP1_LIT, VOP2, VOP2_LIT],
|
||||
"rdna4": [R4_VOPD, R4_VOP3P, R4_VINTERP, R4_VOP3SD, R4_VOP3_SDST, R4_VOP3, R4_DS, R4_GLOBAL, R4_SCRATCH, R4_FLAT, R4_SMEM,
|
||||
R4_SOP1, R4_SOP1_LIT, R4_SOPC, R4_SOPC_LIT, R4_SOPP, R4_SOPK, R4_SOPK_LIT, R4_VOPC_DPP16, R4_VOPC, R4_VOP1_SDST,
|
||||
R4_VOP1_DPP16, R4_VOP1, R4_VOP1_LIT, R4_SOP2, R4_SOP2_LIT, R4_VOP2_DPP16, R4_VOP2, R4_VOP2_LIT],
|
||||
R4_SOP1, R4_SOP1_LIT, R4_SOPC, R4_SOPC_LIT, R4_SOPP, R4_SOPK, R4_SOPK_LIT, R4_VOPC, R4_VOP1_SDST, R4_VOP1, R4_VOP1_LIT,
|
||||
R4_SOP2, R4_SOP2_LIT, R4_VOP2, R4_VOP2_LIT],
|
||||
"cdna": [C_VOP3PX2, C_VOP3P_MFMA, C_VOP3P, C_VOP3SD, C_VOP3_SDST, C_VOP3, C_DS, C_GLOBAL, C_SCRATCH, C_FLAT, C_MUBUF, C_SMEM,
|
||||
C_SOP1, C_SOPC, C_SOPP, C_SOPK, C_SOPK_LIT, C_VOPC_SDWA_SDST, C_VOPC,
|
||||
C_VOP1_DPP16, C_VOP1_SDWA, C_VOP1, C_VOP2_DPP16, C_VOP2_SDWA, C_SOP2, C_VOP2, C_VOP2_LIT],
|
||||
|
||||
@@ -127,7 +127,7 @@ def __getattr__(nm):
|
||||
return load("rocprof", "['rocprof-trace-decoder', p:='/usr/local/lib/rocprof-trace-decoder.so', p.replace('so','dylib')]",
|
||||
[f"{{}}/include/{s}.h" for s in ["rocprof_trace_decoder", "trace_decoder_instrument", "trace_decoder_types"]],
|
||||
srcs="https://github.com/ROCm/rocprof-trace-decoder/archive/dd0485100971522cc4cd8ae136bdda431061a04d.tar.gz")
|
||||
case "mesa": return load("mesa", "([] if DEV.renderer == 'LVP' else ['tinymesa']) + ['tinymesa_cpu']", [
|
||||
case "mesa": return load("mesa", "([] if CPU_CC.value == 'LVP' or DEV.renderer == 'LVP' else ['tinymesa']) + ['tinymesa_cpu']", [
|
||||
*[f"{{}}/src/compiler/nir/{s}.h" for s in ["nir", "nir_builder", "nir_shader_compiler_options", "nir_serialize"]], "{}/gen/nir_intrinsics.h",
|
||||
*[f"{{}}/src/nouveau/{s}.h" for s in ["headers/nv_device_info", "compiler/nak"]],
|
||||
*[f"{{}}/src/gallium/auxiliary/gallivm/lp_bld{s}.h" for s in ["", "_passmgr", "_misc", "_type", "_init", "_nir", "_struct", "_jit_types",
|
||||
@@ -146,7 +146,7 @@ def __getattr__(nm):
|
||||
*[f"python3 src/compiler/{s}_h.py > gen/{s.split('/')[-1]}.h" for s in ["nir/nir_opcodes", "nir/nir_builder_opcodes"]],
|
||||
*[f"python3 src/compiler/nir/nir_{s}_h.py --outdir gen" for s in ["intrinsics", "intrinsics_indices"]]]), cwd=path, shell=True, check=True),
|
||||
srcs="https://gitlab.freedesktop.org/mesa/mesa/-/archive/mesa-25.2.7/mesa-25.2.7.tar.gz",
|
||||
prolog=["from tinygrad.helpers import DEV", "import gzip, base64"],
|
||||
prolog=["from tinygrad.helpers import CPU_CC, DEV", "import gzip, base64"],
|
||||
epilog=lambda path: [system(f"{root}/extra/mesa/lvp_nir_options.sh {path}")])
|
||||
case "libclang":
|
||||
return load("libclang", clang_lib,
|
||||
|
||||
+4281
-3780
File diff suppressed because one or more lines are too long
@@ -1,42 +1,139 @@
|
||||
# mypy: disable-error-code="empty-body"
|
||||
from __future__ import annotations
|
||||
import ctypes
|
||||
from typing import Literal, TypeAlias
|
||||
from typing import Annotated, Literal, TypeAlias
|
||||
from tinygrad.runtime.support.c import _IO, _IOW, _IOR, _IOWR
|
||||
from tinygrad.runtime.support import c
|
||||
class union_PM4_MES_TYPE_3_HEADER(c.Struct): pass
|
||||
enum_mes_set_resources_queue_type_enum: dict[int, str] = {(queue_type__mes_set_resources__kernel_interface_queue_kiq:=0): 'queue_type__mes_set_resources__kernel_interface_queue_kiq', (queue_type__mes_set_resources__hsa_interface_queue_hiq:=1): 'queue_type__mes_set_resources__hsa_interface_queue_hiq', (queue_type__mes_set_resources__hsa_debug_interface_queue:=4): 'queue_type__mes_set_resources__hsa_debug_interface_queue'}
|
||||
class struct_pm4_mes_set_resources(c.Struct): pass
|
||||
class struct_pm4_mes_runlist(c.Struct): pass
|
||||
class struct_pm4_mes_map_process(c.Struct): pass
|
||||
class struct_PM4_MES_MAP_PROCESS_VM(c.Struct): pass
|
||||
enum_mes_map_queues_queue_sel_enum: dict[int, str] = {(queue_sel__mes_map_queues__map_to_specified_queue_slots_vi:=0): 'queue_sel__mes_map_queues__map_to_specified_queue_slots_vi', (queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi:=1): 'queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi'}
|
||||
enum_mes_map_queues_queue_type_enum: dict[int, str] = {(queue_type__mes_map_queues__normal_compute_vi:=0): 'queue_type__mes_map_queues__normal_compute_vi', (queue_type__mes_map_queues__debug_interface_queue_vi:=1): 'queue_type__mes_map_queues__debug_interface_queue_vi', (queue_type__mes_map_queues__normal_latency_static_queue_vi:=2): 'queue_type__mes_map_queues__normal_latency_static_queue_vi', (queue_type__mes_map_queues__low_latency_static_queue_vi:=3): 'queue_type__mes_map_queues__low_latency_static_queue_vi'}
|
||||
enum_mes_map_queues_engine_sel_enum: dict[int, str] = {(engine_sel__mes_map_queues__compute_vi:=0): 'engine_sel__mes_map_queues__compute_vi', (engine_sel__mes_map_queues__sdma0_vi:=2): 'engine_sel__mes_map_queues__sdma0_vi', (engine_sel__mes_map_queues__sdma1_vi:=3): 'engine_sel__mes_map_queues__sdma1_vi'}
|
||||
enum_mes_map_queues_extended_engine_sel_enum: dict[int, str] = {(extended_engine_sel__mes_map_queues__legacy_engine_sel:=0): 'extended_engine_sel__mes_map_queues__legacy_engine_sel', (extended_engine_sel__mes_map_queues__sdma0_to_7_sel:=1): 'extended_engine_sel__mes_map_queues__sdma0_to_7_sel', (extended_engine_sel__mes_map_queues__sdma8_to_15_sel:=2): 'extended_engine_sel__mes_map_queues__sdma8_to_15_sel'}
|
||||
class struct_pm4_mes_map_queues(c.Struct): pass
|
||||
enum_mes_query_status_interrupt_sel_enum: dict[int, str] = {(interrupt_sel__mes_query_status__completion_status:=0): 'interrupt_sel__mes_query_status__completion_status', (interrupt_sel__mes_query_status__process_status:=1): 'interrupt_sel__mes_query_status__process_status', (interrupt_sel__mes_query_status__queue_status:=2): 'interrupt_sel__mes_query_status__queue_status'}
|
||||
enum_mes_query_status_command_enum: dict[int, str] = {(command__mes_query_status__interrupt_only:=0): 'command__mes_query_status__interrupt_only', (command__mes_query_status__fence_only_immediate:=1): 'command__mes_query_status__fence_only_immediate', (command__mes_query_status__fence_only_after_write_ack:=2): 'command__mes_query_status__fence_only_after_write_ack', (command__mes_query_status__fence_wait_for_write_ack_send_interrupt:=3): 'command__mes_query_status__fence_wait_for_write_ack_send_interrupt'}
|
||||
enum_mes_query_status_engine_sel_enum: dict[int, str] = {(engine_sel__mes_query_status__compute:=0): 'engine_sel__mes_query_status__compute', (engine_sel__mes_query_status__sdma0_queue:=2): 'engine_sel__mes_query_status__sdma0_queue', (engine_sel__mes_query_status__sdma1_queue:=3): 'engine_sel__mes_query_status__sdma1_queue'}
|
||||
class struct_pm4_mes_query_status(c.Struct): pass
|
||||
enum_mes_unmap_queues_action_enum: dict[int, str] = {(action__mes_unmap_queues__preempt_queues:=0): 'action__mes_unmap_queues__preempt_queues', (action__mes_unmap_queues__reset_queues:=1): 'action__mes_unmap_queues__reset_queues', (action__mes_unmap_queues__disable_process_queues:=2): 'action__mes_unmap_queues__disable_process_queues', (action__mes_unmap_queues__reserved:=3): 'action__mes_unmap_queues__reserved'}
|
||||
enum_mes_unmap_queues_queue_sel_enum: dict[int, str] = {(queue_sel__mes_unmap_queues__perform_request_on_specified_queues:=0): 'queue_sel__mes_unmap_queues__perform_request_on_specified_queues', (queue_sel__mes_unmap_queues__perform_request_on_pasid_queues:=1): 'queue_sel__mes_unmap_queues__perform_request_on_pasid_queues', (queue_sel__mes_unmap_queues__unmap_all_queues:=2): 'queue_sel__mes_unmap_queues__unmap_all_queues', (queue_sel__mes_unmap_queues__unmap_all_non_static_queues:=3): 'queue_sel__mes_unmap_queues__unmap_all_non_static_queues'}
|
||||
enum_mes_unmap_queues_engine_sel_enum: dict[int, str] = {(engine_sel__mes_unmap_queues__compute:=0): 'engine_sel__mes_unmap_queues__compute', (engine_sel__mes_unmap_queues__sdma0:=2): 'engine_sel__mes_unmap_queues__sdma0', (engine_sel__mes_unmap_queues__sdmal:=3): 'engine_sel__mes_unmap_queues__sdmal'}
|
||||
enum_mes_unmap_queues_extended_engine_sel_enum: dict[int, str] = {(extended_engine_sel__mes_unmap_queues__legacy_engine_sel:=0): 'extended_engine_sel__mes_unmap_queues__legacy_engine_sel', (extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel:=1): 'extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel'}
|
||||
class struct_pm4_mes_unmap_queues(c.Struct): pass
|
||||
enum_mec_release_mem_event_index_enum: dict[int, str] = {(event_index__mec_release_mem__end_of_pipe:=5): 'event_index__mec_release_mem__end_of_pipe', (event_index__mec_release_mem__shader_done:=6): 'event_index__mec_release_mem__shader_done'}
|
||||
enum_mec_release_mem_cache_policy_enum: dict[int, str] = {(cache_policy__mec_release_mem__lru:=0): 'cache_policy__mec_release_mem__lru', (cache_policy__mec_release_mem__stream:=1): 'cache_policy__mec_release_mem__stream'}
|
||||
enum_mec_release_mem_pq_exe_status_enum: dict[int, str] = {(pq_exe_status__mec_release_mem__default:=0): 'pq_exe_status__mec_release_mem__default', (pq_exe_status__mec_release_mem__phase_update:=1): 'pq_exe_status__mec_release_mem__phase_update'}
|
||||
enum_mec_release_mem_dst_sel_enum: dict[int, str] = {(dst_sel__mec_release_mem__memory_controller:=0): 'dst_sel__mec_release_mem__memory_controller', (dst_sel__mec_release_mem__tc_l2:=1): 'dst_sel__mec_release_mem__tc_l2', (dst_sel__mec_release_mem__queue_write_pointer_register:=2): 'dst_sel__mec_release_mem__queue_write_pointer_register', (dst_sel__mec_release_mem__queue_write_pointer_poll_mask_bit:=3): 'dst_sel__mec_release_mem__queue_write_pointer_poll_mask_bit'}
|
||||
enum_mec_release_mem_int_sel_enum: dict[int, str] = {(int_sel__mec_release_mem__none:=0): 'int_sel__mec_release_mem__none', (int_sel__mec_release_mem__send_interrupt_only:=1): 'int_sel__mec_release_mem__send_interrupt_only', (int_sel__mec_release_mem__send_interrupt_after_write_confirm:=2): 'int_sel__mec_release_mem__send_interrupt_after_write_confirm', (int_sel__mec_release_mem__send_data_after_write_confirm:=3): 'int_sel__mec_release_mem__send_data_after_write_confirm', (int_sel__mec_release_mem__unconditionally_send_int_ctxid:=4): 'int_sel__mec_release_mem__unconditionally_send_int_ctxid', (int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_32_bit_compare:=5): 'int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_32_bit_compare', (int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_64_bit_compare:=6): 'int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_64_bit_compare'}
|
||||
enum_mec_release_mem_data_sel_enum: dict[int, str] = {(data_sel__mec_release_mem__none:=0): 'data_sel__mec_release_mem__none', (data_sel__mec_release_mem__send_32_bit_low:=1): 'data_sel__mec_release_mem__send_32_bit_low', (data_sel__mec_release_mem__send_64_bit_data:=2): 'data_sel__mec_release_mem__send_64_bit_data', (data_sel__mec_release_mem__send_gpu_clock_counter:=3): 'data_sel__mec_release_mem__send_gpu_clock_counter', (data_sel__mec_release_mem__send_cp_perfcounter_hi_lo:=4): 'data_sel__mec_release_mem__send_cp_perfcounter_hi_lo', (data_sel__mec_release_mem__store_gds_data_to_memory:=5): 'data_sel__mec_release_mem__store_gds_data_to_memory'}
|
||||
class struct_pm4_mec_release_mem(c.Struct): pass
|
||||
enum_WRITE_DATA_dst_sel_enum: dict[int, str] = {(dst_sel___write_data__mem_mapped_register:=0): 'dst_sel___write_data__mem_mapped_register', (dst_sel___write_data__tc_l2:=2): 'dst_sel___write_data__tc_l2', (dst_sel___write_data__gds:=3): 'dst_sel___write_data__gds', (dst_sel___write_data__memory:=5): 'dst_sel___write_data__memory', (dst_sel___write_data__memory_mapped_adc_persistent_state:=6): 'dst_sel___write_data__memory_mapped_adc_persistent_state'}
|
||||
enum_WRITE_DATA_addr_incr_enum: dict[int, str] = {(addr_incr___write_data__increment_address:=0): 'addr_incr___write_data__increment_address', (addr_incr___write_data__do_not_increment_address:=1): 'addr_incr___write_data__do_not_increment_address'}
|
||||
enum_WRITE_DATA_wr_confirm_enum: dict[int, str] = {(wr_confirm___write_data__do_not_wait_for_write_confirmation:=0): 'wr_confirm___write_data__do_not_wait_for_write_confirmation', (wr_confirm___write_data__wait_for_write_confirmation:=1): 'wr_confirm___write_data__wait_for_write_confirmation'}
|
||||
enum_WRITE_DATA_cache_policy_enum: dict[int, str] = {(cache_policy___write_data__lru:=0): 'cache_policy___write_data__lru', (cache_policy___write_data__stream:=1): 'cache_policy___write_data__stream'}
|
||||
class struct_pm4_mec_write_data_mmio(c.Struct): pass
|
||||
_anonenum0: dict[int, str] = {(CACHE_FLUSH_AND_INV_TS_EVENT:=20): 'CACHE_FLUSH_AND_INV_TS_EVENT'}
|
||||
class union_PM4_MES_TYPE_3_HEADER(c.Struct): SIZE = 0
|
||||
class enum_mes_set_resources_queue_type_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
queue_type__mes_set_resources__kernel_interface_queue_kiq = enum_mes_set_resources_queue_type_enum.define('queue_type__mes_set_resources__kernel_interface_queue_kiq', 0)
|
||||
queue_type__mes_set_resources__hsa_interface_queue_hiq = enum_mes_set_resources_queue_type_enum.define('queue_type__mes_set_resources__hsa_interface_queue_hiq', 1)
|
||||
queue_type__mes_set_resources__hsa_debug_interface_queue = enum_mes_set_resources_queue_type_enum.define('queue_type__mes_set_resources__hsa_debug_interface_queue', 4)
|
||||
|
||||
class struct_pm4_mes_set_resources(c.Struct): SIZE = 0
|
||||
class struct_pm4_mes_runlist(c.Struct): SIZE = 0
|
||||
class struct_pm4_mes_map_process(c.Struct): SIZE = 0
|
||||
class struct_PM4_MES_MAP_PROCESS_VM(c.Struct): SIZE = 0
|
||||
class enum_mes_map_queues_queue_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
queue_sel__mes_map_queues__map_to_specified_queue_slots_vi = enum_mes_map_queues_queue_sel_enum.define('queue_sel__mes_map_queues__map_to_specified_queue_slots_vi', 0)
|
||||
queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi = enum_mes_map_queues_queue_sel_enum.define('queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi', 1)
|
||||
|
||||
class enum_mes_map_queues_queue_type_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
queue_type__mes_map_queues__normal_compute_vi = enum_mes_map_queues_queue_type_enum.define('queue_type__mes_map_queues__normal_compute_vi', 0)
|
||||
queue_type__mes_map_queues__debug_interface_queue_vi = enum_mes_map_queues_queue_type_enum.define('queue_type__mes_map_queues__debug_interface_queue_vi', 1)
|
||||
queue_type__mes_map_queues__normal_latency_static_queue_vi = enum_mes_map_queues_queue_type_enum.define('queue_type__mes_map_queues__normal_latency_static_queue_vi', 2)
|
||||
queue_type__mes_map_queues__low_latency_static_queue_vi = enum_mes_map_queues_queue_type_enum.define('queue_type__mes_map_queues__low_latency_static_queue_vi', 3)
|
||||
|
||||
class enum_mes_map_queues_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
engine_sel__mes_map_queues__compute_vi = enum_mes_map_queues_engine_sel_enum.define('engine_sel__mes_map_queues__compute_vi', 0)
|
||||
engine_sel__mes_map_queues__sdma0_vi = enum_mes_map_queues_engine_sel_enum.define('engine_sel__mes_map_queues__sdma0_vi', 2)
|
||||
engine_sel__mes_map_queues__sdma1_vi = enum_mes_map_queues_engine_sel_enum.define('engine_sel__mes_map_queues__sdma1_vi', 3)
|
||||
|
||||
class enum_mes_map_queues_extended_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
extended_engine_sel__mes_map_queues__legacy_engine_sel = enum_mes_map_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_map_queues__legacy_engine_sel', 0)
|
||||
extended_engine_sel__mes_map_queues__sdma0_to_7_sel = enum_mes_map_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_map_queues__sdma0_to_7_sel', 1)
|
||||
extended_engine_sel__mes_map_queues__sdma8_to_15_sel = enum_mes_map_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_map_queues__sdma8_to_15_sel', 2)
|
||||
|
||||
class struct_pm4_mes_map_queues(c.Struct): SIZE = 0
|
||||
class enum_mes_query_status_interrupt_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
interrupt_sel__mes_query_status__completion_status = enum_mes_query_status_interrupt_sel_enum.define('interrupt_sel__mes_query_status__completion_status', 0)
|
||||
interrupt_sel__mes_query_status__process_status = enum_mes_query_status_interrupt_sel_enum.define('interrupt_sel__mes_query_status__process_status', 1)
|
||||
interrupt_sel__mes_query_status__queue_status = enum_mes_query_status_interrupt_sel_enum.define('interrupt_sel__mes_query_status__queue_status', 2)
|
||||
|
||||
class enum_mes_query_status_command_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
command__mes_query_status__interrupt_only = enum_mes_query_status_command_enum.define('command__mes_query_status__interrupt_only', 0)
|
||||
command__mes_query_status__fence_only_immediate = enum_mes_query_status_command_enum.define('command__mes_query_status__fence_only_immediate', 1)
|
||||
command__mes_query_status__fence_only_after_write_ack = enum_mes_query_status_command_enum.define('command__mes_query_status__fence_only_after_write_ack', 2)
|
||||
command__mes_query_status__fence_wait_for_write_ack_send_interrupt = enum_mes_query_status_command_enum.define('command__mes_query_status__fence_wait_for_write_ack_send_interrupt', 3)
|
||||
|
||||
class enum_mes_query_status_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
engine_sel__mes_query_status__compute = enum_mes_query_status_engine_sel_enum.define('engine_sel__mes_query_status__compute', 0)
|
||||
engine_sel__mes_query_status__sdma0_queue = enum_mes_query_status_engine_sel_enum.define('engine_sel__mes_query_status__sdma0_queue', 2)
|
||||
engine_sel__mes_query_status__sdma1_queue = enum_mes_query_status_engine_sel_enum.define('engine_sel__mes_query_status__sdma1_queue', 3)
|
||||
|
||||
class struct_pm4_mes_query_status(c.Struct): SIZE = 0
|
||||
class enum_mes_unmap_queues_action_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
action__mes_unmap_queues__preempt_queues = enum_mes_unmap_queues_action_enum.define('action__mes_unmap_queues__preempt_queues', 0)
|
||||
action__mes_unmap_queues__reset_queues = enum_mes_unmap_queues_action_enum.define('action__mes_unmap_queues__reset_queues', 1)
|
||||
action__mes_unmap_queues__disable_process_queues = enum_mes_unmap_queues_action_enum.define('action__mes_unmap_queues__disable_process_queues', 2)
|
||||
action__mes_unmap_queues__reserved = enum_mes_unmap_queues_action_enum.define('action__mes_unmap_queues__reserved', 3)
|
||||
|
||||
class enum_mes_unmap_queues_queue_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
queue_sel__mes_unmap_queues__perform_request_on_specified_queues = enum_mes_unmap_queues_queue_sel_enum.define('queue_sel__mes_unmap_queues__perform_request_on_specified_queues', 0)
|
||||
queue_sel__mes_unmap_queues__perform_request_on_pasid_queues = enum_mes_unmap_queues_queue_sel_enum.define('queue_sel__mes_unmap_queues__perform_request_on_pasid_queues', 1)
|
||||
queue_sel__mes_unmap_queues__unmap_all_queues = enum_mes_unmap_queues_queue_sel_enum.define('queue_sel__mes_unmap_queues__unmap_all_queues', 2)
|
||||
queue_sel__mes_unmap_queues__unmap_all_non_static_queues = enum_mes_unmap_queues_queue_sel_enum.define('queue_sel__mes_unmap_queues__unmap_all_non_static_queues', 3)
|
||||
|
||||
class enum_mes_unmap_queues_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
engine_sel__mes_unmap_queues__compute = enum_mes_unmap_queues_engine_sel_enum.define('engine_sel__mes_unmap_queues__compute', 0)
|
||||
engine_sel__mes_unmap_queues__sdma0 = enum_mes_unmap_queues_engine_sel_enum.define('engine_sel__mes_unmap_queues__sdma0', 2)
|
||||
engine_sel__mes_unmap_queues__sdmal = enum_mes_unmap_queues_engine_sel_enum.define('engine_sel__mes_unmap_queues__sdmal', 3)
|
||||
|
||||
class enum_mes_unmap_queues_extended_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
extended_engine_sel__mes_unmap_queues__legacy_engine_sel = enum_mes_unmap_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_unmap_queues__legacy_engine_sel', 0)
|
||||
extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel = enum_mes_unmap_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel', 1)
|
||||
|
||||
class struct_pm4_mes_unmap_queues(c.Struct): SIZE = 0
|
||||
class enum_mec_release_mem_event_index_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
event_index__mec_release_mem__end_of_pipe = enum_mec_release_mem_event_index_enum.define('event_index__mec_release_mem__end_of_pipe', 5)
|
||||
event_index__mec_release_mem__shader_done = enum_mec_release_mem_event_index_enum.define('event_index__mec_release_mem__shader_done', 6)
|
||||
|
||||
class enum_mec_release_mem_cache_policy_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
cache_policy__mec_release_mem__lru = enum_mec_release_mem_cache_policy_enum.define('cache_policy__mec_release_mem__lru', 0)
|
||||
cache_policy__mec_release_mem__stream = enum_mec_release_mem_cache_policy_enum.define('cache_policy__mec_release_mem__stream', 1)
|
||||
|
||||
class enum_mec_release_mem_pq_exe_status_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
pq_exe_status__mec_release_mem__default = enum_mec_release_mem_pq_exe_status_enum.define('pq_exe_status__mec_release_mem__default', 0)
|
||||
pq_exe_status__mec_release_mem__phase_update = enum_mec_release_mem_pq_exe_status_enum.define('pq_exe_status__mec_release_mem__phase_update', 1)
|
||||
|
||||
class enum_mec_release_mem_dst_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
dst_sel__mec_release_mem__memory_controller = enum_mec_release_mem_dst_sel_enum.define('dst_sel__mec_release_mem__memory_controller', 0)
|
||||
dst_sel__mec_release_mem__tc_l2 = enum_mec_release_mem_dst_sel_enum.define('dst_sel__mec_release_mem__tc_l2', 1)
|
||||
dst_sel__mec_release_mem__queue_write_pointer_register = enum_mec_release_mem_dst_sel_enum.define('dst_sel__mec_release_mem__queue_write_pointer_register', 2)
|
||||
dst_sel__mec_release_mem__queue_write_pointer_poll_mask_bit = enum_mec_release_mem_dst_sel_enum.define('dst_sel__mec_release_mem__queue_write_pointer_poll_mask_bit', 3)
|
||||
|
||||
class enum_mec_release_mem_int_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
int_sel__mec_release_mem__none = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__none', 0)
|
||||
int_sel__mec_release_mem__send_interrupt_only = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__send_interrupt_only', 1)
|
||||
int_sel__mec_release_mem__send_interrupt_after_write_confirm = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__send_interrupt_after_write_confirm', 2)
|
||||
int_sel__mec_release_mem__send_data_after_write_confirm = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__send_data_after_write_confirm', 3)
|
||||
int_sel__mec_release_mem__unconditionally_send_int_ctxid = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__unconditionally_send_int_ctxid', 4)
|
||||
int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_32_bit_compare = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_32_bit_compare', 5)
|
||||
int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_64_bit_compare = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_64_bit_compare', 6)
|
||||
|
||||
class enum_mec_release_mem_data_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
data_sel__mec_release_mem__none = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__none', 0)
|
||||
data_sel__mec_release_mem__send_32_bit_low = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__send_32_bit_low', 1)
|
||||
data_sel__mec_release_mem__send_64_bit_data = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__send_64_bit_data', 2)
|
||||
data_sel__mec_release_mem__send_gpu_clock_counter = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__send_gpu_clock_counter', 3)
|
||||
data_sel__mec_release_mem__send_cp_perfcounter_hi_lo = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__send_cp_perfcounter_hi_lo', 4)
|
||||
data_sel__mec_release_mem__store_gds_data_to_memory = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__store_gds_data_to_memory', 5)
|
||||
|
||||
class struct_pm4_mec_release_mem(c.Struct): SIZE = 0
|
||||
class enum_WRITE_DATA_dst_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
dst_sel___write_data__mem_mapped_register = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__mem_mapped_register', 0)
|
||||
dst_sel___write_data__tc_l2 = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__tc_l2', 2)
|
||||
dst_sel___write_data__gds = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__gds', 3)
|
||||
dst_sel___write_data__memory = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__memory', 5)
|
||||
dst_sel___write_data__memory_mapped_adc_persistent_state = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__memory_mapped_adc_persistent_state', 6)
|
||||
|
||||
class enum_WRITE_DATA_addr_incr_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
addr_incr___write_data__increment_address = enum_WRITE_DATA_addr_incr_enum.define('addr_incr___write_data__increment_address', 0)
|
||||
addr_incr___write_data__do_not_increment_address = enum_WRITE_DATA_addr_incr_enum.define('addr_incr___write_data__do_not_increment_address', 1)
|
||||
|
||||
class enum_WRITE_DATA_wr_confirm_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
wr_confirm___write_data__do_not_wait_for_write_confirmation = enum_WRITE_DATA_wr_confirm_enum.define('wr_confirm___write_data__do_not_wait_for_write_confirmation', 0)
|
||||
wr_confirm___write_data__wait_for_write_confirmation = enum_WRITE_DATA_wr_confirm_enum.define('wr_confirm___write_data__wait_for_write_confirmation', 1)
|
||||
|
||||
class enum_WRITE_DATA_cache_policy_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
cache_policy___write_data__lru = enum_WRITE_DATA_cache_policy_enum.define('cache_policy___write_data__lru', 0)
|
||||
cache_policy___write_data__stream = enum_WRITE_DATA_cache_policy_enum.define('cache_policy___write_data__stream', 1)
|
||||
|
||||
class struct_pm4_mec_write_data_mmio(c.Struct): SIZE = 0
|
||||
class _anonenum0(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
CACHE_FLUSH_AND_INV_TS_EVENT = _anonenum0.define('CACHE_FLUSH_AND_INV_TS_EVENT', 20)
|
||||
|
||||
c.init_records()
|
||||
PACKET_TYPE0 = 0 # type: ignore
|
||||
PACKET_TYPE1 = 1 # type: ignore
|
||||
PACKET_TYPE2 = 2 # type: ignore
|
||||
|
||||
@@ -1,42 +1,139 @@
|
||||
# mypy: disable-error-code="empty-body"
|
||||
from __future__ import annotations
|
||||
import ctypes
|
||||
from typing import Literal, TypeAlias
|
||||
from typing import Annotated, Literal, TypeAlias
|
||||
from tinygrad.runtime.support.c import _IO, _IOW, _IOR, _IOWR
|
||||
from tinygrad.runtime.support import c
|
||||
class union_PM4_MES_TYPE_3_HEADER(c.Struct): pass
|
||||
enum_mes_set_resources_queue_type_enum: dict[int, str] = {(queue_type__mes_set_resources__kernel_interface_queue_kiq:=0): 'queue_type__mes_set_resources__kernel_interface_queue_kiq', (queue_type__mes_set_resources__hsa_interface_queue_hiq:=1): 'queue_type__mes_set_resources__hsa_interface_queue_hiq', (queue_type__mes_set_resources__hsa_debug_interface_queue:=4): 'queue_type__mes_set_resources__hsa_debug_interface_queue'}
|
||||
class struct_pm4_mes_set_resources(c.Struct): pass
|
||||
class struct_pm4_mes_runlist(c.Struct): pass
|
||||
class struct_pm4_mes_map_process(c.Struct): pass
|
||||
class struct_PM4_MES_MAP_PROCESS_VM(c.Struct): pass
|
||||
enum_mes_map_queues_queue_sel_enum: dict[int, str] = {(queue_sel__mes_map_queues__map_to_specified_queue_slots_vi:=0): 'queue_sel__mes_map_queues__map_to_specified_queue_slots_vi', (queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi:=1): 'queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi'}
|
||||
enum_mes_map_queues_queue_type_enum: dict[int, str] = {(queue_type__mes_map_queues__normal_compute_vi:=0): 'queue_type__mes_map_queues__normal_compute_vi', (queue_type__mes_map_queues__debug_interface_queue_vi:=1): 'queue_type__mes_map_queues__debug_interface_queue_vi', (queue_type__mes_map_queues__normal_latency_static_queue_vi:=2): 'queue_type__mes_map_queues__normal_latency_static_queue_vi', (queue_type__mes_map_queues__low_latency_static_queue_vi:=3): 'queue_type__mes_map_queues__low_latency_static_queue_vi'}
|
||||
enum_mes_map_queues_engine_sel_enum: dict[int, str] = {(engine_sel__mes_map_queues__compute_vi:=0): 'engine_sel__mes_map_queues__compute_vi', (engine_sel__mes_map_queues__sdma0_vi:=2): 'engine_sel__mes_map_queues__sdma0_vi', (engine_sel__mes_map_queues__sdma1_vi:=3): 'engine_sel__mes_map_queues__sdma1_vi'}
|
||||
enum_mes_map_queues_extended_engine_sel_enum: dict[int, str] = {(extended_engine_sel__mes_map_queues__legacy_engine_sel:=0): 'extended_engine_sel__mes_map_queues__legacy_engine_sel', (extended_engine_sel__mes_map_queues__sdma0_to_7_sel:=1): 'extended_engine_sel__mes_map_queues__sdma0_to_7_sel', (extended_engine_sel__mes_map_queues__sdma8_to_15_sel:=2): 'extended_engine_sel__mes_map_queues__sdma8_to_15_sel'}
|
||||
class struct_pm4_mes_map_queues(c.Struct): pass
|
||||
enum_mes_query_status_interrupt_sel_enum: dict[int, str] = {(interrupt_sel__mes_query_status__completion_status:=0): 'interrupt_sel__mes_query_status__completion_status', (interrupt_sel__mes_query_status__process_status:=1): 'interrupt_sel__mes_query_status__process_status', (interrupt_sel__mes_query_status__queue_status:=2): 'interrupt_sel__mes_query_status__queue_status'}
|
||||
enum_mes_query_status_command_enum: dict[int, str] = {(command__mes_query_status__interrupt_only:=0): 'command__mes_query_status__interrupt_only', (command__mes_query_status__fence_only_immediate:=1): 'command__mes_query_status__fence_only_immediate', (command__mes_query_status__fence_only_after_write_ack:=2): 'command__mes_query_status__fence_only_after_write_ack', (command__mes_query_status__fence_wait_for_write_ack_send_interrupt:=3): 'command__mes_query_status__fence_wait_for_write_ack_send_interrupt'}
|
||||
enum_mes_query_status_engine_sel_enum: dict[int, str] = {(engine_sel__mes_query_status__compute:=0): 'engine_sel__mes_query_status__compute', (engine_sel__mes_query_status__sdma0_queue:=2): 'engine_sel__mes_query_status__sdma0_queue', (engine_sel__mes_query_status__sdma1_queue:=3): 'engine_sel__mes_query_status__sdma1_queue'}
|
||||
class struct_pm4_mes_query_status(c.Struct): pass
|
||||
enum_mes_unmap_queues_action_enum: dict[int, str] = {(action__mes_unmap_queues__preempt_queues:=0): 'action__mes_unmap_queues__preempt_queues', (action__mes_unmap_queues__reset_queues:=1): 'action__mes_unmap_queues__reset_queues', (action__mes_unmap_queues__disable_process_queues:=2): 'action__mes_unmap_queues__disable_process_queues', (action__mes_unmap_queues__reserved:=3): 'action__mes_unmap_queues__reserved'}
|
||||
enum_mes_unmap_queues_queue_sel_enum: dict[int, str] = {(queue_sel__mes_unmap_queues__perform_request_on_specified_queues:=0): 'queue_sel__mes_unmap_queues__perform_request_on_specified_queues', (queue_sel__mes_unmap_queues__perform_request_on_pasid_queues:=1): 'queue_sel__mes_unmap_queues__perform_request_on_pasid_queues', (queue_sel__mes_unmap_queues__unmap_all_queues:=2): 'queue_sel__mes_unmap_queues__unmap_all_queues', (queue_sel__mes_unmap_queues__unmap_all_non_static_queues:=3): 'queue_sel__mes_unmap_queues__unmap_all_non_static_queues'}
|
||||
enum_mes_unmap_queues_engine_sel_enum: dict[int, str] = {(engine_sel__mes_unmap_queues__compute:=0): 'engine_sel__mes_unmap_queues__compute', (engine_sel__mes_unmap_queues__sdma0:=2): 'engine_sel__mes_unmap_queues__sdma0', (engine_sel__mes_unmap_queues__sdmal:=3): 'engine_sel__mes_unmap_queues__sdmal'}
|
||||
enum_mes_unmap_queues_extended_engine_sel_enum: dict[int, str] = {(extended_engine_sel__mes_unmap_queues__legacy_engine_sel:=0): 'extended_engine_sel__mes_unmap_queues__legacy_engine_sel', (extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel:=1): 'extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel'}
|
||||
class struct_pm4_mes_unmap_queues(c.Struct): pass
|
||||
enum_mec_release_mem_event_index_enum: dict[int, str] = {(event_index__mec_release_mem__end_of_pipe:=5): 'event_index__mec_release_mem__end_of_pipe', (event_index__mec_release_mem__shader_done:=6): 'event_index__mec_release_mem__shader_done'}
|
||||
enum_mec_release_mem_cache_policy_enum: dict[int, str] = {(cache_policy__mec_release_mem__lru:=0): 'cache_policy__mec_release_mem__lru', (cache_policy__mec_release_mem__stream:=1): 'cache_policy__mec_release_mem__stream'}
|
||||
enum_mec_release_mem_pq_exe_status_enum: dict[int, str] = {(pq_exe_status__mec_release_mem__default:=0): 'pq_exe_status__mec_release_mem__default', (pq_exe_status__mec_release_mem__phase_update:=1): 'pq_exe_status__mec_release_mem__phase_update'}
|
||||
enum_mec_release_mem_dst_sel_enum: dict[int, str] = {(dst_sel__mec_release_mem__memory_controller:=0): 'dst_sel__mec_release_mem__memory_controller', (dst_sel__mec_release_mem__tc_l2:=1): 'dst_sel__mec_release_mem__tc_l2', (dst_sel__mec_release_mem__queue_write_pointer_register:=2): 'dst_sel__mec_release_mem__queue_write_pointer_register', (dst_sel__mec_release_mem__queue_write_pointer_poll_mask_bit:=3): 'dst_sel__mec_release_mem__queue_write_pointer_poll_mask_bit'}
|
||||
enum_mec_release_mem_int_sel_enum: dict[int, str] = {(int_sel__mec_release_mem__none:=0): 'int_sel__mec_release_mem__none', (int_sel__mec_release_mem__send_interrupt_only:=1): 'int_sel__mec_release_mem__send_interrupt_only', (int_sel__mec_release_mem__send_interrupt_after_write_confirm:=2): 'int_sel__mec_release_mem__send_interrupt_after_write_confirm', (int_sel__mec_release_mem__send_data_after_write_confirm:=3): 'int_sel__mec_release_mem__send_data_after_write_confirm', (int_sel__mec_release_mem__unconditionally_send_int_ctxid:=4): 'int_sel__mec_release_mem__unconditionally_send_int_ctxid', (int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_32_bit_compare:=5): 'int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_32_bit_compare', (int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_64_bit_compare:=6): 'int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_64_bit_compare'}
|
||||
enum_mec_release_mem_data_sel_enum: dict[int, str] = {(data_sel__mec_release_mem__none:=0): 'data_sel__mec_release_mem__none', (data_sel__mec_release_mem__send_32_bit_low:=1): 'data_sel__mec_release_mem__send_32_bit_low', (data_sel__mec_release_mem__send_64_bit_data:=2): 'data_sel__mec_release_mem__send_64_bit_data', (data_sel__mec_release_mem__send_gpu_clock_counter:=3): 'data_sel__mec_release_mem__send_gpu_clock_counter', (data_sel__mec_release_mem__send_cp_perfcounter_hi_lo:=4): 'data_sel__mec_release_mem__send_cp_perfcounter_hi_lo', (data_sel__mec_release_mem__store_gds_data_to_memory:=5): 'data_sel__mec_release_mem__store_gds_data_to_memory'}
|
||||
class struct_pm4_mec_release_mem(c.Struct): pass
|
||||
enum_WRITE_DATA_dst_sel_enum: dict[int, str] = {(dst_sel___write_data__mem_mapped_register:=0): 'dst_sel___write_data__mem_mapped_register', (dst_sel___write_data__tc_l2:=2): 'dst_sel___write_data__tc_l2', (dst_sel___write_data__gds:=3): 'dst_sel___write_data__gds', (dst_sel___write_data__memory:=5): 'dst_sel___write_data__memory', (dst_sel___write_data__memory_mapped_adc_persistent_state:=6): 'dst_sel___write_data__memory_mapped_adc_persistent_state'}
|
||||
enum_WRITE_DATA_addr_incr_enum: dict[int, str] = {(addr_incr___write_data__increment_address:=0): 'addr_incr___write_data__increment_address', (addr_incr___write_data__do_not_increment_address:=1): 'addr_incr___write_data__do_not_increment_address'}
|
||||
enum_WRITE_DATA_wr_confirm_enum: dict[int, str] = {(wr_confirm___write_data__do_not_wait_for_write_confirmation:=0): 'wr_confirm___write_data__do_not_wait_for_write_confirmation', (wr_confirm___write_data__wait_for_write_confirmation:=1): 'wr_confirm___write_data__wait_for_write_confirmation'}
|
||||
enum_WRITE_DATA_cache_policy_enum: dict[int, str] = {(cache_policy___write_data__lru:=0): 'cache_policy___write_data__lru', (cache_policy___write_data__stream:=1): 'cache_policy___write_data__stream'}
|
||||
class struct_pm4_mec_write_data_mmio(c.Struct): pass
|
||||
_anonenum0: dict[int, str] = {(CACHE_FLUSH_AND_INV_TS_EVENT:=20): 'CACHE_FLUSH_AND_INV_TS_EVENT'}
|
||||
class union_PM4_MES_TYPE_3_HEADER(c.Struct): SIZE = 0
|
||||
class enum_mes_set_resources_queue_type_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
queue_type__mes_set_resources__kernel_interface_queue_kiq = enum_mes_set_resources_queue_type_enum.define('queue_type__mes_set_resources__kernel_interface_queue_kiq', 0)
|
||||
queue_type__mes_set_resources__hsa_interface_queue_hiq = enum_mes_set_resources_queue_type_enum.define('queue_type__mes_set_resources__hsa_interface_queue_hiq', 1)
|
||||
queue_type__mes_set_resources__hsa_debug_interface_queue = enum_mes_set_resources_queue_type_enum.define('queue_type__mes_set_resources__hsa_debug_interface_queue', 4)
|
||||
|
||||
class struct_pm4_mes_set_resources(c.Struct): SIZE = 0
|
||||
class struct_pm4_mes_runlist(c.Struct): SIZE = 0
|
||||
class struct_pm4_mes_map_process(c.Struct): SIZE = 0
|
||||
class struct_PM4_MES_MAP_PROCESS_VM(c.Struct): SIZE = 0
|
||||
class enum_mes_map_queues_queue_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
queue_sel__mes_map_queues__map_to_specified_queue_slots_vi = enum_mes_map_queues_queue_sel_enum.define('queue_sel__mes_map_queues__map_to_specified_queue_slots_vi', 0)
|
||||
queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi = enum_mes_map_queues_queue_sel_enum.define('queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi', 1)
|
||||
|
||||
class enum_mes_map_queues_queue_type_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
queue_type__mes_map_queues__normal_compute_vi = enum_mes_map_queues_queue_type_enum.define('queue_type__mes_map_queues__normal_compute_vi', 0)
|
||||
queue_type__mes_map_queues__debug_interface_queue_vi = enum_mes_map_queues_queue_type_enum.define('queue_type__mes_map_queues__debug_interface_queue_vi', 1)
|
||||
queue_type__mes_map_queues__normal_latency_static_queue_vi = enum_mes_map_queues_queue_type_enum.define('queue_type__mes_map_queues__normal_latency_static_queue_vi', 2)
|
||||
queue_type__mes_map_queues__low_latency_static_queue_vi = enum_mes_map_queues_queue_type_enum.define('queue_type__mes_map_queues__low_latency_static_queue_vi', 3)
|
||||
|
||||
class enum_mes_map_queues_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
engine_sel__mes_map_queues__compute_vi = enum_mes_map_queues_engine_sel_enum.define('engine_sel__mes_map_queues__compute_vi', 0)
|
||||
engine_sel__mes_map_queues__sdma0_vi = enum_mes_map_queues_engine_sel_enum.define('engine_sel__mes_map_queues__sdma0_vi', 2)
|
||||
engine_sel__mes_map_queues__sdma1_vi = enum_mes_map_queues_engine_sel_enum.define('engine_sel__mes_map_queues__sdma1_vi', 3)
|
||||
|
||||
class enum_mes_map_queues_extended_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
extended_engine_sel__mes_map_queues__legacy_engine_sel = enum_mes_map_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_map_queues__legacy_engine_sel', 0)
|
||||
extended_engine_sel__mes_map_queues__sdma0_to_7_sel = enum_mes_map_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_map_queues__sdma0_to_7_sel', 1)
|
||||
extended_engine_sel__mes_map_queues__sdma8_to_15_sel = enum_mes_map_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_map_queues__sdma8_to_15_sel', 2)
|
||||
|
||||
class struct_pm4_mes_map_queues(c.Struct): SIZE = 0
|
||||
class enum_mes_query_status_interrupt_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
interrupt_sel__mes_query_status__completion_status = enum_mes_query_status_interrupt_sel_enum.define('interrupt_sel__mes_query_status__completion_status', 0)
|
||||
interrupt_sel__mes_query_status__process_status = enum_mes_query_status_interrupt_sel_enum.define('interrupt_sel__mes_query_status__process_status', 1)
|
||||
interrupt_sel__mes_query_status__queue_status = enum_mes_query_status_interrupt_sel_enum.define('interrupt_sel__mes_query_status__queue_status', 2)
|
||||
|
||||
class enum_mes_query_status_command_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
command__mes_query_status__interrupt_only = enum_mes_query_status_command_enum.define('command__mes_query_status__interrupt_only', 0)
|
||||
command__mes_query_status__fence_only_immediate = enum_mes_query_status_command_enum.define('command__mes_query_status__fence_only_immediate', 1)
|
||||
command__mes_query_status__fence_only_after_write_ack = enum_mes_query_status_command_enum.define('command__mes_query_status__fence_only_after_write_ack', 2)
|
||||
command__mes_query_status__fence_wait_for_write_ack_send_interrupt = enum_mes_query_status_command_enum.define('command__mes_query_status__fence_wait_for_write_ack_send_interrupt', 3)
|
||||
|
||||
class enum_mes_query_status_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
engine_sel__mes_query_status__compute = enum_mes_query_status_engine_sel_enum.define('engine_sel__mes_query_status__compute', 0)
|
||||
engine_sel__mes_query_status__sdma0_queue = enum_mes_query_status_engine_sel_enum.define('engine_sel__mes_query_status__sdma0_queue', 2)
|
||||
engine_sel__mes_query_status__sdma1_queue = enum_mes_query_status_engine_sel_enum.define('engine_sel__mes_query_status__sdma1_queue', 3)
|
||||
|
||||
class struct_pm4_mes_query_status(c.Struct): SIZE = 0
|
||||
class enum_mes_unmap_queues_action_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
action__mes_unmap_queues__preempt_queues = enum_mes_unmap_queues_action_enum.define('action__mes_unmap_queues__preempt_queues', 0)
|
||||
action__mes_unmap_queues__reset_queues = enum_mes_unmap_queues_action_enum.define('action__mes_unmap_queues__reset_queues', 1)
|
||||
action__mes_unmap_queues__disable_process_queues = enum_mes_unmap_queues_action_enum.define('action__mes_unmap_queues__disable_process_queues', 2)
|
||||
action__mes_unmap_queues__reserved = enum_mes_unmap_queues_action_enum.define('action__mes_unmap_queues__reserved', 3)
|
||||
|
||||
class enum_mes_unmap_queues_queue_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
queue_sel__mes_unmap_queues__perform_request_on_specified_queues = enum_mes_unmap_queues_queue_sel_enum.define('queue_sel__mes_unmap_queues__perform_request_on_specified_queues', 0)
|
||||
queue_sel__mes_unmap_queues__perform_request_on_pasid_queues = enum_mes_unmap_queues_queue_sel_enum.define('queue_sel__mes_unmap_queues__perform_request_on_pasid_queues', 1)
|
||||
queue_sel__mes_unmap_queues__unmap_all_queues = enum_mes_unmap_queues_queue_sel_enum.define('queue_sel__mes_unmap_queues__unmap_all_queues', 2)
|
||||
queue_sel__mes_unmap_queues__unmap_all_non_static_queues = enum_mes_unmap_queues_queue_sel_enum.define('queue_sel__mes_unmap_queues__unmap_all_non_static_queues', 3)
|
||||
|
||||
class enum_mes_unmap_queues_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
engine_sel__mes_unmap_queues__compute = enum_mes_unmap_queues_engine_sel_enum.define('engine_sel__mes_unmap_queues__compute', 0)
|
||||
engine_sel__mes_unmap_queues__sdma0 = enum_mes_unmap_queues_engine_sel_enum.define('engine_sel__mes_unmap_queues__sdma0', 2)
|
||||
engine_sel__mes_unmap_queues__sdmal = enum_mes_unmap_queues_engine_sel_enum.define('engine_sel__mes_unmap_queues__sdmal', 3)
|
||||
|
||||
class enum_mes_unmap_queues_extended_engine_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
extended_engine_sel__mes_unmap_queues__legacy_engine_sel = enum_mes_unmap_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_unmap_queues__legacy_engine_sel', 0)
|
||||
extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel = enum_mes_unmap_queues_extended_engine_sel_enum.define('extended_engine_sel__mes_unmap_queues__sdma0_to_7_sel', 1)
|
||||
|
||||
class struct_pm4_mes_unmap_queues(c.Struct): SIZE = 0
|
||||
class enum_mec_release_mem_event_index_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
event_index__mec_release_mem__end_of_pipe = enum_mec_release_mem_event_index_enum.define('event_index__mec_release_mem__end_of_pipe', 5)
|
||||
event_index__mec_release_mem__shader_done = enum_mec_release_mem_event_index_enum.define('event_index__mec_release_mem__shader_done', 6)
|
||||
|
||||
class enum_mec_release_mem_cache_policy_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
cache_policy__mec_release_mem__lru = enum_mec_release_mem_cache_policy_enum.define('cache_policy__mec_release_mem__lru', 0)
|
||||
cache_policy__mec_release_mem__stream = enum_mec_release_mem_cache_policy_enum.define('cache_policy__mec_release_mem__stream', 1)
|
||||
|
||||
class enum_mec_release_mem_pq_exe_status_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
pq_exe_status__mec_release_mem__default = enum_mec_release_mem_pq_exe_status_enum.define('pq_exe_status__mec_release_mem__default', 0)
|
||||
pq_exe_status__mec_release_mem__phase_update = enum_mec_release_mem_pq_exe_status_enum.define('pq_exe_status__mec_release_mem__phase_update', 1)
|
||||
|
||||
class enum_mec_release_mem_dst_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
dst_sel__mec_release_mem__memory_controller = enum_mec_release_mem_dst_sel_enum.define('dst_sel__mec_release_mem__memory_controller', 0)
|
||||
dst_sel__mec_release_mem__tc_l2 = enum_mec_release_mem_dst_sel_enum.define('dst_sel__mec_release_mem__tc_l2', 1)
|
||||
dst_sel__mec_release_mem__queue_write_pointer_register = enum_mec_release_mem_dst_sel_enum.define('dst_sel__mec_release_mem__queue_write_pointer_register', 2)
|
||||
dst_sel__mec_release_mem__queue_write_pointer_poll_mask_bit = enum_mec_release_mem_dst_sel_enum.define('dst_sel__mec_release_mem__queue_write_pointer_poll_mask_bit', 3)
|
||||
|
||||
class enum_mec_release_mem_int_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
int_sel__mec_release_mem__none = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__none', 0)
|
||||
int_sel__mec_release_mem__send_interrupt_only = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__send_interrupt_only', 1)
|
||||
int_sel__mec_release_mem__send_interrupt_after_write_confirm = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__send_interrupt_after_write_confirm', 2)
|
||||
int_sel__mec_release_mem__send_data_after_write_confirm = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__send_data_after_write_confirm', 3)
|
||||
int_sel__mec_release_mem__unconditionally_send_int_ctxid = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__unconditionally_send_int_ctxid', 4)
|
||||
int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_32_bit_compare = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_32_bit_compare', 5)
|
||||
int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_64_bit_compare = enum_mec_release_mem_int_sel_enum.define('int_sel__mec_release_mem__conditionally_send_int_ctxid_based_on_64_bit_compare', 6)
|
||||
|
||||
class enum_mec_release_mem_data_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
data_sel__mec_release_mem__none = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__none', 0)
|
||||
data_sel__mec_release_mem__send_32_bit_low = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__send_32_bit_low', 1)
|
||||
data_sel__mec_release_mem__send_64_bit_data = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__send_64_bit_data', 2)
|
||||
data_sel__mec_release_mem__send_gpu_clock_counter = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__send_gpu_clock_counter', 3)
|
||||
data_sel__mec_release_mem__send_cp_perfcounter_hi_lo = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__send_cp_perfcounter_hi_lo', 4)
|
||||
data_sel__mec_release_mem__store_gds_data_to_memory = enum_mec_release_mem_data_sel_enum.define('data_sel__mec_release_mem__store_gds_data_to_memory', 5)
|
||||
|
||||
class struct_pm4_mec_release_mem(c.Struct): SIZE = 0
|
||||
class enum_WRITE_DATA_dst_sel_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
dst_sel___write_data__mem_mapped_register = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__mem_mapped_register', 0)
|
||||
dst_sel___write_data__tc_l2 = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__tc_l2', 2)
|
||||
dst_sel___write_data__gds = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__gds', 3)
|
||||
dst_sel___write_data__memory = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__memory', 5)
|
||||
dst_sel___write_data__memory_mapped_adc_persistent_state = enum_WRITE_DATA_dst_sel_enum.define('dst_sel___write_data__memory_mapped_adc_persistent_state', 6)
|
||||
|
||||
class enum_WRITE_DATA_addr_incr_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
addr_incr___write_data__increment_address = enum_WRITE_DATA_addr_incr_enum.define('addr_incr___write_data__increment_address', 0)
|
||||
addr_incr___write_data__do_not_increment_address = enum_WRITE_DATA_addr_incr_enum.define('addr_incr___write_data__do_not_increment_address', 1)
|
||||
|
||||
class enum_WRITE_DATA_wr_confirm_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
wr_confirm___write_data__do_not_wait_for_write_confirmation = enum_WRITE_DATA_wr_confirm_enum.define('wr_confirm___write_data__do_not_wait_for_write_confirmation', 0)
|
||||
wr_confirm___write_data__wait_for_write_confirmation = enum_WRITE_DATA_wr_confirm_enum.define('wr_confirm___write_data__wait_for_write_confirmation', 1)
|
||||
|
||||
class enum_WRITE_DATA_cache_policy_enum(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
cache_policy___write_data__lru = enum_WRITE_DATA_cache_policy_enum.define('cache_policy___write_data__lru', 0)
|
||||
cache_policy___write_data__stream = enum_WRITE_DATA_cache_policy_enum.define('cache_policy___write_data__stream', 1)
|
||||
|
||||
class struct_pm4_mec_write_data_mmio(c.Struct): SIZE = 0
|
||||
class _anonenum0(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
CACHE_FLUSH_AND_INV_TS_EVENT = _anonenum0.define('CACHE_FLUSH_AND_INV_TS_EVENT', 20)
|
||||
|
||||
c.init_records()
|
||||
GFX9_NUM_GFX_RINGS = 1 # type: ignore
|
||||
GFX9_NUM_COMPUTE_RINGS = 8 # type: ignore
|
||||
PACKET_TYPE0 = 0 # type: ignore
|
||||
|
||||
@@ -1,515 +1,453 @@
|
||||
# mypy: disable-error-code="empty-body"
|
||||
from __future__ import annotations
|
||||
import ctypes
|
||||
from typing import Literal, TypeAlias
|
||||
from typing import Annotated, Literal, TypeAlias
|
||||
from tinygrad.runtime.support.c import _IO, _IOW, _IOR, _IOWR
|
||||
from tinygrad.runtime.support import c
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG(c.Struct):
|
||||
SIZE = 28
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION
|
||||
COUNT_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION
|
||||
PARAMETER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION
|
||||
SRC_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION
|
||||
SRC_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION, 0]
|
||||
COUNT_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION, 4]
|
||||
PARAMETER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION, 8]
|
||||
SRC_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION, 12]
|
||||
SRC_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION, 16]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION, 20]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION, 24]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
extra_info: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('extra_info', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
extra_info: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
count: int
|
||||
reserved_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION.register_fields([('count', ctypes.c_uint32, 0, 22, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 6), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
count: Annotated[Annotated[int, ctypes.c_uint32], 0, 22, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 6]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
reserved_0: int
|
||||
dst_swap: int
|
||||
reserved_1: int
|
||||
src_swap: int
|
||||
reserved_2: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION.register_fields([('reserved_0', ctypes.c_uint32, 0, 16, 0), ('dst_swap', ctypes.c_uint32, 2, 2, 0), ('reserved_1', ctypes.c_uint32, 2, 6, 2), ('src_swap', ctypes.c_uint32, 3, 2, 0), ('reserved_2', ctypes.c_uint32, 3, 6, 2), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
dst_swap: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 2, 6, 2]
|
||||
src_swap: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION.register_fields([('src_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_63_32: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION.register_fields([('src_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION, 0), ('COUNT_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION, 4), ('PARAMETER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION, 8), ('SRC_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION, 12), ('SRC_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION, 16), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION, 20), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION, 24)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR: TypeAlias = rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG(c.Struct):
|
||||
SIZE = 52
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION
|
||||
SRC_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION
|
||||
SRC_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION
|
||||
SRC_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION
|
||||
SRC_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION
|
||||
SRC_PARAMETER_3_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION
|
||||
DST_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION
|
||||
DST_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION
|
||||
DST_PARAMETER_3_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION
|
||||
RECT_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION
|
||||
RECT_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION, 0]
|
||||
SRC_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION, 4]
|
||||
SRC_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION, 8]
|
||||
SRC_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION, 12]
|
||||
SRC_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION, 16]
|
||||
SRC_PARAMETER_3_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION, 20]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION, 24]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION, 28]
|
||||
DST_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION, 32]
|
||||
DST_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION, 36]
|
||||
DST_PARAMETER_3_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION, 40]
|
||||
RECT_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION, 44]
|
||||
RECT_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION, 48]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved: int
|
||||
element: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved', ctypes.c_uint32, 2, 13, 0), ('element', ctypes.c_uint32, 3, 3, 5), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved: Annotated[Annotated[int, ctypes.c_uint32], 2, 13, 0]
|
||||
element: Annotated[Annotated[int, ctypes.c_uint32], 3, 3, 5]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION.register_fields([('src_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION.register_fields([('src_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_offset_x: int
|
||||
reserved_1: int
|
||||
src_offset_y: int
|
||||
reserved_2: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION.register_fields([('src_offset_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('src_offset_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_offset_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
src_offset_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_offset_z: int
|
||||
reserved_1: int
|
||||
src_pitch: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION.register_fields([('src_offset_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 3), ('src_pitch', ctypes.c_uint32, 1, 19, 5), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_offset_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 3]
|
||||
src_pitch: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_slice_pitch: int
|
||||
reserved_1: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION.register_fields([('src_slice_pitch', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
src_slice_pitch: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_7_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_7_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_7_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_offset_x: int
|
||||
reserved_1: int
|
||||
dst_offset_y: int
|
||||
reserved_2: int
|
||||
DW_8_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION.register_fields([('dst_offset_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('dst_offset_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_8_DATA', ctypes.c_uint32, 0)])
|
||||
dst_offset_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
dst_offset_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_8_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_offset_z: int
|
||||
reserved_1: int
|
||||
dst_pitch: int
|
||||
DW_9_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION.register_fields([('dst_offset_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 3), ('dst_pitch', ctypes.c_uint32, 1, 19, 5), ('DW_9_DATA', ctypes.c_uint32, 0)])
|
||||
dst_offset_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 3]
|
||||
dst_pitch: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_9_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_slice_pitch: int
|
||||
reserved_1: int
|
||||
DW_10_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION.register_fields([('dst_slice_pitch', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_10_DATA', ctypes.c_uint32, 0)])
|
||||
dst_slice_pitch: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_10_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
rect_x: int
|
||||
reserved_1: int
|
||||
rect_y: int
|
||||
reserved_2: int
|
||||
DW_11_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION.register_fields([('rect_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('rect_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_11_DATA', ctypes.c_uint32, 0)])
|
||||
rect_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
rect_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_11_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
rect_z: int
|
||||
reserved_1: int
|
||||
dst_swap: int
|
||||
reserved_2: int
|
||||
src_swap: int
|
||||
reserved_3: int
|
||||
DW_12_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION.register_fields([('rect_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 5, 3), ('dst_swap', ctypes.c_uint32, 2, 2, 0), ('reserved_2', ctypes.c_uint32, 2, 6, 2), ('src_swap', ctypes.c_uint32, 3, 2, 0), ('reserved_3', ctypes.c_uint32, 3, 6, 2), ('DW_12_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION, 0), ('SRC_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION, 4), ('SRC_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION, 8), ('SRC_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION, 12), ('SRC_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION, 16), ('SRC_PARAMETER_3_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION, 20), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION, 24), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION, 28), ('DST_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION, 32), ('DST_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION, 36), ('DST_PARAMETER_3_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION, 40), ('RECT_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION, 44), ('RECT_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION, 48)])
|
||||
rect_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 5, 3]
|
||||
dst_swap: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 2, 6, 2]
|
||||
src_swap: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_3: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_12_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT: TypeAlias = rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG(c.Struct):
|
||||
SIZE = 20
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION
|
||||
DATA_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION
|
||||
COUNT_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION, 0]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION, 4]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION, 8]
|
||||
DATA_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION, 12]
|
||||
COUNT_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION, 16]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
sw: int
|
||||
reserved_0: int
|
||||
fillsize: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('sw', ctypes.c_uint32, 2, 2, 0), ('reserved_0', ctypes.c_uint32, 2, 12, 2), ('fillsize', ctypes.c_uint32, 3, 2, 6), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
sw: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 12, 2]
|
||||
fillsize: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION.register_fields([('src_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
count: int
|
||||
reserved_0: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION.register_fields([('count', ctypes.c_uint32, 0, 22, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 6), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION, 0), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION, 4), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION, 8), ('DATA_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION, 12), ('COUNT_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION, 16)])
|
||||
count: Annotated[Annotated[int, ctypes.c_uint32], 0, 22, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 6]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL: TypeAlias = rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG(c.Struct):
|
||||
SIZE = 16
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION
|
||||
DATA_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION, 8]
|
||||
DATA_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION, 12]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
mtype: int
|
||||
gcc: int
|
||||
sys: int
|
||||
pad1: int
|
||||
snp: int
|
||||
gpa: int
|
||||
l2_policy: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('mtype', ctypes.c_uint32, 2, 3, 0), ('gcc', ctypes.c_uint32, 2, 1, 3), ('sys', ctypes.c_uint32, 2, 1, 4), ('pad1', ctypes.c_uint32, 2, 1, 5), ('snp', ctypes.c_uint32, 2, 1, 6), ('gpa', ctypes.c_uint32, 2, 1, 7), ('l2_policy', ctypes.c_uint32, 3, 2, 0), ('reserved_0', ctypes.c_uint32, 3, 6, 2), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
mtype: Annotated[Annotated[int, ctypes.c_uint32], 2, 3, 0]
|
||||
gcc: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 3]
|
||||
sys: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 4]
|
||||
pad1: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 5]
|
||||
snp: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 6]
|
||||
gpa: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 7]
|
||||
l2_policy: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
data: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION.register_fields([('data', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION, 8), ('DATA_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION, 12)])
|
||||
data: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_FENCE: TypeAlias = rocr_AMD_SDMA_PKT_FENCE_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG(c.Struct):
|
||||
SIZE = 24
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION
|
||||
VALUE_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION
|
||||
MASK_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION
|
||||
DW5_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION, 8]
|
||||
VALUE_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION, 12]
|
||||
MASK_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION, 16]
|
||||
DW5_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION, 20]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
hdp_flush: int
|
||||
reserved_1: int
|
||||
func: int
|
||||
mem_poll: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 0), ('hdp_flush', ctypes.c_uint32, 3, 1, 2), ('reserved_1', ctypes.c_uint32, 3, 1, 3), ('func', ctypes.c_uint32, 3, 3, 4), ('mem_poll', ctypes.c_uint32, 3, 1, 7), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 0]
|
||||
hdp_flush: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 2]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 3]
|
||||
func: Annotated[Annotated[int, ctypes.c_uint32], 3, 3, 4]
|
||||
mem_poll: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 7]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
value: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION.register_fields([('value', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
value: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
mask: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION.register_fields([('mask', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
mask: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
interval: int
|
||||
retry_count: int
|
||||
reserved_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION.register_fields([('interval', ctypes.c_uint32, 0, 16, 0), ('retry_count', ctypes.c_uint32, 2, 12, 0), ('reserved_0', ctypes.c_uint32, 3, 4, 4), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION, 8), ('VALUE_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION, 12), ('MASK_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION, 16), ('DW5_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION, 20)])
|
||||
interval: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
retry_count: Annotated[Annotated[int, ctypes.c_uint32], 2, 12, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM: TypeAlias = rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG(c.Struct):
|
||||
SIZE = 32
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION
|
||||
SRC_DATA_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION
|
||||
SRC_DATA_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION
|
||||
CMP_DATA_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION
|
||||
CMP_DATA_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION
|
||||
LOOP_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION, 8]
|
||||
SRC_DATA_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION, 12]
|
||||
SRC_DATA_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION, 16]
|
||||
CMP_DATA_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION, 20]
|
||||
CMP_DATA_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION, 24]
|
||||
LOOP_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION, 28]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
l: int
|
||||
reserved_0: int
|
||||
operation: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('l', ctypes.c_uint32, 2, 1, 0), ('reserved_0', ctypes.c_uint32, 2, 8, 1), ('operation', ctypes.c_uint32, 3, 7, 1), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
l: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 8, 1]
|
||||
operation: Annotated[Annotated[int, ctypes.c_uint32], 3, 7, 1]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION.register_fields([('src_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_63_32: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION.register_fields([('src_data_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
cmp_data_31_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION.register_fields([('cmp_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
cmp_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
cmp_data_63_32: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION.register_fields([('cmp_data_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
cmp_data_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
loop_interval: int
|
||||
reserved_0: int
|
||||
DW_7_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION.register_fields([('loop_interval', ctypes.c_uint32, 0, 13, 0), ('reserved_0', ctypes.c_uint32, 1, 19, 5), ('DW_7_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION, 8), ('SRC_DATA_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION, 12), ('SRC_DATA_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION, 16), ('CMP_DATA_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION, 20), ('CMP_DATA_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION, 24), ('LOOP_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION, 28)])
|
||||
loop_interval: Annotated[Annotated[int, ctypes.c_uint32], 0, 13, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_7_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_ATOMIC: TypeAlias = rocr_AMD_SDMA_PKT_ATOMIC_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG(c.Struct):
|
||||
SIZE = 12
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION, 8]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION, 8)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP: TypeAlias = rocr_AMD_SDMA_PKT_TIMESTAMP_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG(c.Struct):
|
||||
SIZE = 8
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION
|
||||
INT_CONTEXT_UNION: rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION, 0]
|
||||
INT_CONTEXT_UNION: Annotated[rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION, 4]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
int_ctx: int
|
||||
reserved_1: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION.register_fields([('int_ctx', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION, 0), ('INT_CONTEXT_UNION', rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION, 4)])
|
||||
int_ctx: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_TRAP: TypeAlias = rocr_AMD_SDMA_PKT_TRAP_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG(c.Struct):
|
||||
SIZE = 24
|
||||
DW_0_DATA: int
|
||||
DW_1_DATA: int
|
||||
DW_2_DATA: int
|
||||
DW_3_DATA: int
|
||||
DW_4_DATA: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG.register_fields([('DW_0_DATA', ctypes.c_uint32, 0), ('DW_1_DATA', ctypes.c_uint32, 4), ('DW_2_DATA', ctypes.c_uint32, 8), ('DW_3_DATA', ctypes.c_uint32, 12), ('DW_4_DATA', ctypes.c_uint32, 16), ('DW_5_DATA', ctypes.c_uint32, 20)])
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 4]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 8]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 12]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 16]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 20]
|
||||
rocr_AMD_SDMA_PKT_HDP_FLUSH: TypeAlias = rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG(c.Struct):
|
||||
SIZE = 20
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION
|
||||
WORD1_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION
|
||||
WORD2_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION
|
||||
WORD3_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION
|
||||
WORD4_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION, 0]
|
||||
WORD1_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION, 4]
|
||||
WORD2_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION, 8]
|
||||
WORD3_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION, 12]
|
||||
WORD4_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION, 16]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
BaseVA_LO: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION.register_fields([('BaseVA_LO', ctypes.c_uint32, 0, 25, 7), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
BaseVA_LO: Annotated[Annotated[int, ctypes.c_uint32], 0, 25, 7]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
BaseVA_HI: int
|
||||
GCR_CONTROL_GLI_INV: int
|
||||
GCR_CONTROL_GL1_RANGE: int
|
||||
GCR_CONTROL_GLM_WB: int
|
||||
GCR_CONTROL_GLM_INV: int
|
||||
GCR_CONTROL_GLK_WB: int
|
||||
GCR_CONTROL_GLK_INV: int
|
||||
GCR_CONTROL_GLV_INV: int
|
||||
GCR_CONTROL_GL1_INV: int
|
||||
GCR_CONTROL_GL2_US: int
|
||||
GCR_CONTROL_GL2_RANGE: int
|
||||
GCR_CONTROL_GL2_DISCARD: int
|
||||
GCR_CONTROL_GL2_INV: int
|
||||
GCR_CONTROL_GL2_WB: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION.register_fields([('BaseVA_HI', ctypes.c_uint32, 0, 16, 0), ('GCR_CONTROL_GLI_INV', ctypes.c_uint32, 2, 2, 0), ('GCR_CONTROL_GL1_RANGE', ctypes.c_uint32, 2, 2, 2), ('GCR_CONTROL_GLM_WB', ctypes.c_uint32, 2, 1, 4), ('GCR_CONTROL_GLM_INV', ctypes.c_uint32, 2, 1, 5), ('GCR_CONTROL_GLK_WB', ctypes.c_uint32, 2, 1, 6), ('GCR_CONTROL_GLK_INV', ctypes.c_uint32, 2, 1, 7), ('GCR_CONTROL_GLV_INV', ctypes.c_uint32, 3, 1, 0), ('GCR_CONTROL_GL1_INV', ctypes.c_uint32, 3, 1, 1), ('GCR_CONTROL_GL2_US', ctypes.c_uint32, 3, 1, 2), ('GCR_CONTROL_GL2_RANGE', ctypes.c_uint32, 3, 2, 3), ('GCR_CONTROL_GL2_DISCARD', ctypes.c_uint32, 3, 1, 5), ('GCR_CONTROL_GL2_INV', ctypes.c_uint32, 3, 1, 6), ('GCR_CONTROL_GL2_WB', ctypes.c_uint32, 3, 1, 7), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
BaseVA_HI: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
GCR_CONTROL_GLI_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
GCR_CONTROL_GL1_RANGE: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 2]
|
||||
GCR_CONTROL_GLM_WB: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 4]
|
||||
GCR_CONTROL_GLM_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 5]
|
||||
GCR_CONTROL_GLK_WB: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 6]
|
||||
GCR_CONTROL_GLK_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 7]
|
||||
GCR_CONTROL_GLV_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 0]
|
||||
GCR_CONTROL_GL1_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 1]
|
||||
GCR_CONTROL_GL2_US: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 2]
|
||||
GCR_CONTROL_GL2_RANGE: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 3]
|
||||
GCR_CONTROL_GL2_DISCARD: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 5]
|
||||
GCR_CONTROL_GL2_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 6]
|
||||
GCR_CONTROL_GL2_WB: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 7]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
GCR_CONTROL_RANGE_IS_PA: int
|
||||
GCR_CONTROL_SEQ: int
|
||||
LimitVA_LO: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION.register_fields([('GCR_CONTROL_RANGE_IS_PA', ctypes.c_uint32, 0, 1, 0), ('GCR_CONTROL_SEQ', ctypes.c_uint32, 0, 2, 1), ('LimitVA_LO', ctypes.c_uint32, 0, 25, 7), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
GCR_CONTROL_RANGE_IS_PA: Annotated[Annotated[int, ctypes.c_uint32], 0, 1, 0]
|
||||
GCR_CONTROL_SEQ: Annotated[Annotated[int, ctypes.c_uint32], 0, 2, 1]
|
||||
LimitVA_LO: Annotated[Annotated[int, ctypes.c_uint32], 0, 25, 7]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
LimitVA_HI: int
|
||||
VMID: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION.register_fields([('LimitVA_HI', ctypes.c_uint32, 0, 16, 0), ('VMID', ctypes.c_uint32, 3, 4, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION, 0), ('WORD1_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION, 4), ('WORD2_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION, 8), ('WORD3_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION, 12), ('WORD4_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION, 16)])
|
||||
LimitVA_HI: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
VMID: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_GCR: TypeAlias = rocr_AMD_SDMA_PKT_GCR_TAG
|
||||
c.init_records()
|
||||
SDMA_OP_COPY = 1 # type: ignore
|
||||
SDMA_OP_FENCE = 5 # type: ignore
|
||||
SDMA_OP_TRAP = 6 # type: ignore
|
||||
|
||||
@@ -1,515 +1,453 @@
|
||||
# mypy: disable-error-code="empty-body"
|
||||
from __future__ import annotations
|
||||
import ctypes
|
||||
from typing import Literal, TypeAlias
|
||||
from typing import Annotated, Literal, TypeAlias
|
||||
from tinygrad.runtime.support.c import _IO, _IOW, _IOR, _IOWR
|
||||
from tinygrad.runtime.support import c
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG(c.Struct):
|
||||
SIZE = 28
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION
|
||||
COUNT_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION
|
||||
PARAMETER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION
|
||||
SRC_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION
|
||||
SRC_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION, 0]
|
||||
COUNT_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION, 4]
|
||||
PARAMETER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION, 8]
|
||||
SRC_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION, 12]
|
||||
SRC_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION, 16]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION, 20]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION, 24]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
extra_info: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('extra_info', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
extra_info: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
count: int
|
||||
reserved_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION.register_fields([('count', ctypes.c_uint32, 0, 22, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 6), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
count: Annotated[Annotated[int, ctypes.c_uint32], 0, 22, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 6]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
reserved_0: int
|
||||
dst_swap: int
|
||||
reserved_1: int
|
||||
src_swap: int
|
||||
reserved_2: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION.register_fields([('reserved_0', ctypes.c_uint32, 0, 16, 0), ('dst_swap', ctypes.c_uint32, 2, 2, 0), ('reserved_1', ctypes.c_uint32, 2, 6, 2), ('src_swap', ctypes.c_uint32, 3, 2, 0), ('reserved_2', ctypes.c_uint32, 3, 6, 2), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
dst_swap: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 2, 6, 2]
|
||||
src_swap: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION.register_fields([('src_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_63_32: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION.register_fields([('src_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION, 0), ('COUNT_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION, 4), ('PARAMETER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION, 8), ('SRC_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION, 12), ('SRC_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION, 16), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION, 20), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION, 24)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR: TypeAlias = rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG(c.Struct):
|
||||
SIZE = 52
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION
|
||||
SRC_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION
|
||||
SRC_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION
|
||||
SRC_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION
|
||||
SRC_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION
|
||||
SRC_PARAMETER_3_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION
|
||||
DST_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION
|
||||
DST_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION
|
||||
DST_PARAMETER_3_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION
|
||||
RECT_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION
|
||||
RECT_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION, 0]
|
||||
SRC_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION, 4]
|
||||
SRC_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION, 8]
|
||||
SRC_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION, 12]
|
||||
SRC_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION, 16]
|
||||
SRC_PARAMETER_3_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION, 20]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION, 24]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION, 28]
|
||||
DST_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION, 32]
|
||||
DST_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION, 36]
|
||||
DST_PARAMETER_3_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION, 40]
|
||||
RECT_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION, 44]
|
||||
RECT_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION, 48]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved: int
|
||||
element: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved', ctypes.c_uint32, 2, 13, 0), ('element', ctypes.c_uint32, 3, 3, 5), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved: Annotated[Annotated[int, ctypes.c_uint32], 2, 13, 0]
|
||||
element: Annotated[Annotated[int, ctypes.c_uint32], 3, 3, 5]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION.register_fields([('src_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION.register_fields([('src_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_offset_x: int
|
||||
reserved_1: int
|
||||
src_offset_y: int
|
||||
reserved_2: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION.register_fields([('src_offset_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('src_offset_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_offset_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
src_offset_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_offset_z: int
|
||||
reserved_1: int
|
||||
src_pitch: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION.register_fields([('src_offset_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 3), ('src_pitch', ctypes.c_uint32, 1, 19, 5), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_offset_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 3]
|
||||
src_pitch: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_slice_pitch: int
|
||||
reserved_1: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION.register_fields([('src_slice_pitch', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
src_slice_pitch: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_7_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_7_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_7_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_offset_x: int
|
||||
reserved_1: int
|
||||
dst_offset_y: int
|
||||
reserved_2: int
|
||||
DW_8_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION.register_fields([('dst_offset_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('dst_offset_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_8_DATA', ctypes.c_uint32, 0)])
|
||||
dst_offset_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
dst_offset_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_8_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_offset_z: int
|
||||
reserved_1: int
|
||||
dst_pitch: int
|
||||
DW_9_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION.register_fields([('dst_offset_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 3), ('dst_pitch', ctypes.c_uint32, 1, 19, 5), ('DW_9_DATA', ctypes.c_uint32, 0)])
|
||||
dst_offset_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 3]
|
||||
dst_pitch: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_9_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_slice_pitch: int
|
||||
reserved_1: int
|
||||
DW_10_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION.register_fields([('dst_slice_pitch', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_10_DATA', ctypes.c_uint32, 0)])
|
||||
dst_slice_pitch: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_10_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
rect_x: int
|
||||
reserved_1: int
|
||||
rect_y: int
|
||||
reserved_2: int
|
||||
DW_11_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION.register_fields([('rect_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('rect_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_11_DATA', ctypes.c_uint32, 0)])
|
||||
rect_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
rect_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_11_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
rect_z: int
|
||||
reserved_1: int
|
||||
dst_swap: int
|
||||
reserved_2: int
|
||||
src_swap: int
|
||||
reserved_3: int
|
||||
DW_12_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION.register_fields([('rect_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 5, 3), ('dst_swap', ctypes.c_uint32, 2, 2, 0), ('reserved_2', ctypes.c_uint32, 2, 6, 2), ('src_swap', ctypes.c_uint32, 3, 2, 0), ('reserved_3', ctypes.c_uint32, 3, 6, 2), ('DW_12_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION, 0), ('SRC_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION, 4), ('SRC_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION, 8), ('SRC_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION, 12), ('SRC_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION, 16), ('SRC_PARAMETER_3_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION, 20), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION, 24), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION, 28), ('DST_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION, 32), ('DST_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION, 36), ('DST_PARAMETER_3_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION, 40), ('RECT_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION, 44), ('RECT_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION, 48)])
|
||||
rect_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 5, 3]
|
||||
dst_swap: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 2, 6, 2]
|
||||
src_swap: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_3: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_12_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT: TypeAlias = rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG(c.Struct):
|
||||
SIZE = 20
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION
|
||||
DATA_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION
|
||||
COUNT_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION, 0]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION, 4]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION, 8]
|
||||
DATA_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION, 12]
|
||||
COUNT_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION, 16]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
sw: int
|
||||
reserved_0: int
|
||||
fillsize: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('sw', ctypes.c_uint32, 2, 2, 0), ('reserved_0', ctypes.c_uint32, 2, 12, 2), ('fillsize', ctypes.c_uint32, 3, 2, 6), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
sw: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 12, 2]
|
||||
fillsize: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION.register_fields([('src_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
count: int
|
||||
reserved_0: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION.register_fields([('count', ctypes.c_uint32, 0, 22, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 6), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION, 0), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION, 4), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION, 8), ('DATA_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION, 12), ('COUNT_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION, 16)])
|
||||
count: Annotated[Annotated[int, ctypes.c_uint32], 0, 22, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 6]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL: TypeAlias = rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG(c.Struct):
|
||||
SIZE = 16
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION
|
||||
DATA_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION, 8]
|
||||
DATA_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION, 12]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
mtype: int
|
||||
gcc: int
|
||||
sys: int
|
||||
pad1: int
|
||||
snp: int
|
||||
gpa: int
|
||||
l2_policy: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('mtype', ctypes.c_uint32, 2, 3, 0), ('gcc', ctypes.c_uint32, 2, 1, 3), ('sys', ctypes.c_uint32, 2, 1, 4), ('pad1', ctypes.c_uint32, 2, 1, 5), ('snp', ctypes.c_uint32, 2, 1, 6), ('gpa', ctypes.c_uint32, 2, 1, 7), ('l2_policy', ctypes.c_uint32, 3, 2, 0), ('reserved_0', ctypes.c_uint32, 3, 6, 2), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
mtype: Annotated[Annotated[int, ctypes.c_uint32], 2, 3, 0]
|
||||
gcc: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 3]
|
||||
sys: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 4]
|
||||
pad1: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 5]
|
||||
snp: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 6]
|
||||
gpa: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 7]
|
||||
l2_policy: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
data: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION.register_fields([('data', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION, 8), ('DATA_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION, 12)])
|
||||
data: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_FENCE: TypeAlias = rocr_AMD_SDMA_PKT_FENCE_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG(c.Struct):
|
||||
SIZE = 24
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION
|
||||
VALUE_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION
|
||||
MASK_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION
|
||||
DW5_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION, 8]
|
||||
VALUE_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION, 12]
|
||||
MASK_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION, 16]
|
||||
DW5_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION, 20]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
hdp_flush: int
|
||||
reserved_1: int
|
||||
func: int
|
||||
mem_poll: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 0), ('hdp_flush', ctypes.c_uint32, 3, 1, 2), ('reserved_1', ctypes.c_uint32, 3, 1, 3), ('func', ctypes.c_uint32, 3, 3, 4), ('mem_poll', ctypes.c_uint32, 3, 1, 7), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 0]
|
||||
hdp_flush: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 2]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 3]
|
||||
func: Annotated[Annotated[int, ctypes.c_uint32], 3, 3, 4]
|
||||
mem_poll: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 7]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
value: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION.register_fields([('value', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
value: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
mask: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION.register_fields([('mask', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
mask: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
interval: int
|
||||
retry_count: int
|
||||
reserved_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION.register_fields([('interval', ctypes.c_uint32, 0, 16, 0), ('retry_count', ctypes.c_uint32, 2, 12, 0), ('reserved_0', ctypes.c_uint32, 3, 4, 4), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION, 8), ('VALUE_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION, 12), ('MASK_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION, 16), ('DW5_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION, 20)])
|
||||
interval: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
retry_count: Annotated[Annotated[int, ctypes.c_uint32], 2, 12, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM: TypeAlias = rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG(c.Struct):
|
||||
SIZE = 32
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION
|
||||
SRC_DATA_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION
|
||||
SRC_DATA_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION
|
||||
CMP_DATA_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION
|
||||
CMP_DATA_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION
|
||||
LOOP_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION, 8]
|
||||
SRC_DATA_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION, 12]
|
||||
SRC_DATA_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION, 16]
|
||||
CMP_DATA_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION, 20]
|
||||
CMP_DATA_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION, 24]
|
||||
LOOP_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION, 28]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
l: int
|
||||
reserved_0: int
|
||||
operation: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('l', ctypes.c_uint32, 2, 1, 0), ('reserved_0', ctypes.c_uint32, 2, 8, 1), ('operation', ctypes.c_uint32, 3, 7, 1), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
l: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 8, 1]
|
||||
operation: Annotated[Annotated[int, ctypes.c_uint32], 3, 7, 1]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION.register_fields([('src_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_63_32: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION.register_fields([('src_data_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
cmp_data_31_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION.register_fields([('cmp_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
cmp_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
cmp_data_63_32: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION.register_fields([('cmp_data_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
cmp_data_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
loop_interval: int
|
||||
reserved_0: int
|
||||
DW_7_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION.register_fields([('loop_interval', ctypes.c_uint32, 0, 13, 0), ('reserved_0', ctypes.c_uint32, 1, 19, 5), ('DW_7_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION, 8), ('SRC_DATA_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION, 12), ('SRC_DATA_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION, 16), ('CMP_DATA_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION, 20), ('CMP_DATA_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION, 24), ('LOOP_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION, 28)])
|
||||
loop_interval: Annotated[Annotated[int, ctypes.c_uint32], 0, 13, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_7_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_ATOMIC: TypeAlias = rocr_AMD_SDMA_PKT_ATOMIC_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG(c.Struct):
|
||||
SIZE = 12
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION, 8]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION, 8)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP: TypeAlias = rocr_AMD_SDMA_PKT_TIMESTAMP_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG(c.Struct):
|
||||
SIZE = 8
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION
|
||||
INT_CONTEXT_UNION: rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION, 0]
|
||||
INT_CONTEXT_UNION: Annotated[rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION, 4]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
int_ctx: int
|
||||
reserved_1: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION.register_fields([('int_ctx', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION, 0), ('INT_CONTEXT_UNION', rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION, 4)])
|
||||
int_ctx: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_TRAP: TypeAlias = rocr_AMD_SDMA_PKT_TRAP_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG(c.Struct):
|
||||
SIZE = 24
|
||||
DW_0_DATA: int
|
||||
DW_1_DATA: int
|
||||
DW_2_DATA: int
|
||||
DW_3_DATA: int
|
||||
DW_4_DATA: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG.register_fields([('DW_0_DATA', ctypes.c_uint32, 0), ('DW_1_DATA', ctypes.c_uint32, 4), ('DW_2_DATA', ctypes.c_uint32, 8), ('DW_3_DATA', ctypes.c_uint32, 12), ('DW_4_DATA', ctypes.c_uint32, 16), ('DW_5_DATA', ctypes.c_uint32, 20)])
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 4]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 8]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 12]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 16]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 20]
|
||||
rocr_AMD_SDMA_PKT_HDP_FLUSH: TypeAlias = rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG(c.Struct):
|
||||
SIZE = 20
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION
|
||||
WORD1_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION
|
||||
WORD2_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION
|
||||
WORD3_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION
|
||||
WORD4_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION, 0]
|
||||
WORD1_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION, 4]
|
||||
WORD2_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION, 8]
|
||||
WORD3_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION, 12]
|
||||
WORD4_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION, 16]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
BaseVA_LO: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION.register_fields([('BaseVA_LO', ctypes.c_uint32, 0, 25, 7), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
BaseVA_LO: Annotated[Annotated[int, ctypes.c_uint32], 0, 25, 7]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
BaseVA_HI: int
|
||||
GCR_CONTROL_GLI_INV: int
|
||||
GCR_CONTROL_GL1_RANGE: int
|
||||
GCR_CONTROL_GLM_WB: int
|
||||
GCR_CONTROL_GLM_INV: int
|
||||
GCR_CONTROL_GLK_WB: int
|
||||
GCR_CONTROL_GLK_INV: int
|
||||
GCR_CONTROL_GLV_INV: int
|
||||
GCR_CONTROL_GL1_INV: int
|
||||
GCR_CONTROL_GL2_US: int
|
||||
GCR_CONTROL_GL2_RANGE: int
|
||||
GCR_CONTROL_GL2_DISCARD: int
|
||||
GCR_CONTROL_GL2_INV: int
|
||||
GCR_CONTROL_GL2_WB: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION.register_fields([('BaseVA_HI', ctypes.c_uint32, 0, 16, 0), ('GCR_CONTROL_GLI_INV', ctypes.c_uint32, 2, 2, 0), ('GCR_CONTROL_GL1_RANGE', ctypes.c_uint32, 2, 2, 2), ('GCR_CONTROL_GLM_WB', ctypes.c_uint32, 2, 1, 4), ('GCR_CONTROL_GLM_INV', ctypes.c_uint32, 2, 1, 5), ('GCR_CONTROL_GLK_WB', ctypes.c_uint32, 2, 1, 6), ('GCR_CONTROL_GLK_INV', ctypes.c_uint32, 2, 1, 7), ('GCR_CONTROL_GLV_INV', ctypes.c_uint32, 3, 1, 0), ('GCR_CONTROL_GL1_INV', ctypes.c_uint32, 3, 1, 1), ('GCR_CONTROL_GL2_US', ctypes.c_uint32, 3, 1, 2), ('GCR_CONTROL_GL2_RANGE', ctypes.c_uint32, 3, 2, 3), ('GCR_CONTROL_GL2_DISCARD', ctypes.c_uint32, 3, 1, 5), ('GCR_CONTROL_GL2_INV', ctypes.c_uint32, 3, 1, 6), ('GCR_CONTROL_GL2_WB', ctypes.c_uint32, 3, 1, 7), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
BaseVA_HI: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
GCR_CONTROL_GLI_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
GCR_CONTROL_GL1_RANGE: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 2]
|
||||
GCR_CONTROL_GLM_WB: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 4]
|
||||
GCR_CONTROL_GLM_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 5]
|
||||
GCR_CONTROL_GLK_WB: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 6]
|
||||
GCR_CONTROL_GLK_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 7]
|
||||
GCR_CONTROL_GLV_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 0]
|
||||
GCR_CONTROL_GL1_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 1]
|
||||
GCR_CONTROL_GL2_US: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 2]
|
||||
GCR_CONTROL_GL2_RANGE: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 3]
|
||||
GCR_CONTROL_GL2_DISCARD: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 5]
|
||||
GCR_CONTROL_GL2_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 6]
|
||||
GCR_CONTROL_GL2_WB: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 7]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
GCR_CONTROL_RANGE_IS_PA: int
|
||||
GCR_CONTROL_SEQ: int
|
||||
LimitVA_LO: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION.register_fields([('GCR_CONTROL_RANGE_IS_PA', ctypes.c_uint32, 0, 1, 0), ('GCR_CONTROL_SEQ', ctypes.c_uint32, 0, 2, 1), ('LimitVA_LO', ctypes.c_uint32, 0, 25, 7), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
GCR_CONTROL_RANGE_IS_PA: Annotated[Annotated[int, ctypes.c_uint32], 0, 1, 0]
|
||||
GCR_CONTROL_SEQ: Annotated[Annotated[int, ctypes.c_uint32], 0, 2, 1]
|
||||
LimitVA_LO: Annotated[Annotated[int, ctypes.c_uint32], 0, 25, 7]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
LimitVA_HI: int
|
||||
VMID: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION.register_fields([('LimitVA_HI', ctypes.c_uint32, 0, 16, 0), ('VMID', ctypes.c_uint32, 3, 4, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION, 0), ('WORD1_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION, 4), ('WORD2_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION, 8), ('WORD3_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION, 12), ('WORD4_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION, 16)])
|
||||
LimitVA_HI: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
VMID: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_GCR: TypeAlias = rocr_AMD_SDMA_PKT_GCR_TAG
|
||||
c.init_records()
|
||||
SDMA_OP_COPY = 1 # type: ignore
|
||||
SDMA_OP_FENCE = 5 # type: ignore
|
||||
SDMA_OP_TRAP = 6 # type: ignore
|
||||
|
||||
@@ -1,515 +1,453 @@
|
||||
# mypy: disable-error-code="empty-body"
|
||||
from __future__ import annotations
|
||||
import ctypes
|
||||
from typing import Literal, TypeAlias
|
||||
from typing import Annotated, Literal, TypeAlias
|
||||
from tinygrad.runtime.support.c import _IO, _IOW, _IOR, _IOWR
|
||||
from tinygrad.runtime.support import c
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG(c.Struct):
|
||||
SIZE = 28
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION
|
||||
COUNT_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION
|
||||
PARAMETER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION
|
||||
SRC_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION
|
||||
SRC_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION, 0]
|
||||
COUNT_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION, 4]
|
||||
PARAMETER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION, 8]
|
||||
SRC_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION, 12]
|
||||
SRC_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION, 16]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION, 20]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION, 24]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
extra_info: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('extra_info', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
extra_info: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
count: int
|
||||
reserved_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION.register_fields([('count', ctypes.c_uint32, 0, 22, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 6), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
count: Annotated[Annotated[int, ctypes.c_uint32], 0, 22, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 6]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
reserved_0: int
|
||||
dst_swap: int
|
||||
reserved_1: int
|
||||
src_swap: int
|
||||
reserved_2: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION.register_fields([('reserved_0', ctypes.c_uint32, 0, 16, 0), ('dst_swap', ctypes.c_uint32, 2, 2, 0), ('reserved_1', ctypes.c_uint32, 2, 6, 2), ('src_swap', ctypes.c_uint32, 3, 2, 0), ('reserved_2', ctypes.c_uint32, 3, 6, 2), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
dst_swap: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 2, 6, 2]
|
||||
src_swap: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION.register_fields([('src_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_63_32: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION.register_fields([('src_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_HEADER_UNION, 0), ('COUNT_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_COUNT_UNION, 4), ('PARAMETER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_PARAMETER_UNION, 8), ('SRC_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_LO_UNION, 12), ('SRC_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_SRC_ADDR_HI_UNION, 16), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_LO_UNION, 20), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG_DST_ADDR_HI_UNION, 24)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR: TypeAlias = rocr_AMD_SDMA_PKT_COPY_LINEAR_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG(c.Struct):
|
||||
SIZE = 52
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION
|
||||
SRC_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION
|
||||
SRC_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION
|
||||
SRC_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION
|
||||
SRC_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION
|
||||
SRC_PARAMETER_3_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION
|
||||
DST_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION
|
||||
DST_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION
|
||||
DST_PARAMETER_3_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION
|
||||
RECT_PARAMETER_1_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION
|
||||
RECT_PARAMETER_2_UNION: rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION, 0]
|
||||
SRC_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION, 4]
|
||||
SRC_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION, 8]
|
||||
SRC_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION, 12]
|
||||
SRC_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION, 16]
|
||||
SRC_PARAMETER_3_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION, 20]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION, 24]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION, 28]
|
||||
DST_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION, 32]
|
||||
DST_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION, 36]
|
||||
DST_PARAMETER_3_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION, 40]
|
||||
RECT_PARAMETER_1_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION, 44]
|
||||
RECT_PARAMETER_2_UNION: Annotated[rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION, 48]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved: int
|
||||
element: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved', ctypes.c_uint32, 2, 13, 0), ('element', ctypes.c_uint32, 3, 3, 5), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved: Annotated[Annotated[int, ctypes.c_uint32], 2, 13, 0]
|
||||
element: Annotated[Annotated[int, ctypes.c_uint32], 3, 3, 5]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION.register_fields([('src_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION.register_fields([('src_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
src_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_offset_x: int
|
||||
reserved_1: int
|
||||
src_offset_y: int
|
||||
reserved_2: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION.register_fields([('src_offset_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('src_offset_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_offset_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
src_offset_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_offset_z: int
|
||||
reserved_1: int
|
||||
src_pitch: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION.register_fields([('src_offset_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 3), ('src_pitch', ctypes.c_uint32, 1, 19, 5), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_offset_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 3]
|
||||
src_pitch: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_slice_pitch: int
|
||||
reserved_1: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION.register_fields([('src_slice_pitch', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
src_slice_pitch: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_7_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_7_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_7_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_offset_x: int
|
||||
reserved_1: int
|
||||
dst_offset_y: int
|
||||
reserved_2: int
|
||||
DW_8_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION.register_fields([('dst_offset_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('dst_offset_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_8_DATA', ctypes.c_uint32, 0)])
|
||||
dst_offset_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
dst_offset_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_8_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_offset_z: int
|
||||
reserved_1: int
|
||||
dst_pitch: int
|
||||
DW_9_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION.register_fields([('dst_offset_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 3), ('dst_pitch', ctypes.c_uint32, 1, 19, 5), ('DW_9_DATA', ctypes.c_uint32, 0)])
|
||||
dst_offset_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 3]
|
||||
dst_pitch: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_9_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_slice_pitch: int
|
||||
reserved_1: int
|
||||
DW_10_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION.register_fields([('dst_slice_pitch', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_10_DATA', ctypes.c_uint32, 0)])
|
||||
dst_slice_pitch: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_10_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
rect_x: int
|
||||
reserved_1: int
|
||||
rect_y: int
|
||||
reserved_2: int
|
||||
DW_11_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION.register_fields([('rect_x', ctypes.c_uint32, 0, 14, 0), ('reserved_1', ctypes.c_uint32, 1, 2, 6), ('rect_y', ctypes.c_uint32, 2, 14, 0), ('reserved_2', ctypes.c_uint32, 3, 2, 6), ('DW_11_DATA', ctypes.c_uint32, 0)])
|
||||
rect_x: Annotated[Annotated[int, ctypes.c_uint32], 0, 14, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 2, 6]
|
||||
rect_y: Annotated[Annotated[int, ctypes.c_uint32], 2, 14, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_11_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
rect_z: int
|
||||
reserved_1: int
|
||||
dst_swap: int
|
||||
reserved_2: int
|
||||
src_swap: int
|
||||
reserved_3: int
|
||||
DW_12_DATA: int
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION.register_fields([('rect_z', ctypes.c_uint32, 0, 11, 0), ('reserved_1', ctypes.c_uint32, 1, 5, 3), ('dst_swap', ctypes.c_uint32, 2, 2, 0), ('reserved_2', ctypes.c_uint32, 2, 6, 2), ('src_swap', ctypes.c_uint32, 3, 2, 0), ('reserved_3', ctypes.c_uint32, 3, 6, 2), ('DW_12_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_HEADER_UNION, 0), ('SRC_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_LO_UNION, 4), ('SRC_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_ADDR_HI_UNION, 8), ('SRC_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_1_UNION, 12), ('SRC_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_2_UNION, 16), ('SRC_PARAMETER_3_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_SRC_PARAMETER_3_UNION, 20), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_LO_UNION, 24), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_ADDR_HI_UNION, 28), ('DST_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_1_UNION, 32), ('DST_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_2_UNION, 36), ('DST_PARAMETER_3_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_DST_PARAMETER_3_UNION, 40), ('RECT_PARAMETER_1_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_1_UNION, 44), ('RECT_PARAMETER_2_UNION', rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG_RECT_PARAMETER_2_UNION, 48)])
|
||||
rect_z: Annotated[Annotated[int, ctypes.c_uint32], 0, 11, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 1, 5, 3]
|
||||
dst_swap: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_2: Annotated[Annotated[int, ctypes.c_uint32], 2, 6, 2]
|
||||
src_swap: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_3: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_12_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT: TypeAlias = rocr_AMD_SDMA_PKT_COPY_LINEAR_RECT_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG(c.Struct):
|
||||
SIZE = 20
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION
|
||||
DST_ADDR_LO_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION
|
||||
DST_ADDR_HI_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION
|
||||
DATA_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION
|
||||
COUNT_UNION: rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION, 0]
|
||||
DST_ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION, 4]
|
||||
DST_ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION, 8]
|
||||
DATA_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION, 12]
|
||||
COUNT_UNION: Annotated[rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION, 16]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
sw: int
|
||||
reserved_0: int
|
||||
fillsize: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('sw', ctypes.c_uint32, 2, 2, 0), ('reserved_0', ctypes.c_uint32, 2, 12, 2), ('fillsize', ctypes.c_uint32, 3, 2, 6), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
sw: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 12, 2]
|
||||
fillsize: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 6]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION.register_fields([('dst_addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
dst_addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION.register_fields([('dst_addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
dst_addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION.register_fields([('src_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
count: int
|
||||
reserved_0: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION.register_fields([('count', ctypes.c_uint32, 0, 22, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 6), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_HEADER_UNION, 0), ('DST_ADDR_LO_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_LO_UNION, 4), ('DST_ADDR_HI_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DST_ADDR_HI_UNION, 8), ('DATA_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_DATA_UNION, 12), ('COUNT_UNION', rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG_COUNT_UNION, 16)])
|
||||
count: Annotated[Annotated[int, ctypes.c_uint32], 0, 22, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 6]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_CONSTANT_FILL: TypeAlias = rocr_AMD_SDMA_PKT_CONSTANT_FILL_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG(c.Struct):
|
||||
SIZE = 16
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION
|
||||
DATA_UNION: rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION, 8]
|
||||
DATA_UNION: Annotated[rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION, 12]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
mtype: int
|
||||
gcc: int
|
||||
sys: int
|
||||
pad1: int
|
||||
snp: int
|
||||
gpa: int
|
||||
l2_policy: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('mtype', ctypes.c_uint32, 2, 3, 0), ('gcc', ctypes.c_uint32, 2, 1, 3), ('sys', ctypes.c_uint32, 2, 1, 4), ('pad1', ctypes.c_uint32, 2, 1, 5), ('snp', ctypes.c_uint32, 2, 1, 6), ('gpa', ctypes.c_uint32, 2, 1, 7), ('l2_policy', ctypes.c_uint32, 3, 2, 0), ('reserved_0', ctypes.c_uint32, 3, 6, 2), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
mtype: Annotated[Annotated[int, ctypes.c_uint32], 2, 3, 0]
|
||||
gcc: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 3]
|
||||
sys: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 4]
|
||||
pad1: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 5]
|
||||
snp: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 6]
|
||||
gpa: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 7]
|
||||
l2_policy: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 3, 6, 2]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
data: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION.register_fields([('data', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_FENCE_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_ADDR_HI_UNION, 8), ('DATA_UNION', rocr_AMD_SDMA_PKT_FENCE_TAG_DATA_UNION, 12)])
|
||||
data: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_FENCE: TypeAlias = rocr_AMD_SDMA_PKT_FENCE_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG(c.Struct):
|
||||
SIZE = 24
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION
|
||||
VALUE_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION
|
||||
MASK_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION
|
||||
DW5_UNION: rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION, 8]
|
||||
VALUE_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION, 12]
|
||||
MASK_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION, 16]
|
||||
DW5_UNION: Annotated[rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION, 20]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
hdp_flush: int
|
||||
reserved_1: int
|
||||
func: int
|
||||
mem_poll: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 10, 0), ('hdp_flush', ctypes.c_uint32, 3, 1, 2), ('reserved_1', ctypes.c_uint32, 3, 1, 3), ('func', ctypes.c_uint32, 3, 3, 4), ('mem_poll', ctypes.c_uint32, 3, 1, 7), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 10, 0]
|
||||
hdp_flush: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 2]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 3]
|
||||
func: Annotated[Annotated[int, ctypes.c_uint32], 3, 3, 4]
|
||||
mem_poll: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 7]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
value: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION.register_fields([('value', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
value: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
mask: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION.register_fields([('mask', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
mask: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
interval: int
|
||||
retry_count: int
|
||||
reserved_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION.register_fields([('interval', ctypes.c_uint32, 0, 16, 0), ('retry_count', ctypes.c_uint32, 2, 12, 0), ('reserved_0', ctypes.c_uint32, 3, 4, 4), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_ADDR_HI_UNION, 8), ('VALUE_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_VALUE_UNION, 12), ('MASK_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_MASK_UNION, 16), ('DW5_UNION', rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG_DW5_UNION, 20)])
|
||||
interval: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
retry_count: Annotated[Annotated[int, ctypes.c_uint32], 2, 12, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_POLL_REGMEM: TypeAlias = rocr_AMD_SDMA_PKT_POLL_REGMEM_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG(c.Struct):
|
||||
SIZE = 32
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION
|
||||
SRC_DATA_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION
|
||||
SRC_DATA_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION
|
||||
CMP_DATA_LO_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION
|
||||
CMP_DATA_HI_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION
|
||||
LOOP_UNION: rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION, 8]
|
||||
SRC_DATA_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION, 12]
|
||||
SRC_DATA_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION, 16]
|
||||
CMP_DATA_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION, 20]
|
||||
CMP_DATA_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION, 24]
|
||||
LOOP_UNION: Annotated[rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION, 28]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
l: int
|
||||
reserved_0: int
|
||||
operation: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('l', ctypes.c_uint32, 2, 1, 0), ('reserved_0', ctypes.c_uint32, 2, 8, 1), ('operation', ctypes.c_uint32, 3, 7, 1), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
l: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 8, 1]
|
||||
operation: Annotated[Annotated[int, ctypes.c_uint32], 3, 7, 1]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_31_0: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION.register_fields([('src_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
src_data_63_32: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION.register_fields([('src_data_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
src_data_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
cmp_data_31_0: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION.register_fields([('cmp_data_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_5_DATA', ctypes.c_uint32, 0)])
|
||||
cmp_data_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
cmp_data_63_32: int
|
||||
DW_6_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION.register_fields([('cmp_data_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_6_DATA', ctypes.c_uint32, 0)])
|
||||
cmp_data_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_6_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
loop_interval: int
|
||||
reserved_0: int
|
||||
DW_7_DATA: int
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION.register_fields([('loop_interval', ctypes.c_uint32, 0, 13, 0), ('reserved_0', ctypes.c_uint32, 1, 19, 5), ('DW_7_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_ATOMIC_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_ADDR_HI_UNION, 8), ('SRC_DATA_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_LO_UNION, 12), ('SRC_DATA_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_SRC_DATA_HI_UNION, 16), ('CMP_DATA_LO_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_LO_UNION, 20), ('CMP_DATA_HI_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_CMP_DATA_HI_UNION, 24), ('LOOP_UNION', rocr_AMD_SDMA_PKT_ATOMIC_TAG_LOOP_UNION, 28)])
|
||||
loop_interval: Annotated[Annotated[int, ctypes.c_uint32], 0, 13, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 1, 19, 5]
|
||||
DW_7_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_ATOMIC: TypeAlias = rocr_AMD_SDMA_PKT_ATOMIC_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG(c.Struct):
|
||||
SIZE = 12
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION
|
||||
ADDR_LO_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION
|
||||
ADDR_HI_UNION: rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION, 0]
|
||||
ADDR_LO_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION, 4]
|
||||
ADDR_HI_UNION: Annotated[rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION, 8]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_31_0: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION.register_fields([('addr_31_0', ctypes.c_uint32, 0, 32, 0), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
addr_31_0: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
addr_63_32: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION.register_fields([('addr_63_32', ctypes.c_uint32, 0, 32, 0), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_HEADER_UNION, 0), ('ADDR_LO_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_LO_UNION, 4), ('ADDR_HI_UNION', rocr_AMD_SDMA_PKT_TIMESTAMP_TAG_ADDR_HI_UNION, 8)])
|
||||
addr_63_32: Annotated[Annotated[int, ctypes.c_uint32], 0, 32, 0]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_TIMESTAMP: TypeAlias = rocr_AMD_SDMA_PKT_TIMESTAMP_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG(c.Struct):
|
||||
SIZE = 8
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION
|
||||
INT_CONTEXT_UNION: rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION, 0]
|
||||
INT_CONTEXT_UNION: Annotated[rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION, 4]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
reserved_0: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('reserved_0', ctypes.c_uint32, 2, 16, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
reserved_0: Annotated[Annotated[int, ctypes.c_uint32], 2, 16, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
int_ctx: int
|
||||
reserved_1: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION.register_fields([('int_ctx', ctypes.c_uint32, 0, 28, 0), ('reserved_1', ctypes.c_uint32, 3, 4, 4), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_TRAP_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_TRAP_TAG_HEADER_UNION, 0), ('INT_CONTEXT_UNION', rocr_AMD_SDMA_PKT_TRAP_TAG_INT_CONTEXT_UNION, 4)])
|
||||
int_ctx: Annotated[Annotated[int, ctypes.c_uint32], 0, 28, 0]
|
||||
reserved_1: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 4]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_TRAP: TypeAlias = rocr_AMD_SDMA_PKT_TRAP_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG(c.Struct):
|
||||
SIZE = 24
|
||||
DW_0_DATA: int
|
||||
DW_1_DATA: int
|
||||
DW_2_DATA: int
|
||||
DW_3_DATA: int
|
||||
DW_4_DATA: int
|
||||
DW_5_DATA: int
|
||||
rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG.register_fields([('DW_0_DATA', ctypes.c_uint32, 0), ('DW_1_DATA', ctypes.c_uint32, 4), ('DW_2_DATA', ctypes.c_uint32, 8), ('DW_3_DATA', ctypes.c_uint32, 12), ('DW_4_DATA', ctypes.c_uint32, 16), ('DW_5_DATA', ctypes.c_uint32, 20)])
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 4]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 8]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 12]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 16]
|
||||
DW_5_DATA: Annotated[Annotated[int, ctypes.c_uint32], 20]
|
||||
rocr_AMD_SDMA_PKT_HDP_FLUSH: TypeAlias = rocr_AMD_SDMA_PKT_HDP_FLUSH_TAG
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG(c.Struct):
|
||||
SIZE = 20
|
||||
HEADER_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION
|
||||
WORD1_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION
|
||||
WORD2_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION
|
||||
WORD3_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION
|
||||
WORD4_UNION: rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION
|
||||
HEADER_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION, 0]
|
||||
WORD1_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION, 4]
|
||||
WORD2_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION, 8]
|
||||
WORD3_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION, 12]
|
||||
WORD4_UNION: Annotated[rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION, 16]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
op: int
|
||||
sub_op: int
|
||||
DW_0_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION.register_fields([('op', ctypes.c_uint32, 0, 8, 0), ('sub_op', ctypes.c_uint32, 1, 8, 0), ('DW_0_DATA', ctypes.c_uint32, 0)])
|
||||
op: Annotated[Annotated[int, ctypes.c_uint32], 0, 8, 0]
|
||||
sub_op: Annotated[Annotated[int, ctypes.c_uint32], 1, 8, 0]
|
||||
DW_0_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
BaseVA_LO: int
|
||||
DW_1_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION.register_fields([('BaseVA_LO', ctypes.c_uint32, 0, 25, 7), ('DW_1_DATA', ctypes.c_uint32, 0)])
|
||||
BaseVA_LO: Annotated[Annotated[int, ctypes.c_uint32], 0, 25, 7]
|
||||
DW_1_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
BaseVA_HI: int
|
||||
GCR_CONTROL_GLI_INV: int
|
||||
GCR_CONTROL_GL1_RANGE: int
|
||||
GCR_CONTROL_GLM_WB: int
|
||||
GCR_CONTROL_GLM_INV: int
|
||||
GCR_CONTROL_GLK_WB: int
|
||||
GCR_CONTROL_GLK_INV: int
|
||||
GCR_CONTROL_GLV_INV: int
|
||||
GCR_CONTROL_GL1_INV: int
|
||||
GCR_CONTROL_GL2_US: int
|
||||
GCR_CONTROL_GL2_RANGE: int
|
||||
GCR_CONTROL_GL2_DISCARD: int
|
||||
GCR_CONTROL_GL2_INV: int
|
||||
GCR_CONTROL_GL2_WB: int
|
||||
DW_2_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION.register_fields([('BaseVA_HI', ctypes.c_uint32, 0, 16, 0), ('GCR_CONTROL_GLI_INV', ctypes.c_uint32, 2, 2, 0), ('GCR_CONTROL_GL1_RANGE', ctypes.c_uint32, 2, 2, 2), ('GCR_CONTROL_GLM_WB', ctypes.c_uint32, 2, 1, 4), ('GCR_CONTROL_GLM_INV', ctypes.c_uint32, 2, 1, 5), ('GCR_CONTROL_GLK_WB', ctypes.c_uint32, 2, 1, 6), ('GCR_CONTROL_GLK_INV', ctypes.c_uint32, 2, 1, 7), ('GCR_CONTROL_GLV_INV', ctypes.c_uint32, 3, 1, 0), ('GCR_CONTROL_GL1_INV', ctypes.c_uint32, 3, 1, 1), ('GCR_CONTROL_GL2_US', ctypes.c_uint32, 3, 1, 2), ('GCR_CONTROL_GL2_RANGE', ctypes.c_uint32, 3, 2, 3), ('GCR_CONTROL_GL2_DISCARD', ctypes.c_uint32, 3, 1, 5), ('GCR_CONTROL_GL2_INV', ctypes.c_uint32, 3, 1, 6), ('GCR_CONTROL_GL2_WB', ctypes.c_uint32, 3, 1, 7), ('DW_2_DATA', ctypes.c_uint32, 0)])
|
||||
BaseVA_HI: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
GCR_CONTROL_GLI_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 0]
|
||||
GCR_CONTROL_GL1_RANGE: Annotated[Annotated[int, ctypes.c_uint32], 2, 2, 2]
|
||||
GCR_CONTROL_GLM_WB: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 4]
|
||||
GCR_CONTROL_GLM_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 5]
|
||||
GCR_CONTROL_GLK_WB: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 6]
|
||||
GCR_CONTROL_GLK_INV: Annotated[Annotated[int, ctypes.c_uint32], 2, 1, 7]
|
||||
GCR_CONTROL_GLV_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 0]
|
||||
GCR_CONTROL_GL1_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 1]
|
||||
GCR_CONTROL_GL2_US: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 2]
|
||||
GCR_CONTROL_GL2_RANGE: Annotated[Annotated[int, ctypes.c_uint32], 3, 2, 3]
|
||||
GCR_CONTROL_GL2_DISCARD: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 5]
|
||||
GCR_CONTROL_GL2_INV: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 6]
|
||||
GCR_CONTROL_GL2_WB: Annotated[Annotated[int, ctypes.c_uint32], 3, 1, 7]
|
||||
DW_2_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
GCR_CONTROL_RANGE_IS_PA: int
|
||||
GCR_CONTROL_SEQ: int
|
||||
LimitVA_LO: int
|
||||
DW_3_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION.register_fields([('GCR_CONTROL_RANGE_IS_PA', ctypes.c_uint32, 0, 1, 0), ('GCR_CONTROL_SEQ', ctypes.c_uint32, 0, 2, 1), ('LimitVA_LO', ctypes.c_uint32, 0, 25, 7), ('DW_3_DATA', ctypes.c_uint32, 0)])
|
||||
GCR_CONTROL_RANGE_IS_PA: Annotated[Annotated[int, ctypes.c_uint32], 0, 1, 0]
|
||||
GCR_CONTROL_SEQ: Annotated[Annotated[int, ctypes.c_uint32], 0, 2, 1]
|
||||
LimitVA_LO: Annotated[Annotated[int, ctypes.c_uint32], 0, 25, 7]
|
||||
DW_3_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
@c.record
|
||||
class rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION(c.Struct):
|
||||
SIZE = 4
|
||||
LimitVA_HI: int
|
||||
VMID: int
|
||||
DW_4_DATA: int
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION.register_fields([('LimitVA_HI', ctypes.c_uint32, 0, 16, 0), ('VMID', ctypes.c_uint32, 3, 4, 0), ('DW_4_DATA', ctypes.c_uint32, 0)])
|
||||
rocr_AMD_SDMA_PKT_GCR_TAG.register_fields([('HEADER_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_HEADER_UNION, 0), ('WORD1_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD1_UNION, 4), ('WORD2_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD2_UNION, 8), ('WORD3_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD3_UNION, 12), ('WORD4_UNION', rocr_AMD_SDMA_PKT_GCR_TAG_WORD4_UNION, 16)])
|
||||
LimitVA_HI: Annotated[Annotated[int, ctypes.c_uint32], 0, 16, 0]
|
||||
VMID: Annotated[Annotated[int, ctypes.c_uint32], 3, 4, 0]
|
||||
DW_4_DATA: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
rocr_AMD_SDMA_PKT_GCR: TypeAlias = rocr_AMD_SDMA_PKT_GCR_TAG
|
||||
c.init_records()
|
||||
SDMA_OP_COPY = 1 # type: ignore
|
||||
SDMA_OP_FENCE = 5 # type: ignore
|
||||
SDMA_OP_TRAP = 6 # type: ignore
|
||||
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user