1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Copyright (C) 2025 zk4x
// SPDX-License-Identifier: LGPL-3.0-only WITH Classpath-exception-2.0
use std::fmt::{Display, Write};
use crate::tensor::TensorId;
/// Enumeration representing the various errors that can occur within the Zyx library.
#[derive(Debug)]
pub enum ZyxError {
/// Invalid shapes for operation
ShapeError(Box<str>),
/// Wrong dtype for given operation
DTypeError(Box<str>),
/// Error from file operations
IOError(std::io::Error),
/// Error parsing some data
ParseError(Box<str>),
/// Memory allocation error
AllocationError(Box<str>),
/// There are no available backends
NoBackendAvailable,
/// Error returned by backends
BackendError(BackendError),
/// Failed to launch kernel due to unknown reasons
KernelLaunchFailure,
/// Tried to load a graph tensor without calling realize first
GraphTensorNotRealized(Box<str>),
/// A frozen tape's leaf bindings (buffer pools) changed since `freeze` —
/// the compiled plan no longer matches the inputs. The tape must be
/// re-frozen.
FrozenPlanStale(Box<str>),
/// Invalid kernel structure (e.g. an op of the wrong kind for a transform)
KernelError(Box<str>),
}
impl ZyxError {
/// Shape error
#[track_caller]
#[must_use]
pub fn shape_error(e: Box<str>) -> Self {
let location = std::panic::Location::caller();
let mut e: String = e.into();
write!(e, ", {}:{}:{}", location.file(), location.line(), location.column()).unwrap();
Self::ShapeError(e.into())
}
/// `DType` error
#[track_caller]
#[must_use]
pub fn dtype_error(e: Box<str>) -> Self {
let location = std::panic::Location::caller();
let mut e: String = e.into();
write!(e, ", {}:{}:{}", location.file(), location.line(), location.column()).unwrap();
Self::DTypeError(e.into())
}
/// Parse error
#[track_caller]
#[must_use]
pub fn parse_error(e: Box<str>) -> Self {
let location = std::panic::Location::caller();
let mut e: String = e.into();
write!(e, ", {}:{}:{}", location.file(), location.line(), location.column()).unwrap();
Self::ParseError(e.into())
}
/// Error when trying to load a graph tensor that has not been realized yet.
/// Graph tensors must be materialized (via `Tape::realize`) before their
/// buffers can be accessed. This error indicates the graph was never compiled.
#[track_caller]
pub fn graph_tensor_not_realized(tid: TensorId) -> Self {
let location = std::panic::Location::caller();
Self::GraphTensorNotRealized(
format!(
"graph tensor {tid} must be realized before loading, at {}:{}:{}",
location.file(),
location.line(),
location.column()
)
.into(),
)
}
/// A frozen tape was replayed with inputs whose buffer bindings changed
/// since `freeze` compiled the plan. The frozen contract is that bindings
/// are fixed; the tape must be re-frozen for the new inputs.
#[track_caller]
pub fn frozen_plan_stale(e: Box<str>) -> Self {
let location = std::panic::Location::caller();
let mut e: String = e.into();
write!(e, ", {}:{}:{}", location.file(), location.line(), location.column()).unwrap();
Self::FrozenPlanStale(e.into())
}
/// Kernel error
#[track_caller]
#[must_use]
pub fn kernel_error(e: Box<str>) -> Self {
let location = std::panic::Location::caller();
let mut e: String = e.into();
write!(e, ", {}:{}:{}", location.file(), location.line(), location.column()).unwrap();
Self::KernelError(e.into())
}
}
impl std::fmt::Display for ZyxError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ZyxError::ShapeError(e) => f.write_str(e),
ZyxError::DTypeError(e) => f.write_fmt(format_args!("Wrong dtype {e:?}")),
ZyxError::IOError(e) => f.write_fmt(format_args!("IO {e}")),
ZyxError::ParseError(e) => f.write_fmt(format_args!("IO {e}")),
ZyxError::NoBackendAvailable => f.write_fmt(format_args!("No available backend")),
ZyxError::AllocationError(e) => f.write_fmt(format_args!("Allocation error {e}")),
ZyxError::BackendError(e) => f.write_fmt(format_args!("Backend {e}")),
ZyxError::KernelLaunchFailure => f.write_fmt(format_args!(
"Multiple kernel variations failed to launch. Could be autotuner issue, but more likely faulty hardware driver."
)),
ZyxError::GraphTensorNotRealized(e) => f.write_str(e),
ZyxError::FrozenPlanStale(e) => f.write_str(e),
ZyxError::KernelError(e) => f.write_str(e),
}
}
}
impl std::error::Error for ZyxError {}
impl From<std::io::Error> for ZyxError {
#[track_caller]
fn from(value: std::io::Error) -> Self {
Self::IOError(value)
}
}
#[derive(Debug)]
pub struct BackendError {
pub status: ErrorStatus,
pub context: Box<str>,
}
impl From<BackendError> for ZyxError {
fn from(value: BackendError) -> Self {
ZyxError::BackendError(value)
}
}
impl Display for BackendError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:?}: {}", self.status, self.context))
}
}
#[derive(Debug)]
pub enum ErrorStatus {
/// Dynamic library was not found on the disk
DyLibNotFound,
/// Backend initialization failure
Initialization,
/// Backend deinitialization failure
Deinitialization,
/// Failed to enumerate devices
DeviceEnumeration,
/// Failed to query device for information
DeviceQuery,
/// Failed to allocate memory
MemoryAllocation,
/// Failed to deallocate memory
MemoryDeallocation,
/// Failed to copy memory to pool
MemoryCopyH2P,
/// Failed to copy memory to host
MemoryCopyP2H,
/// Failed to copy memory between pools (device-to-device peer copy)
MemoryCopyP2P,
/// Kernel argument was not correct
IncorrectKernelArg,
/// Failed to compile kernel
KernelCompilation,
/// Failed to launch kernel
KernelLaunch,
/// Failed to synchronize kernel
KernelSync,
/// Kernel does not have the required section structure
/// (Tenstorrent: exactly 2 barriers delimiting reader/compute/writer)
InvalidKernelSections,
/// Kernel needs more circular buffers than the device provides
TooManyCircularBuffers,
/// Circular buffer push/pop imbalance (a deadlock on hardware)
CircularBufferImbalance,
/// Circular buffer shape invalid for hardware (not whole pages,
/// exceeds per-CB L1 budget)
InvalidCircularBuffer,
/// Compute core accessed DRAM (Tenstorrent compute cores can only
/// touch CBs/L1 and args, never DRAM globals)
ComputeAccessesDram,
}