1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 #pragma once
 27 
 28 #include <iostream>
 29 #include <map>
 30 #include <vector>
 31 #include <cstdio>
 32 #include <cstring>
 33 #include <unistd.h>
 34 #include <sys/time.h>
 35 #include <iostream>
 36 #include <iomanip>
 37 #include <bitset>
 38 #include <stack>
 39 
 40 #ifdef __APPLE__
 41 #define LongUnsignedNewline "%llu\n"
 42 #define Size_tNewline "%lu\n"
 43 #define LongHexNewline "(0x%llx)\n"
 44 #define alignedMalloc(size, alignment) memalign(alignment, size)
 45 #define SNPRINTF snprintf
 46 #else
 47 
 48 #include <malloc.h>
 49 
 50 #define LongHexNewline "(0x%lx)\n"
 51 #define LongUnsignedNewline "%lu\n"
 52 #define Size_tNewline "%lu\n"
 53 #if defined (_WIN32)
 54 #include "windows.h"
 55 #define alignedMalloc(size, alignment) _aligned_malloc(size, alignment)
 56 #define SNPRINTF _snprintf
 57 #else
 58 #define alignedMalloc(size, alignment) memalign(alignment, size)
 59 #define SNPRINTF  snprintf
 60 #endif
 61 #endif
 62 typedef char s8_t;
 63 typedef char byte;
 64 typedef char boolean;
 65 typedef char z1_t;
 66 typedef unsigned char u8_t;
 67 typedef short s16_t;
 68 typedef unsigned short u16_t;
 69 typedef unsigned int u32_t;
 70 typedef int s32_t;
 71 typedef float f32_t;
 72 typedef double f64_t;
 73 typedef long s64_t;
 74 typedef unsigned long u64_t;
 75 
 76 extern void hexdump(void *ptr, int buflen);
 77 
 78  struct Buffer_s {
 79     void *memorySegment;   // Address of a Buffer/MemorySegment
 80     long sizeInBytes;     // The size of the memory segment in bytes
 81     void *vendorPtr;       // The vendor side can reference vendor into
 82     u8_t access;          // 0=??/1=RO/2=WO/3=RW if this is a buffer
 83     u8_t state;           // 0=UNKNOWN/1=GPUDIRTY/2=JAVADIRTY
 84 } ;
 85 
 86  union Value_u {
 87     boolean z1;  // 'Z'
 88     u8_t s8;  // 'B'
 89     u16_t u16;  // 'C'
 90     s16_t s16;  // 'S'
 91     u16_t x16;  // 'C' or 'S"
 92     s32_t s32;  // 'I'
 93     s32_t x32;  // 'I' or 'F'
 94     f32_t f32; // 'F'
 95     f64_t f64; // 'D'
 96     s64_t s64; // 'J'
 97     s64_t x64; // 'D' or 'J'
 98     Buffer_s buffer; // '&'
 99 } ;
