1 Here is the Java source code for a kernel
  2 ```Java
  3 public static void mandel(KernelContext kc, S32Array2D s32Array2D, S32Array pallette, float offsetx, float offsety, float scale) {
  4         if (kc.x < kc.maxX) {
  5             float width = s32Array2D.width();
  6             float height = s32Array2D.height();
  7             float x = ((kc.x % s32Array2D.width()) * scale - (scale / 2f * width)) / width + offsetx;
  8             float y = ((kc.x / s32Array2D.width()) * scale - (scale / 2f * height)) / height + offsety;
  9             float zx = x;
 10             float zy = y;
 11             float new_zx;
 12             int colorIdx = 0;
 13             while ((colorIdx < pallette.length()) && (((zx * zx) + (zy * zy)) < 4f)) {
 14                 new_zx = ((zx * zx) - (zy * zy)) + x;
 15                 zy = (2f * zx * zy) + y;
 16                 zx = new_zx;
 17                 colorIdx++;
 18             }
 19             int color = colorIdx < pallette.length() ? pallette.array(colorIdx) : 0;
 20             s32Array2D.array(kc.x, color);
 21         }
 22     }
 23 
 24 ```
 25 
 26 And here is the babylon code model
 27 
 28 ```
 29 func @"mandel" @loc="39:5:file:/Users/grfrost/orahub/hat/examples/mandel/src/java/mandel/MandelCompute.java"
 30  (%0 : hat.KernelContext, %1 : hat.buffer.S32Array2D, %2 : hat.buffer.S32Array, %3 : float, %4 : float, %5 : float)void -> {
 31     %6 : Var<hat.KernelContext> = var %0 @"kc" ;
 32     %7 : Var<hat.buffer.S32Array2D> = var %1 @"s32Array2D" ;
 33     %8 : Var<hat.buffer.S32Array> = var %2 @"pallette" ;
 34     %9 : Var<float> = var %3 @"offsetx" ;
 35     %10 : Var<float> = var %4 @"offsety" ;
 36     %11 : Var<float> = var %5 @"scale" ;
 37     java.if
 38         ()boolean -> {
 39             %12 : hat.KernelContext = var.load %6 ;
 40             %13 : int = field.load %12 @"hat.KernelContext::x()int" ;
 41             %14 : hat.KernelContext = var.load %6 ;
 42             %15 : int = field.load %14 @"hat.KernelContext::maxX()int" ;
 43             %16 : boolean = lt %13 %15 ;
 44             yield %16 ;
 45         }
 46         ()void -> {
 47             %17 : hat.buffer.S32Array2D = var.load %7 ;
 48             %18 : int = invoke %17 @"hat.buffer.S32Array2D::width()int" ;
 49             %19 : float = conv %18 ;
 50             %20 : Var<float> = var %19 @"width" ;
 51             %21 : hat.buffer.S32Array2D = var.load %7 ;
 52             %22 : int = invoke %21 @"hat.buffer.S32Array2D::height()int" ;
 53             %23 : float = conv %22 ;
 54             %24 : Var<float> = var %23 @"height" ;
 55             %25 : hat.KernelContext = var.load %6 ;
 56             %26 : int = field.load %25 @"hat.KernelContext::x()int" ;
 57             %27 : hat.buffer.S32Array2D = var.load %7 ;
 58             %28 : int = invoke %27 @"hat.buffer.S32Array2D::width()int" ;
 59             %29 : int = mod %26 %28 ;
 60             %30 : float = conv %29 ;
 61             %31 : float = var.load %11 ;
 62             %32 : float = mul %30 %31 ;
 63             %33 : float = var.load %11 ;
 64             %34 : float = constant @"2.0" ;
 65             %35 : float = div %33 %34 ;
 66             %36 : float = var.load %20 ;
 67             %37 : float = mul %35 %36 ;
 68             %38 : float = sub %32 %37 ;
 69             %39 : float = var.load %20 ;
 70             %40 : float = div %38 %39 ;
 71             %41 : float = var.load %9 ;
 72             %42 : float = add %40 %41 ;
 73             %43 : Var<float> = var %42 @"x" ;
 74             %44 : hat.KernelContext = var.load %6 ;
 75             %45 : int = field.load %44 @"hat.KernelContext::x()int" ;
 76             %46 : hat.buffer.S32Array2D = var.load %7 ;
 77             %47 : int = invoke %46 @"hat.buffer.S32Array2D::width()int" ;
 78             %48 : int = div %45 %47 ;
 79             %49 : float = conv %48 ;
 80             %50 : float = var.load %11 ;
 81             %51 : float = mul %49 %50 ;
 82             %52 : float = var.load %11 ;
 83             %53 : float = constant @"2.0" ;
 84             %54 : float = div %52 %53 ;
 85             %55 : float = var.load %24 ;
 86             %56 : float = mul %54 %55 ;
 87             %57 : float = sub %51 %56 ;
 88             %58 : float = var.load %24 ;
 89             %59 : float = div %57 %58 ;
 90             %60 : float = var.load %10 ;
 91             %61 : float = add %59 %60 ;
 92             %62 : Var<float> = var %61 @"y" ;
 93             %63 : float = var.load %43 ;
 94             %64 : Var<float> = var %63 @"zx" ;
 95             %65 : float = var.load %62 ;
 96             %66 : Var<float> = var %65 @"zy" ;
 97             %67 : float = constant @"0.0" ;
 98             %68 : Var<float> = var %67 @"new_zx" ;
 99             %69 : int = constant @"0" ;
100             %70 : Var<int> = var %69 @"colorIdx" ;
101             java.while
102                 ()boolean -> {
103                     %71 : boolean = java.cand
104                         ()boolean -> {
105                             %72 : int = var.load %70 ;
106                             %73 : hat.buffer.S32Array = var.load %8 ;
107                             %74 : int = invoke %73 @"hat.buffer.S32Array::length()int" ;
108                             %75 : boolean = lt %72 %74 ;
109                             yield %75 ;
110                         }
111                         ()boolean -> {
112                             %76 : float = var.load %64 ;
113                             %77 : float = var.load %64 ;
114                             %78 : float = mul %76 %77 ;
115                             %79 : float = var.load %66 ;
116                             %80 : float = var.load %66 ;
117                             %81 : float = mul %79 %80 ;
118                             %82 : float = add %78 %81 ;
119                             %83 : float = constant @"4.0" ;
120                             %84 : boolean = lt %82 %83 ;
121                             yield %84 ;
122                         };
123                     yield %71 ;
124                 }
125                 ()void -> {
126                     %85 : float = var.load %64 ;
127                     %86 : float = var.load %64 ;
128                     %87 : float = mul %85 %86 ;
129                     %88 : float = var.load %66 ;
130                     %89 : float = var.load %66 ;
131                     %90 : float = mul %88 %89 ;
132                     %91 : float = sub %87 %90 ;
133                     %92 : float = var.load %43 ;
134                     %93 : float = add %91 %92 ;
135                     var.store %68 %93 ;
136                     %94 : float = constant @"2.0" ;
137                     %95 : float = var.load %64 ;
138                     %96 : float = mul %94 %95 ;
139                     %97 : float = var.load %66 ;
140                     %98 : float = mul %96 %97 ;
141                     %99 : float = var.load %62 ;
142                     %100 : float = add %98 %99 ;
143                     var.store %66 %100 ;
144                     %101 : float = var.load %68 ;
145                     var.store %64 %101 ;
146                     %102 : int = var.load %70 ;
147                     %103 : int = constant @"1" ;
148                     %104 : int = add %102 %103 ;
149                     var.store %70 %104 ;
150                     java.continue ;
151                 };
152             %105 : int = java.cexpression
153                 ()boolean -> {
154                     %106 : int = var.load %70 ;
155                     %107 : hat.buffer.S32Array = var.load %8 ;
156                     %108 : int = invoke %107 @"hat.buffer.S32Array::length()int" ;
157                     %109 : boolean = lt %106 %108 ;
158                     yield %109 ;
159                 }
160                 ()int -> {
161                     %110 : hat.buffer.S32Array = var.load %8 ;
162                     %111 : int = var.load %70 ;
163                     %112 : long = conv %111 ;
164                     %113 : int = invoke %110 %112 @"hat.buffer.S32Array::array(long)int" ;
165                     yield %113 ;
166                 }
167                 ()int -> {
168                     %114 : int = constant @"0" ;
169                     yield %114 ;
170                 };
171             %115 : Var<int> = var %105 @"color" ;
172             %116 : hat.buffer.S32Array2D = var.load %7 ;
173             %117 : hat.KernelContext = var.load %6 ;
174             %118 : int = field.load %117 @"hat.KernelContext::x()int" ;
175             %119 : long = conv %118 ;
176             %120 : int = var.load %115 ;
177             invoke %116 %119 %120 @"hat.buffer.S32Array2D::array(long, int)void" ;
178             yield ;
179         }
180         ()void -> {
181             yield;
182         };
183     return ;
184 };
185 
186 ```
187 From the above we can generate C99 style CUDA code
188 
189 
190 Here is the Cuda C99 code generated
191 
192 ```C
193 typedef struct KernelContext_s{
194     int x;
195     int maxX;
196 }KernelContext_t;
197 
198 typedef struct S32Array2D_s{
199     int width;
200     int height;
201     int array[0];
202 }S32Array2D_t;
203 
204 typedef struct S32Array_s{
205     int length;
206     int array[0];
207 }S32Array_t;
208 
209 
210 extern "C" __global__ void mandel(
211      S32Array2D_t* s32Array2D,  S32Array_t* pallette, float offsetx, float offsety, float scale
212 ){
213     KernelContext_t kc;
214     kc.x=blockIdx.x*blockDim.x+threadIdx.x;
215     kc.maxX=gridDim.x*blockDim.x;
216     if(kc.x<kc.maxX){
217         float width = (float)s32Array2D->width;
218         float height = (float)s32Array2D->height;
219         float x = ((float)(kc.x%s32Array2D->width)*scale-scale/2.0*width)/width+offsetx;
220         float y = ((float)(kc.x/s32Array2D->width)*scale-scale/2.0*height)/height+offsety;
221         float zx = x;
222         float zy = y;
223         float new_zx = 0.0;
224         int colorIdx = 0;
225         while(colorIdx<pallette->length && zx*zx+zy*zy<4.0){
226             new_zx=zx*zx-zy*zy+x;
227             zy=2.0*zx*zy+y;
228             zx=new_zx;
229             colorIdx=colorIdx+1;
230         }
231         int color = colorIdx<pallette->length?pallette->array[(long)colorIdx]:0;
232         s32Array2D->array[(long)kc.x]=color;
233     }
234     return;
235 }
236 ```
237 
238 Which we can convert to ptx using the nvcc compiler (on a NVDIA platform)
239 
240 `nvcc -ptx mandel.cu -o mandel.ptx`
241 
242 ```
243 //
244 // Generated by NVIDIA NVVM Compiler
245 //
246 // Compiler Build ID: CL-33191640
247 // Cuda compilation tools, release 12.2, V12.2.140
248 // Based on NVVM 7.0.1
249 //
250 
251 .version 8.2
252 .target sm_52
253 .address_size 64
254 
255         // .globl       mandel
256 
257 .visible .entry mandel(
258         .param .u64 mandel_param_0,
259         .param .u64 mandel_param_1,
260         .param .f32 mandel_param_2,
261         .param .f32 mandel_param_3,
262         .param .f32 mandel_param_4
263 )
264 {
265         .reg .pred      %p<9>;
266         .reg .f32       %f<29>;
267         .reg .b32       %r<24>;
268         .reg .f64       %fd<22>;
269         .reg .b64       %rd<9>;
270 
271 
272         ld.param.u64    %rd3, [mandel_param_0];
273         ld.param.u64    %rd4, [mandel_param_1];
274         ld.param.f32    %f13, [mandel_param_2];
275         ld.param.f32    %f14, [mandel_param_3];
276         ld.param.f32    %f15, [mandel_param_4];
277         cvta.to.global.u64      %rd1, %rd4;
278         cvta.to.global.u64      %rd2, %rd3;
279         mov.u32         %r8, %ntid.x;
280         mov.u32         %r9, %ctaid.x;
281         mov.u32         %r10, %tid.x;
282         mad.lo.s32      %r1, %r9, %r8, %r10;
283         mov.u32         %r11, %nctaid.x;
284         mul.lo.s32      %r12, %r11, %r8;
285         setp.ge.s32     %p1, %r1, %r12;
286         @%p1 bra        $L__BB0_7;
287 
288         ld.global.u32   %r14, [%rd2];
289         cvt.rn.f32.s32  %f16, %r14;
290         ld.global.u32   %r15, [%rd2+4];
291         cvt.rn.f32.s32  %f17, %r15;
292         div.s32         %r16, %r1, %r14;
293         mul.lo.s32      %r17, %r16, %r14;
294         sub.s32         %r18, %r1, %r17;
295         cvt.rn.f32.s32  %f18, %r18;
296         mul.f32         %f19, %f18, %f15;
297         cvt.f64.f32     %fd2, %f19;
298         cvt.f64.f32     %fd3, %f15;
299         mul.f64         %fd4, %fd3, 0d3FE0000000000000;
300         cvt.f64.f32     %fd5, %f16;
301         mul.f64         %fd6, %fd4, %fd5;
302         sub.f64         %fd7, %fd2, %fd6;
303         div.rn.f64      %fd8, %fd7, %fd5;
304         cvt.f64.f32     %fd9, %f13;
305         add.f64         %fd10, %fd8, %fd9;
306         cvt.rn.f32.f64  %f1, %fd10;
307         cvt.rn.f32.s32  %f20, %r16;
308         mul.f32         %f21, %f20, %f15;
309         cvt.f64.f32     %fd11, %f21;
310         cvt.f64.f32     %fd12, %f17;
311         mul.f64         %fd13, %fd4, %fd12;
312         sub.f64         %fd14, %fd11, %fd13;
313         div.rn.f64      %fd15, %fd14, %fd12;
314         cvt.f64.f32     %fd16, %f14;
315         add.f64         %fd17, %fd15, %fd16;
316         cvt.rn.f32.f64  %f27, %fd17;
317         ld.global.u32   %r2, [%rd1];
318         setp.lt.s32     %p2, %r2, 1;
319         mov.u32         %r23, 0;
320         mul.f32         %f26, %f1, %f1;
321         mul.f32         %f25, %f27, %f27;
322         add.f32         %f22, %f26, %f25;
323         setp.geu.f32    %p3, %f22, 0f40800000;
324         or.pred         %p4, %p2, %p3;
325         mov.u32         %r22, %r23;
326         @%p4 bra        $L__BB0_4;
327 
328         cvt.f64.f32     %fd1, %f27;
329         mov.f32         %f28, %f1;
330 
331 $L__BB0_3:
332         sub.f32         %f23, %f26, %f25;
333         add.f32         %f9, %f23, %f1;
334         cvt.f64.f32     %fd18, %f28;
335         add.f64         %fd19, %fd18, %fd18;
336         cvt.f64.f32     %fd20, %f27;
337         fma.rn.f64      %fd21, %fd19, %fd20, %fd1;
338         cvt.rn.f32.f64  %f27, %fd21;
339         add.s32         %r22, %r22, 1;
340         setp.lt.s32     %p5, %r22, %r2;
341         mul.f32         %f26, %f9, %f9;
342         mul.f32         %f25, %f27, %f27;
343         add.f32         %f24, %f26, %f25;
344         setp.lt.f32     %p6, %f24, 0f40800000;
345         and.pred        %p7, %p5, %p6;
346         mov.f32         %f28, %f9;
347         @%p7 bra        $L__BB0_3;
348 
349 $L__BB0_4:
350         setp.ge.s32     %p8, %r22, %r2;
351         @%p8 bra        $L__BB0_6;
352 
353         mul.wide.s32    %rd5, %r22, 4;
354         add.s64         %rd6, %rd1, %rd5;
355         ld.global.u32   %r23, [%rd6+4];
356 
357 $L__BB0_6:
358         mul.wide.s32    %rd7, %r1, 4;
359         add.s64         %rd8, %rd2, %rd7;
360         st.global.u32   [%rd8+8], %r23;
361 
362 $L__BB0_7:
363         ret;
364 
365 }
366 ```
367 But we would like to create the ptx directly from the babylon model, without being on an NVidia platform.  Probably the lowered model
368 
369 We will probably use the lowered babylon model
370 
371 ```
372 func @"mandel" @loc="39:5:file:/Users/grfrost/orahub/hat/examples/mandel/src/java/mandel/MandelCompute.java"
373   (%0 : hat.KernelContext, %1 : hat.buffer.S32Array2D, %2 : hat.buffer.S32Array, %3 : float, %4 : float, %5 : float)void -> {
374     %6 : Var<hat.KernelContext> = var %0 @"kc" ;
375     %7 : Var<hat.buffer.S32Array2D> = var %1 @"s32Array2D" ;
376     %8 : Var<hat.buffer.S32Array> = var %2 @"pallette" ;
377     %9 : Var<float> = var %3 @"offsetx" ;
378     %10 : Var<float> = var %4 @"offsety" ;
379     %11 : Var<float> = var %5 @"scale" ;
380     %12 : hat.KernelContext = var.load %6 ;
381     %13 : int = field.load %12 @"hat.KernelContext::x()int" ;
382     %14 : hat.KernelContext = var.load %6 ;
383     %15 : int = field.load %14 @"hat.KernelContext::maxX()int" ;
384     %16 : boolean = lt %13 %15 ;
385     cbranch %16 ^block_0 ^block_1;
386 
387   ^block_0:
388     %17 : hat.buffer.S32Array2D = var.load %7 ;
389     %18 : int = invoke %17 @"hat.buffer.S32Array2D::width()int" ;
390     %19 : float = conv %18 ;
391     %20 : Var<float> = var %19 @"width" ;
392     %21 : hat.buffer.S32Array2D = var.load %7 ;
393     %22 : int = invoke %21 @"hat.buffer.S32Array2D::height()int" ;
394     %23 : float = conv %22 ;
395     %24 : Var<float> = var %23 @"height" ;
396     %25 : hat.KernelContext = var.load %6 ;
397     %26 : int = field.load %25 @"hat.KernelContext::x()int" ;
398     %27 : hat.buffer.S32Array2D = var.load %7 ;
399     %28 : int = invoke %27 @"hat.buffer.S32Array2D::width()int" ;
400     %29 : int = mod %26 %28 ;
401     %30 : float = conv %29 ;
402     %31 : float = var.load %11 ;
403     %32 : float = mul %30 %31 ;
404     %33 : float = var.load %11 ;
405     %34 : float = constant @"2.0" ;
406     %35 : float = div %33 %34 ;
407     %36 : float = var.load %20 ;
408     %37 : float = mul %35 %36 ;
409     %38 : float = sub %32 %37 ;
410     %39 : float = var.load %20 ;
411     %40 : float = div %38 %39 ;
412     %41 : float = var.load %9 ;
413     %42 : float = add %40 %41 ;
414     %43 : Var<float> = var %42 @"x" ;
415     %44 : hat.KernelContext = var.load %6 ;
416     %45 : int = field.load %44 @"hat.KernelContext::x()int" ;
417     %46 : hat.buffer.S32Array2D = var.load %7 ;
418     %47 : int = invoke %46 @"hat.buffer.S32Array2D::width()int" ;
419     %48 : int = div %45 %47 ;
420     %49 : float = conv %48 ;
421     %50 : float = var.load %11 ;
422     %51 : float = mul %49 %50 ;
423     %52 : float = var.load %11 ;
424     %53 : float = constant @"2.0" ;
425     %54 : float = div %52 %53 ;
426     %55 : float = var.load %24 ;
427     %56 : float = mul %54 %55 ;
428     %57 : float = sub %51 %56 ;
429     %58 : float = var.load %24 ;
430     %59 : float = div %57 %58 ;
431     %60 : float = var.load %10 ;
432     %61 : float = add %59 %60 ;
433     %62 : Var<float> = var %61 @"y" ;
434     %63 : float = var.load %43 ;
435     %64 : Var<float> = var %63 @"zx" ;
436     %65 : float = var.load %62 ;
437     %66 : Var<float> = var %65 @"zy" ;
438     %67 : float = constant @"0.0" ;
439     %68 : Var<float> = var %67 @"new_zx" ;
440     %69 : int = constant @"0" ;
441     %70 : Var<int> = var %69 @"colorIdx" ;
442     branch ^block_2;
443 
444   ^block_2:
445     %71 : int = var.load %70 ;
446     %72 : hat.buffer.S32Array = var.load %8 ;
447     %73 : int = invoke %72 @"hat.buffer.S32Array::length()int" ;
448     %74 : boolean = lt %71 %73 ;
449     cbranch %74 ^block_3 ^block_4(%74);
450 
451   ^block_3:
452     %75 : float = var.load %64 ;
453     %76 : float = var.load %64 ;
454     %77 : float = mul %75 %76 ;
455     %78 : float = var.load %66 ;
456     %79 : float = var.load %66 ;
457     %80 : float = mul %78 %79 ;
458     %81 : float = add %77 %80 ;
459     %82 : float = constant @"4.0" ;
460     %83 : boolean = lt %81 %82 ;
461     branch ^block_4(%83);
462 
463   ^block_4(%84 : boolean):
464     cbranch %84 ^block_5 ^block_6;
465 
466   ^block_5:
467     %85 : float = var.load %64 ;
468     %86 : float = var.load %64 ;
469     %87 : float = mul %85 %86 ;
470     %88 : float = var.load %66 ;
471     %89 : float = var.load %66 ;
472     %90 : float = mul %88 %89 ;
473     %91 : float = sub %87 %90 ;
474     %92 : float = var.load %43 ;
475     %93 : float = add %91 %92 ;
476     var.store %68 %93 ;
477     %94 : float = constant @"2.0" ;
478     %95 : float = var.load %64 ;
479     %96 : float = mul %94 %95 ;
480     %97 : float = var.load %66 ;
481     %98 : float = mul %96 %97 ;
482     %99 : float = var.load %62 ;
483     %100 : float = add %98 %99 ;
484     var.store %66 %100 ;
485     %101 : float = var.load %68 ;
486     var.store %64 %101 ;
487     %102 : int = var.load %70 ;
488     %103 : int = constant @"1" ;
489     %104 : int = add %102 %103 ;
490     var.store %70 %104 ;
491     branch ^block_2;
492 
493   ^block_6:
494     %105 : int = var.load %70 ;
495     %106 : hat.buffer.S32Array = var.load %8 ;
496     %107 : int = invoke %106 @"hat.buffer.S32Array::length()int" ;
497     %108 : boolean = lt %105 %107 ;
498     cbranch %108 ^block_7 ^block_8;
499 
500   ^block_7:
501     %109 : hat.buffer.S32Array = var.load %8 ;
502     %110 : int = var.load %70 ;
503     %111 : long = conv %110 ;
504     %112 : int = invoke %109 %111 @"hat.buffer.S32Array::array(long)int" ;
505     branch ^block_9(%112);
506 
507   ^block_8:
508     %113 : int = constant @"0" ;
509     branch ^block_9(%113);
510 
511   ^block_9(%114 : int):
512     %115 : Var<int> = var %114 @"color" ;
513     %116 : hat.buffer.S32Array2D = var.load %7 ;
514     %117 : hat.KernelContext = var.load %6 ;
515     %118 : int = field.load %117 @"hat.KernelContext::x()int" ;
516     %119 : long = conv %118 ;
517     %120 : int = var.load %115 ;
518     invoke %116 %119 %120 @"hat.buffer.S32Array2D::array(long, int)void" ;
519     branch ^block_10;
520 
521   ^block_1:
522     branch ^block_10;
523 
524   ^block_10:
525     return ;
526 };
527 ```
528