lib/accy/src/kernel/dsl/program/root.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const kernel = @import("../../root.zig");
3 const kernel_compile = @import("../../compile/root.zig");
4 const executable = @import("../../../executable/root.zig");
5 const execute = @import("execute.zig");
6 const parameter = @import("../../program/root.zig").parameter;
7
8 pub fn Program(comptime definition: anytype) type {
9 return Source(definition);
10 }
11
12 pub fn Family(comptime definition: anytype) type {
13 return struct {
14 pub const name = definition.name;
15 pub const parameters = definition.parameters;
16 pub const Layout: type = parameter.Standard(parameters);
17 pub const Instance: type = definition.Instance;
18 pub const Limits: type = kernel.Limits;
19
20 pub fn arg(comptime name_value: anytype) usize {
21 return Layout.index(name_value);
22 }
23
24 pub fn schema() []const kernel.Param {
25 return parameter.schema(parameters);
26 }
27
28 pub fn build(allocator: std.mem.Allocator, limits: Limits, instance: Instance) !kernel.Graph {
29 return execute.buildInstanceSource(definition, instance, allocator, limits);
30 }
31
32 pub fn buildNamed(allocator: std.mem.Allocator, limits: Limits, graph_name: []const u8, instance: Instance) !kernel.Graph {
33 return execute.buildNamedInstanceSource(definition, graph_name, instance, allocator, limits);
34 }
35
36 pub fn interpret(allocator: std.mem.Allocator, limits: Limits, instance: Instance, initial: anytype) !execute.result(@TypeOf(initial)) {
37 return execute.interpretInstanceSource(definition, instance, allocator, limits, initial);
38 }
39
40 pub fn launch(allocator: std.mem.Allocator, limits: Limits, instance: Instance) !kernel.Launch {
41 var graph = try build(allocator, limits, instance);
42 defer graph.deinit();
43 return graph.launch();
44 }
45
46 pub fn scheduleSnapshot(allocator: std.mem.Allocator, limits: Limits, instance: Instance) !kernel.ScheduleSnapshot {
47 var graph = try build(allocator, limits, instance);
48 defer graph.deinit();
49 return graph.scheduleSnapshot(allocator);
50 }
51
52 pub fn createPlan(allocator: std.mem.Allocator, limits: Limits, instance: Instance, options: kernel.PlanOptions) !kernel.Plan {
53 var graph = try build(allocator, limits, instance);
54 defer graph.deinit();
55 return graph.createPlan(allocator, options);
56 }
57
58 pub fn createCheckedPlan(allocator: std.mem.Allocator, limits: Limits, instance: Instance, options: kernel.PlanOptions) !kernel.Plan {
59 var graph = try build(allocator, limits, instance);
60 defer graph.deinit();
61 return graph.createCheckedPlan(allocator, options);
62 }
63
64 pub fn compileFragment(
65 allocator: std.mem.Allocator,
66 limits: Limits,
67 instance: Instance,
68 handle: kernel.BackendHandle,
69 options: executable.FragmentCompilerOptions,
70 ) !*executable.CompiledFragment {
71 var graph = try build(allocator, limits, instance);
72 defer graph.deinit();
73 return kernel_compile.compileFragment(allocator, handle, &graph, options);
74 }
75
76 pub fn createKernelArtifact(
77 allocator: std.mem.Allocator,
78 limits: Limits,
79 instance: Instance,
80 handle: kernel.BackendHandle,
81 options: executable.KernelCompilerOptions,
82 ) !kernel.KernelArtifact {
83 var graph = try build(allocator, limits, instance);
84 defer graph.deinit();
85 return kernel_compile.createArtifact(allocator, handle, &graph, options);
86 }
87
88 pub fn createKernelCallArtifact(
89 allocator: std.mem.Allocator,
90 limits: Limits,
91 instance: Instance,
92 handle: kernel.BackendHandle,
93 options: kernel.KernelCallArtifactOptions,
94 ) !kernel.OwnedKernelCallArtifact {
95 var graph = try build(allocator, limits, instance);
96 defer graph.deinit();
97 return kernel.createKernelCallArtifact(allocator, handle, &graph, options);
98 }
99
100 pub fn runCpu(allocator: std.mem.Allocator, limits: Limits, instance: Instance, args: []const kernel.Argument) !void {
101 var graph = try build(allocator, limits, instance);
102 defer graph.deinit();
103 try graph.runCpu(allocator, args);
104 }
105
106 pub fn runCpuWithDiagnostic(
107 allocator: std.mem.Allocator,
108 limits: Limits,
109 instance: Instance,
110 args: []const kernel.Argument,
111 diagnostic: *kernel.ExecutionDiagnostic,
112 ) !void {
113 var graph = try build(allocator, limits, instance);
114 defer graph.deinit();
115 try graph.runCpuWithDiagnostic(allocator, args, diagnostic);
116 }
117
118 pub fn verify(allocator: std.mem.Allocator, limits: Limits, instance: Instance) !void {
119 var graph = try build(allocator, limits, instance);
120 defer graph.deinit();
121 try graph.verify();
122 }
123 };
124 }
125
126 fn Source(comptime definition: anytype) type {
127 return struct {
128 pub const name = definition.name;
129 pub const parameters = definition.parameters;
130 pub const Layout: type = parameter.Standard(parameters);
131 pub const Limits: type = kernel.Limits;
132 const Methods: type = Surface(@This());
133
134 pub fn arg(comptime name_value: anytype) usize {
135 return Layout.index(name_value);
136 }
137
138 pub fn schema() []const kernel.Param {
139 return parameter.schema(parameters);
140 }
141
142 pub fn build(allocator: std.mem.Allocator, limits: Limits) !kernel.Graph {
143 return execute.buildSource(definition, allocator, limits);
144 }
145
146 pub fn interpret(allocator: std.mem.Allocator, limits: Limits, initial: anytype) !execute.result(@TypeOf(initial)) {
147 return execute.interpretSource(definition, allocator, limits, initial);
148 }
149
150 pub const analyze = Methods.analyze;
151 pub const transform = Methods.transform;
152 pub const launch = Methods.launch;
153 pub const scheduleSnapshot = Methods.scheduleSnapshot;
154 pub const createPlan = Methods.createPlan;
155 pub const createCheckedPlan = Methods.createCheckedPlan;
156 pub const compileFragment = Methods.compileFragment;
157 pub const createKernelArtifact = Methods.createKernelArtifact;
158 pub const createKernelCallArtifact = Methods.createKernelCallArtifact;
159 pub const runCpu = Methods.runCpu;
160 pub const runCpuWithDiagnostic = Methods.runCpuWithDiagnostic;
161 pub const verify = Methods.verify;
162 };
163 }
164
165 fn Derived(comptime SourceProgram: type, comptime transform_spec: anytype) type {
166 return struct {
167 pub const name = SourceProgram.name;
168 pub const parameters = SourceProgram.parameters;
169 pub const Layout: type = SourceProgram.Layout;
170 pub const Source: type = SourceProgram;
171 pub const spec = transform_spec;
172 pub const Limits: type = kernel.Limits;
173 const Methods: type = Surface(@This());
174
175 pub fn arg(comptime name_value: anytype) usize {
176 return Layout.index(name_value);
177 }
178
179 pub fn schema() []const kernel.Param {
180 return SourceProgram.schema();
181 }
182
183 pub fn build(allocator: std.mem.Allocator, limits: Limits) !kernel.Graph {
184 return execute.buildDerived(SourceProgram, transform_spec, allocator, limits);
185 }
186
187 pub fn interpret(allocator: std.mem.Allocator, limits: Limits, initial: anytype) !execute.stackedResult(@TypeOf(transform_spec), @TypeOf(initial)) {
188 return execute.interpretDerived(SourceProgram, transform_spec, allocator, limits, initial);
189 }
190
191 pub const analyze = Methods.analyze;
192 pub const transform = Methods.transform;
193 pub const launch = Methods.launch;
194 pub const scheduleSnapshot = Methods.scheduleSnapshot;
195 pub const createPlan = Methods.createPlan;
196 pub const createCheckedPlan = Methods.createCheckedPlan;
197 pub const compileFragment = Methods.compileFragment;
198 pub const createKernelArtifact = Methods.createKernelArtifact;
199 pub const createKernelCallArtifact = Methods.createKernelCallArtifact;
200 pub const runCpu = Methods.runCpu;
201 pub const runCpuWithDiagnostic = Methods.runCpuWithDiagnostic;
202 pub const verify = Methods.verify;
203 };
204 }
205
206 fn Analysis(comptime ProgramType: type, comptime analysis_impl: anytype) type {
207 return struct {
208 pub const Program: type = ProgramType;
209 pub const name = ProgramType.name;
210 pub const parameters = ProgramType.parameters;
211 pub const Layout: type = ProgramType.Layout;
212 pub const Limits: type = kernel.Limits;
213
214 pub fn arg(comptime name_value: anytype) usize {
215 return Layout.index(name_value);
216 }
217
218 pub fn schema() []const kernel.Param {
219 return ProgramType.schema();
220 }
221
222 pub fn interpret(allocator: std.mem.Allocator, limits: Limits) !execute.result(@TypeOf(analysis_impl)) {
223 return ProgramType.interpret(allocator, limits, analysis_impl);
224 }
225
226 pub fn transform(comptime make_transform: anytype) type {
227 return AnalysisTransform(ProgramType, analysis_impl, make_transform);
228 }
229 };
230 }
231
232 fn AnalysisTransform(comptime ProgramType: type, comptime analysis_impl: anytype, comptime make_transform: anytype) type {
233 return struct {
234 pub const name = ProgramType.name;
235 pub const parameters = ProgramType.parameters;
236 pub const Layout: type = ProgramType.Layout;
237 pub const Source: type = ProgramType;
238 pub const Limits: type = kernel.Limits;
239 const Methods: type = Surface(@This());
240 const AnalysisResult: type = execute.AnalysisResult(analysis_impl);
241 const TransformSpec: type = execute.TransformSpec(analysis_impl, make_transform);
242
243 pub fn arg(comptime name_value: anytype) usize {
244 return Layout.index(name_value);
245 }
246
247 pub fn schema() []const kernel.Param {
248 return ProgramType.schema();
249 }
250
251 pub fn build(allocator: std.mem.Allocator, limits: Limits) !kernel.Graph {
252 return execute.buildAnalysisTransform(ProgramType, analysis_impl, make_transform, allocator, limits);
253 }
254
255 pub fn interpret(allocator: std.mem.Allocator, limits: Limits, initial: anytype) !execute.stackedResult(TransformSpec, @TypeOf(initial)) {
256 return execute.interpretAnalysisTransform(ProgramType, analysis_impl, make_transform, allocator, limits, initial);
257 }
258
259 pub const analyze = Methods.analyze;
260 pub const transform = Methods.transform;
261 pub const launch = Methods.launch;
262 pub const scheduleSnapshot = Methods.scheduleSnapshot;
263 pub const createPlan = Methods.createPlan;
264 pub const createCheckedPlan = Methods.createCheckedPlan;
265 pub const compileFragment = Methods.compileFragment;
266 pub const createKernelArtifact = Methods.createKernelArtifact;
267 pub const createKernelCallArtifact = Methods.createKernelCallArtifact;
268 pub const runCpu = Methods.runCpu;
269 pub const runCpuWithDiagnostic = Methods.runCpuWithDiagnostic;
270 pub const verify = Methods.verify;
271 };
272 }
273
274 fn Surface(comptime ProgramType: type) type {
275 return struct {
276 pub fn transform(comptime impl: anytype) type {
277 const next_spec = kernel.interpret.asSpec(impl);
278 if (comptime @hasDecl(ProgramType, "spec")) {
279 return Derived(ProgramType.Source, kernel.interpret.stack(.{ ProgramType.spec, next_spec }));
280 }
281 return Derived(ProgramType, next_spec);
282 }
283
284 pub fn analyze(comptime analysis_impl: anytype) type {
285 return Analysis(ProgramType, analysis_impl);
286 }
287
288 pub fn launch(allocator: std.mem.Allocator, limits: kernel.Limits) !kernel.Launch {
289 return execute.launch(ProgramType, allocator, limits);
290 }
291
292 pub fn scheduleSnapshot(allocator: std.mem.Allocator, limits: kernel.Limits) !kernel.ScheduleSnapshot {
293 return execute.scheduleSnapshot(ProgramType, allocator, limits);
294 }
295
296 pub fn createPlan(allocator: std.mem.Allocator, limits: kernel.Limits, options: kernel.PlanOptions) !kernel.Plan {
297 return execute.createPlan(ProgramType, allocator, limits, options);
298 }
299
300 pub fn createCheckedPlan(allocator: std.mem.Allocator, limits: kernel.Limits, options: kernel.PlanOptions) !kernel.Plan {
301 return execute.createCheckedPlan(ProgramType, allocator, limits, options);
302 }
303
304 pub fn compileFragment(
305 allocator: std.mem.Allocator,
306 limits: kernel.Limits,
307 handle: kernel.BackendHandle,
308 options: executable.FragmentCompilerOptions,
309 ) !*executable.CompiledFragment {
310 return execute.compileFragment(ProgramType, allocator, limits, handle, options);
311 }
312
313 pub fn createKernelArtifact(
314 allocator: std.mem.Allocator,
315 limits: kernel.Limits,
316 handle: kernel.BackendHandle,
317 options: executable.KernelCompilerOptions,
318 ) !kernel.KernelArtifact {
319 return execute.createKernelArtifact(ProgramType, allocator, limits, handle, options);
320 }
321
322 pub fn createKernelCallArtifact(
323 allocator: std.mem.Allocator,
324 limits: kernel.Limits,
325 handle: kernel.BackendHandle,
326 options: kernel.KernelCallArtifactOptions,
327 ) !kernel.OwnedKernelCallArtifact {
328 return execute.createKernelCallArtifact(ProgramType, allocator, limits, handle, options);
329 }
330
331 pub fn runCpu(allocator: std.mem.Allocator, limits: kernel.Limits, args: []const kernel.Argument) !void {
332 try execute.runCpu(ProgramType, allocator, limits, args);
333 }
334
335 pub fn runCpuWithDiagnostic(
336 allocator: std.mem.Allocator,
337 limits: kernel.Limits,
338 args: []const kernel.Argument,
339 diagnostic: *kernel.ExecutionDiagnostic,
340 ) !void {
341 try execute.runCpuWithDiagnostic(ProgramType, allocator, limits, args, diagnostic);
342 }
343
344 pub fn verify(allocator: std.mem.Allocator, limits: kernel.Limits) !void {
345 try execute.verify(ProgramType, allocator, limits);
346 }
347 };
348 }