100 
101  struct Arg_s {
102     u32_t idx;          // 0..argc
103     u8_t variant;      // which variant 'I','Z','S','J','F', '&' implies Buffer/MemorySegment
104     u8_t pad8[8];
105     Value_u value;
106     u8_t pad6[6];
107 };
108 
109 struct ArgArray_s {
110     u32_t argc;
111     u8_t pad12[12];
112     Arg_s argv[0/*argc*/];
113     // void * vendorPtr;
114     // int schemaLen
115     // char schema[schemaLen]
116 };
117 
118 class ArgSled {
119 private:
120     ArgArray_s *argArray;
121 public:
122     int argc() {
123         return argArray->argc;
124     }
125 
126     Arg_s *arg(int n) {
127         Arg_s *a = (argArray->argv + n);
128         return a;
129     }
130 
131     void hexdumpArg(int n) {
132         hexdump(arg(n), sizeof(Arg_s));
133     }
134 
135     void dumpArg(int n) {
136         Arg_s *a = arg(n);
137         int idx = (int) a->idx;
138         std::cout << "arg[" << idx << "]";
139         char variant = (char) a->variant;
140         switch (variant) {
141             case 'F':
142                 std::cout << " f32 " << a->value.f32 << std::endl;
143                 break;
144             case 'I':
145                 std::cout << " s32 " << a->value.s32 << std::endl;
146                 break;
147             case 'D':
148                 std::cout << " f64 " << a->value.f64 << std::endl;
149                 break;
150             case 'J':
151                 std::cout << " s64 " << a->value.s64 << std::endl;
152                 break;
153             case 'C':
154                 std::cout << " u16 " << a->value.u16 << std::endl;
155                 break;
156             case 'S':
157                 std::cout << " s16 " << a->value.s32 << std::endl;
158                 break;
159             case 'Z':
160                 std::cout << " z1 " << a->value.z1 << std::endl;
161                 break;
162             case '&':
163                 std::cout << " buffer {"
164                           << " void *address = 0x" << std::hex << (long) a->value.buffer.memorySegment << std::dec
165                           << ", long bytesSize= 0x" << std::hex << (long) a->value.buffer.sizeInBytes << std::dec
166                           << "}" << std::endl;
167                 break;
168             default:
169                 std::cout << (char) variant << std::endl;
170                 break;
171         }
172     }
173 
174     void *vendorPtrPtr() {
175         Arg_s *a = arg(argc());
176         return (void *) a;
177     }
178 
179     int *schemaLenPtr() {
180         int *schemaLenP = (int *) ((char *) vendorPtrPtr() + sizeof(void *));
181         return schemaLenP;
182     }
183 
184     int schemaLen() {
185         return *schemaLenPtr();
186     }
187 
188     char *schema() {
189         int *schemaLenP = ((int *) ((char *) vendorPtrPtr() + sizeof(void *)) + 1);
190         return (char *) schemaLenP;
191     }
192 
193     ArgSled(ArgArray_s *argArray)
194             : argArray(argArray) {}
195 };
196 
197 
198 class Timer {
199     struct timeval startTV, endTV;
200 public:
201     unsigned long elapsed_us;
202 
203     void start() {
204         gettimeofday(&startTV, NULL);
205     }
206 
207     unsigned long end() {
208         gettimeofday(&endTV, NULL);
209         elapsed_us = (endTV.tv_sec - startTV.tv_sec) * 1000000;      // sec to us
210         elapsed_us += (endTV.tv_usec - startTV.tv_usec);
211         return elapsed_us;
212     }
213 };
214 
215 
216 class BuildInfo {
217 public:
218     char *src;
219     char *log;
220     bool ok;
221 
222     BuildInfo(char *src, char *log, bool ok)
223             : src(src), log(log), ok(ok) {
224     }
225 
226     ~BuildInfo() {
227         if (src) {
228             delete[] src;
229         }
230         if (log) {
231             delete[] log;
232         }
233     }
234 
235 };
236 
237 
238 //extern "C" void dumpArgArray(void *ptr);
239 
240 
241 extern void hexdump(void *ptr, int buflen);
242 
243 class Sled {
244 public:
245     static void show(std::ostream &out, void *argArray);
246 };
247 
248 
249 class NDRange {
250 public:
251     int x;
252     int maxX;
253 };
254 
255 class Backend {
256 public:
257     class Config {
258     public:
259     };
260 
261     class Program {
262     public:
263         class Kernel {
264         public:
265             class Buffer {
266             public:
267                 Kernel *kernel;
268                 Arg_s *arg;
269 
270                 virtual void copyToDevice() = 0;
271 
272                 virtual void copyFromDevice() = 0;
273 
274                 Buffer(Kernel *kernel, Arg_s *arg)
275                         : kernel(kernel), arg(arg) {
276                 }
277 
278                 virtual ~Buffer() {}
279             };
280 
281             char *name;// strduped!
282 
283             Program *program;
284 
285             virtual long ndrange(void *argArray) = 0;
286             static char *copy(char *name){
287                 size_t len =::strlen(name);
288                 char *buf = new char[len+1];
289                 memcpy(buf, name, len);
290                 buf[len]='\0';
291                 return buf;
292             }
293             Kernel(Program *program, char *name)
294                     : program(program), name(copy(name)) {
295             }
296 
297             virtual ~Kernel() {
298                 if (name) {
299                     delete[] name;
300                 }
301             }
302         };
303 
304     public:
305         Backend *backend;
306         BuildInfo *buildInfo;
307 
308         virtual long getKernel(int nameLen, char *name) = 0;
309 
310         virtual bool programOK() = 0;
311 
312         Program(Backend *backend, BuildInfo *buildInfo)
313                 : backend(backend), buildInfo(buildInfo) {
314         }
315 
316         virtual ~Program() {
317             if (buildInfo != nullptr) {
318                 delete buildInfo;
319             }
320         };
321 
322     };
323 
324     Config *config;
325     int configSchemaLen;
326     char *configSchema;
327 
328     Backend(Config *config, int configSchemaLen, char *configSchema)
329             : config(config), configSchemaLen(configSchemaLen), configSchema(configSchema) {}
330 
331     virtual ~Backend() {};
332 
333     virtual void info() = 0;
334 
335     virtual int getMaxComputeUnits() = 0;
336 
337     virtual long compileProgram(int len, char *source) = 0;
338 
339 
340 };
341 
342 extern "C" long getBackend(void *config, int configSchemaLen, char *configSchema);
343 extern "C" void info(long backendHandle);
344 extern "C" int getMaxComputeUnits(long backendHandle);
345 extern "C" long compileProgram(long backendHandle, int len, char *source);
346 extern "C" long getKernel(long programHandle, int len, char *name);
347 extern "C" void releaseBackend(long backendHandle);
348 extern "C" void releaseProgram(long programHandle);
349 extern "C" bool programOK(long programHandle);
350 extern "C" void releaseKernel(long kernelHandle);
351 extern "C" long ndrange(long kernelHandle, void *argArray);
352