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
use alloc::string::{String, ToString};
use pliron::derive::format;
use crate::AddressType;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, serde::Serialize, serde::Deserialize)]
#[allow(missing_docs)]
#[format("`(` $x `, ` $y `, ` $z `)`")]
/// The number of units across all 3 axis totalling to the number of working units in a cube.
pub struct Dim3 {
/// The number of units in the x axis.
pub x: u32,
/// The number of units in the y axis.
pub y: u32,
/// The number of units in the z axis.
pub z: u32,
}
impl Dim3 {
/// Create a new `Dim3` with x = y = z = 1.
pub const fn new_single() -> Self {
Self { x: 1, y: 1, z: 1 }
}
/// Create a new `Dim3` with the given x, and y = z = 1.
pub const fn new_1d(x: u32) -> Self {
Self { x, y: 1, z: 1 }
}
/// Create a new dim3 with the given x and y, and z = 1.
pub const fn new_2d(x: u32, y: u32) -> Self {
Self { x, y, z: 1 }
}
/// Create a new `Dim3` with the given x, y and z.
/// This is equivalent to the [new](Dim3::new) function.
pub const fn new_3d(x: u32, y: u32, z: u32) -> Self {
Self { x, y, z }
}
/// Total numbers of units per cube
pub const fn num_elems(&self) -> u32 {
self.x * self.y * self.z
}
/// Whether this `Dim3` can fully contain `other`
pub const fn can_contain(&self, other: Dim3) -> bool {
self.x >= other.x && self.y >= other.y && self.z >= other.z
}
}
impl From<(u32, u32, u32)> for Dim3 {
fn from(value: (u32, u32, u32)) -> Self {
Dim3::new_3d(value.0, value.1, value.2)
}
}
impl From<Dim3> for (u32, u32, u32) {
fn from(val: Dim3) -> Self {
(val.x, val.y, val.z)
}
}
/// The kind of execution to be performed.
#[derive(
Default, Hash, PartialEq, Eq, Clone, Debug, Copy, serde::Serialize, serde::Deserialize,
)]
pub enum ExecutionMode {
/// Checked kernels are safe.
#[default]
Checked,
/// Validate OOB and alert if OOB access occurs
Validate,
/// Unchecked kernels are unsafe.
Unchecked,
}
/// How much source-level debug data a kernel carries. Profilers and debuggers read it to map
/// kernel code back to the `#[cube]` source.
#[derive(
Default,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Debug,
serde::Serialize,
serde::Deserialize,
)]
pub enum DebugInfo {
/// No debug data.
#[default]
#[serde(rename = "none")]
None,
/// Source lines, with each inlined `#[cube]` function as its own frame.
#[serde(rename = "line-tables")]
LineTables,
/// Line tables and the embedded source text.
#[serde(rename = "full")]
Full,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct KernelSettings {
/// The cube dim of the kernel
pub cube_dim: Dim3,
/// The address type of the kernel
pub address_type: AddressType,
/// The name of the kernel
pub kernel_name: String,
/// The source-level debug data to include
pub debug_info: DebugInfo,
/// CUDA Cluster dim, if any
pub cluster_dim: Option<Dim3>,
/// Execution mode
pub execution_mode: ExecutionMode,
}
impl KernelSettings {
pub fn new(cube_dim: Dim3, execution_mode: ExecutionMode, address_type: AddressType) -> Self {
Self {
cube_dim,
address_type,
kernel_name: String::new(),
debug_info: DebugInfo::None,
cluster_dim: None,
execution_mode,
}
}
}
impl KernelSettings {
/// Set cube dimension.
pub fn cube_dim(mut self, cube_dim: Dim3) -> Self {
self.cube_dim = cube_dim;
self
}
/// Set address type.
pub fn address_type(mut self, ty: AddressType) -> Self {
self.address_type = ty;
self
}
/// Set kernel name.
pub fn kernel_name<S: AsRef<str>>(mut self, name: S) -> Self {
self.kernel_name = name.as_ref().to_string();
self
}
/// Include full debug data, whatever the cargo profile asks for.
#[must_use]
pub fn debug_symbols(self) -> Self {
self.debug_info(DebugInfo::Full)
}
/// Set the source-level debug data to include.
#[must_use]
pub fn debug_info(mut self, debug_info: DebugInfo) -> Self {
self.debug_info = debug_info;
self
}
/// Set cluster dim
pub fn cluster_dim(mut self, cluster_dim: Dim3) -> Self {
self.cluster_dim = Some(cluster_dim);
self
}
}