1 # Building HAT
2
3 ----
4 * [Contents](hat-00.md)
5 * Build Babylon and HAT
6 * [Quick Install](hat-01-quick-install.md)
7 * [Building Babylon with jtreg](hat-01-02-building-babylon.md)
8 * [Building HAT with jtreg](hat-01-03-building-hat.md)
9 * [Enabling the NVIDIA CUDA Backend](hat-01-05-building-hat-for-cuda.md)
10 * [Testing Framework](hat-02-testing-framework.md)
11 * [Running Examples](hat-03-examples.md)
12 * [HAT Programming Model](hat-03-programming-model.md)
13 * Interface Mapping
14 * [Interface Mapping Overview](hat-04-01-interface-mapping.md)
15 * [Cascade Interface Mapping](hat-04-02-cascade-interface-mapping.md)
16 * Development
17 * [Project Layout](hat-01-01-project-layout.md)
18 * [IntelliJ Code Formatter](hat-development.md)
19 * Implementation Details
20 * [Walkthrough Of Accelerator.compute()](hat-accelerator-compute.md)
21 * [How we minimize buffer transfers](hat-minimizing-buffer-transfers.md)
22 * [Running HAT with Docker on NVIDIA GPUs](hat-07-docker-build-nvidia.md)
23 ---
24
25 # Building HAT with Script
26
27 We initially used `maven` and `cmake` to build HAT. If you feel more comfortable
28 with maven consider [building with maven and cmake](hat-01-03-building-hat-with-maven.md)
29 but it is possible that maven support will be removed if the `Script` approach takes off.
30
31 ## Dependencies
32
33 Before we start to build HAT we will need `cmake` and `jextract` installed.
34
35 You can download `jextract` from [here](https://jdk.java.net/jextract/)
36
37 Use `sudo apt` on Linux or `brew install`.
38
39 ```bash
40 sudo apt install cmake
41
42 ```
43
44 ```bash
45 brew install cmake
46 ```
47
48 You will also need a Babylon JDK built (the one we built [here](hat-01-02-building-babylon.md))
49
50 ## Setting your PATH variable
51
52 To build HAT we will need `JAVA_HOME` to point to our prebuilt babylon jdk
53
54 I suggest you also create a `JEXTRACT_HOME` var to point to the location where you placed JEXTRACT. The jextract EA builds can be found at https://jdk.java.net/jextract/.
55
56 In my case
57 ```
58 export JEXTRACT_HOME=/Users/me/jextract-22
59 ```
60
61 Make sure also that `cmake` in in your PATH
62
63 ## ./env.bash
64
65 Thankfully just sourcing the top level `env.bash` script should then be able to set up your `PATH` for you.
66
67 It should detect the arch type (AARCH64 or X86_46) and
68 select the correct relative parent dir for your BABYLON_JDK and inject that dir in your `PATH`.
69
70 It should also add jextract to your PATH (based on the value you set above for `JEXTRACT_HOME`)
71
72
73 ```bash
74 cd hat
75 export JEXTRACT_HOME=/Users/me/jextract-22
76 . ./env.bash
77 echo ${JAVA_HOME}
78 /Users/me/github/babylon/hat/../build/macosx-aarch64-server-release/jdk
79 echo ${PATH}
80 /Users/me/github/babylon/hat/../build/macosx-aarch64-server-release/jdk/bin:/Users/me/jextract-22/bin:/usr/local/bin:......
81 ```
82
83 ## Building using bld
84
85 To build hat artifacts (hat jar + backends and examples)
86 ```bash
87 java @hat/bld
88 ```
89
90 This places build artifacts in the `build` and `stages` dirs
91
92 ```bash
93 cd hat
94 . ./env.bash
95 java @hat/bld
96 ls build
97 hat-1.0.jar hat-example-heal-1.0.jar libptx_backend.dylib
98 hat-backend-ffi-cuda-1.0.jar hat-example-mandel-1.0.jar libspirv_backend.dylib
99 hat-backend-ffi-mock-1.0.jar hat-example-squares-1.0.jar mock_info
100 hat-backend-ffi-opencl-1.0.jar hat-example-view-1.0.jar opencl_info
101 hat-backend-ffi-ptx-1.0.jar hat-example-violajones-1.0.jar ptx_info
102 hat-backend-ffi-spirv-1.0.jar libmock_backend.dylib spirv_info
103 hat-example-experiments-1.0.jar libopencl_backend.dylib
104 ls stage
105 opencl_jextracted opengl_jextracted
106 ```
107
108 `bld` relies on cmake to build native code for backends, so if cmake finds OpenCL libs/headers, you will see libopencl_backend (.so or .dylib) in the build dir, if cmake finds CUDA you will see libcuda_backend(.so or .dylib)
109
110 We have another script called `sanity` which will check all .md/.java/.cpp/.h for tabs, lines that end with whitespace
111 or files without appropriate licence headers
112
113 This is run using
114
115 ```bash
116 java @hat/sanity
117 ```
118
119 ## Running an example
120
121 To run a HAT example we can run from the artifacts in `build` dir
122
123 ```bash
124 ${JAVA_HOME}/bin/java \
125 --add-modules jdk.incubator.code --enable-preview --enable-native-access=ALL-UNNAMED \
126 --class-path build/hat-core-1.0.jar:build/hat-example-shared-1.0.jar:build/hat-backend-ffi-shared-1.0.jar:build/hat-backend-ffi-opencl-1.0.jar:build/hat-example-mandel-1.0.jar \
127 --add-exports=java.base/jdk.internal=ALL-UNNAMED \
128 -Djava.library.path=build\
129 mandel.Main
130 ```
131
132 The `hat/run.java` script can also be used which simply needs the backend
133 name `ffi-opencl|ffi-java|ffi-cuda|ffi-ptx|ffi-mock` and the package name `mandel`
134
135 ```bash
136 java @hat/run ffi-opencl mandel
137 ```
138
139 If you pass `headless` as the first arg
140
141 ```bash
142 java @hat/run headless ffi-opencl mandel
143 ```
144
145 This sets `-Dheadless=true` and passes '--headless' to the example. Some examples can use this to avoid launching UI.
146
147
148 # More Bld info
149 `hat/Script.java` is an evolving set of static methods and types required (so far.. ;) )
150 to be able to build HAT, hat backends and examples via the `bld` script
151
152 We rely on java's ability to launch java source directly (without needing to javac first)
153
154 * [JEP 458: Launch Multi-File Source-Code Program](https://openjdk.org/jeps/458)
155 * [JEP 330: Launch Single-File Source-Code Programs](https://openjdk.org/jeps/330)
156
157 The `hat/bld.java` script (really java source) can be run like this
158
159 ```bash
160 java --add-modules jdk.incubator.code --enable-preview --source 26 hat/bld.java
161 ```
162
163 In our case the magic is under the `hat`subdir
164
165 We also have a handy `hat/XXXX` which allows us to avoid specifying common args `--enable-preview --source 26` eash time we launch a script
166
167 ```
168 hat
169 ├── hat
170 | ├── Script.java
171 | ├── sanity (the args for sanity.java) "--enable-preview --source 26 sanity"
172 | |-- sanity.java (the script)
173 | ├── run (the args for sanity.java) "--enable-preview --source 26 hatrun"
174 | |-- run.java (the script)
175 | ├── bld (the args for bld.java) "--enable-preview --source 26 bld"
176 | ├── bld.java (the script)
177
178 ```
179
180 For example
181 ```bash
182 java @hat/bld
183 ```
184
185 Is just a shortcut for
186 ```bash
187 java --add-modules jdk.incubator.code --enable-preview --source 26 hat/bld.java
188 ```
189
190 ----
191 ### HAT runtime environment variable.
192
193 During ffi-backend development we added some useful flags to pass to native code to allow us to trace calls, inject logging, control options.
194
195 These should be considered just development flags.
196
197 At runtime the ffi-backends all communicate from the java side to the native side via a 32 bit 'config' int.
198
199 The Java side class [hat.backend.ffi.Config](https://github.com/openjdk/babylon/blob/code-reflection/hat/backends/ffi/shared/src/main/java/hat/backend/ffi/Config.java)
200
201 Is initialized from an environment variable `HAT` at runtime
202
203 So for example when we launch
204 ```bash
205 java @hat/run ffi-opencl heal
206 ```
207
208 We can pass config info to `HAT` via either `-DHAT=xxx` or via the `HAT` ENV variable.
209
210 So for example to get HAT to dump the text form of the kernel code models.
211
212 ```
213 HAT=INFO,SHOW_KERNEL_MODEL java @hat/run ffi-opencl heal
214 ```
215
216 Or to show generated opencl or cuda code
217 ```
218 HAT=INFO,SHOW_CODE java @hat/run ffi-opencl heal
219 ```
220
221 This is particularly useful for selecting PLATFORM + DEVICE if you have multiple GPU devices.
222
223 Here we select DEVICE 0 on PLATFORM 0 (actually the default)
224 ```
225 HAT=INFO,PLATFORM:0,DEVICE:0,SHOW_CODE ...
226 ```
227 or for DEVICE 1 on PLATFORM 1
228 ```
229 HAT=INFO,PLATFORM:1,DEVICE:1,SHOW_CODE ...
230 ```
231
232 No the platform and device id's are 4 bits. This probably works for development, but we will need a more expressive way of capturing this via the accelerator selection.
233
234 This just allows us to test without code changes.
235
236 To keep he java code and the native code in sync. The `main` method at the end of
237 [hat.backend.ffi.Config](https://github.com/openjdk/babylon/blob/code-reflection/hat/backends/ffi/shared/src/main/java/hat/backend/ffi/Config.java)
238 is actually used to create the C99 header for Cuda and OpenCL ffi-backends.
239
240 So whenever we change the Java config class we should run the main method to generate the header. This is not really robust, (but proved way better than trying to remember for all backends) but you need to know, if you add move config bits to the Java side.
241
242 The Main method uses a variant of the code builders used for C99 style code (CUDA/OpenCL) to generate the config.h header.
243
244 This is how we keep the ffi based backends in sync
245
246 Some more useful `config bits`
247
248 ```
249 HAT=PTX java @hat/run ffi-cuda ....
250 ```
251 Sends PTX generated by our prototype PTX generator to the backend (for CUDA) rather than C99 code.
252
253 ```
254 HAT=INFO java @hat/run ....
255 ```
256
257 Will dump all of the `config bits` from the native side.
258
259 At present this yields
260 ```
261 native minimizeCopies 0
262 native trace 0
263 native profile 0
264 native showCode 0
265 native showKernelModel 0
266 native showComputeModel 0
267 native info 1
268 native traceCopies 0
269 native traceSkippedCopies 0
270 native traceEnqueues 0
271 native traceCalls 0
272 native showWhy 0
273 native showState 0
274 native ptx 0
275 native interpret 0
276 ```
277 Generally the flags all represent single bits (except PLATFORM:n and DEVICE:n) and are set using comma separated uppercase+underscore string forms.
278
279
280 So to experiment with `minimizeCopies` and to `showCode` we set `HAT=MINIMIZE_COPIES,SHOW_CODE`