13 #include "hc_am_internal.hpp" 14 #include "hsa_atomic.h" 22 #define HC_FEATURE_PRINTF (1) 25 #define HC_PRINTF_DEBUG (0) 45 std::atomic_ullong al;
47 unsigned long long ull;
50 enum PrintfPacketDataType {
52 PRINTF_BUFFER_SIZE = 0
53 ,PRINTF_STRING_BUFFER = 1
54 ,PRINTF_STRING_BUFFER_SIZE = 2
56 ,PRINTF_HEADER_SIZE = 4
66 ,PRINTF_CONST_VOID_PTR
68 ,PRINTF_CONST_CHAR_PTR
73 void clear() [[
hc,cpu]] { type = PRINTF_UNUSED; }
74 void set(
unsigned int d) [[hc,cpu]] { type = PRINTF_UNSIGNED_INT; data.ui = d; }
75 void set(
int d) [[hc,cpu]] { type = PRINTF_SIGNED_INT; data.i = d; }
76 void set(
float d) [[hc,cpu]] { type = PRINTF_FLOAT; data.f = d; }
77 void set(
double d) [[hc,cpu]] { type = PRINTF_DOUBLE; data.d = d; }
78 void set(
void* d) [[hc,cpu]] { type = PRINTF_VOID_PTR; data.ptr = d; }
79 void set(
const void* d) [[hc,cpu]] { type = PRINTF_CONST_VOID_PTR; data.cptr = d; }
80 void set(
char* d) [[hc,cpu]] { type = PRINTF_CHAR_PTR; data.ptr = d; }
81 void set(
const char* d) [[hc,cpu]] { type = PRINTF_CONST_CHAR_PTR; data.cptr = d; }
82 PrintfPacketDataType type;
92 ,PRINTF_BUFFER_OVERFLOW = 1
93 ,PRINTF_STRING_BUFFER_OVERFLOW = 2
94 ,PRINTF_UNKNOWN_ERROR = 3
97 static inline PrintfPacket* createPrintfBuffer(
const unsigned int numElements) {
99 if (numElements > PRINTF_MIN_SIZE) {
100 printfBuffer = hc::internal::am_alloc_host_coherent(
sizeof(
PrintfPacket) * numElements);
103 printfBuffer[PRINTF_BUFFER_SIZE].type = PRINTF_BUFFER_SIZE;
104 printfBuffer[PRINTF_BUFFER_SIZE].data.ui = numElements;
108 printfBuffer[PRINTF_STRING_BUFFER].type = PRINTF_STRING_BUFFER;
109 printfBuffer[PRINTF_STRING_BUFFER].data.ptr = hc::internal::am_alloc_host_coherent(
sizeof(
char) * numElements * 12);
110 printfBuffer[PRINTF_STRING_BUFFER_SIZE].type = PRINTF_STRING_BUFFER_SIZE;
111 printfBuffer[PRINTF_STRING_BUFFER_SIZE].data.ui = numElements * 12;
114 printfBuffer[PRINTF_OFFSETS].type = PRINTF_OFFSETS;
115 printfBuffer[PRINTF_OFFSETS].data.uia[0] = PRINTF_HEADER_SIZE;
116 printfBuffer[PRINTF_OFFSETS].data.uia[1] = 0;
121 static inline void deletePrintfBuffer(
PrintfPacket*& buffer) {
123 if (buffer[PRINTF_STRING_BUFFER].data.ptr)
124 hc::am_free(buffer[PRINTF_STRING_BUFFER].data.ptr);
130 static inline unsigned int string_length(
const char* str) [[
hc,cpu]]{
131 unsigned int size = 0;
132 while(str[size]!=
'\0')
137 static inline void copy_n(
char* dest,
const char* src,
const unsigned int len) [[hc,cpu]] {
138 for(
unsigned int i=0; i < len; i++){
144 template <
typename T>
145 std::size_t mem_size_if_string(
typename std::enable_if< std::is_same<T,const char*>::value
146 || std::is_same<T,char*>::value, T>::type s) [[hc,cpu]] {
147 return string_length(s) + 1;
150 template <
typename T>
151 std::size_t mem_size_if_string(
typename std::enable_if< !std::is_same<T,const char*>::value
152 && !std::is_same<T,char*>::value, T>::type s) [[hc,cpu]] {
157 static inline void countArg(
unsigned int& count_arg,
unsigned int& count_char) [[hc,cpu]] {}
158 template <
typename T>
159 static inline void countArg(
unsigned int& count_arg,
unsigned int& count_char,
const T t) [[hc,cpu]] {
161 count_char += mem_size_if_string<T>(t);
163 template <
typename T,
typename... Rest>
164 static inline void countArg(
unsigned int& count_arg,
unsigned int& count_char,
const T t,
const Rest&... rest) [[hc,cpu]] {
166 count_char += mem_size_if_string<T>(t);
167 countArg(count_arg, count_char, rest...);
171 PrintfError process_str_batch(
PrintfPacket* queue,
int poffset,
unsigned int& soffset
172 ,
typename std::enable_if< std::is_same<T,const char*>::value || std::is_same<T,char*>::value, T>::type
string) [[hc,cpu]] {
174 if (queue[poffset].type != PRINTF_CHAR_PTR && queue[poffset].type != PRINTF_CONST_CHAR_PTR)
175 return PRINTF_UNKNOWN_ERROR;
177 unsigned int str_len = string_length(
string);
178 unsigned int sb_offset = soffset;
179 char* string_buffer = (
char*) queue[PRINTF_STRING_BUFFER].data.ptr;
180 if (!string_buffer || soffset + str_len + 1 > queue[PRINTF_STRING_BUFFER_SIZE].data.ui){
181 return PRINTF_STRING_BUFFER_OVERFLOW;
183 copy_n(&string_buffer[sb_offset],
string, str_len + 1);
184 queue[poffset].set(&string_buffer[sb_offset]);
185 soffset += str_len + 1;
186 return PRINTF_SUCCESS;
190 PrintfError process_str_batch(
PrintfPacket* queue,
int poffset,
unsigned int& soffset
191 ,
typename std::enable_if< !std::is_same<T,const char*>::value && !std::is_same<T,char*>::value, T>::type data) [[hc,cpu]] {
193 if (queue[poffset].type == PRINTF_CHAR_PTR || queue[poffset].type == PRINTF_CONST_CHAR_PTR)
194 return PRINTF_UNKNOWN_ERROR;
196 return PRINTF_SUCCESS;
199 template <
typename T>
200 static inline PrintfError set_batch(
PrintfPacket* queue,
int poffset,
unsigned int& soffset,
const T t) [[hc,cpu]] {
201 PrintfError err = PRINTF_SUCCESS;
202 queue[poffset].set(t);
203 err = process_str_batch<T>(queue, poffset, soffset, t);
207 template <
typename T,
typename... Rest>
208 static inline PrintfError set_batch(
PrintfPacket* queue,
int poffset,
unsigned int& soffset,
const T t, Rest... rest) [[hc,cpu]] {
209 PrintfError err = PRINTF_SUCCESS;
210 queue[poffset].set(t);
212 if ((err = process_str_batch<T>(queue, poffset, soffset, t)) != PRINTF_SUCCESS)
215 return set_batch(queue, poffset + 1, soffset, rest...);
218 template <
typename... All>
219 static inline PrintfError printf(
PrintfPacket* queue, All... all) [[hc,cpu]] {
220 unsigned int count_arg = 0;
221 unsigned int count_char = 0;
222 countArg(count_arg, count_char, all...);
224 PrintfError error = PRINTF_SUCCESS;
227 if (!queue || count_arg + 1 + queue[PRINTF_OFFSETS].data.uia[0] > queue[PRINTF_BUFFER_SIZE].data.ui) {
228 error = PRINTF_BUFFER_OVERFLOW;
230 else if (!queue[PRINTF_STRING_BUFFER].data.ptr || count_char + queue[PRINTF_OFFSETS].data.uia[1] > queue[PRINTF_STRING_BUFFER_SIZE].data.ui){
231 error = PRINTF_STRING_BUFFER_OVERFLOW;
239 old_off.ull = queue[PRINTF_OFFSETS].data.al.load();
240 try_off.uia[0] = old_off.uia[0] + count_arg + 1;
241 try_off.uia[1] = old_off.uia[1] + count_char;
242 }
while(!(queue[PRINTF_OFFSETS].data.al.compare_exchange_weak(old_off.ull, try_off.ull)));
244 unsigned int poffset = (
unsigned int)old_off.uia[0];
245 unsigned int soffset = (
unsigned int)old_off.uia[1];
247 if (poffset + count_arg + 1 > queue[PRINTF_BUFFER_SIZE].data.ui) {
248 error = PRINTF_BUFFER_OVERFLOW;
250 else if (soffset + count_char > queue[PRINTF_STRING_BUFFER_SIZE].data.ui){
251 error = PRINTF_STRING_BUFFER_OVERFLOW;
254 if (set_batch(queue, poffset, soffset, count_arg, all...) != PRINTF_SUCCESS)
255 error = PRINTF_STRING_BUFFER_OVERFLOW;
266 #ifdef HCC_ENABLE_ACCELERATOR_PRINTF 268 template <
typename... All>
269 static inline PrintfError printf(
const char* format_string, All... all) [[hc,cpu]] {
270 return printf(hc::printf_buffer, format_string, all...);
276 template <
typename... All>
277 static inline PrintfError printf(
const char* format_string, All... all) [[hc,cpu]] {
278 return PRINTF_SUCCESS;
284 static std::regex specifierPattern(
"(%){1}[-+#0]*[0-9]*((.)[0-9]+){0,1}([diuoxXfFeEgGaAcsp]){1}");
285 static std::regex signedIntegerPattern(
"(%){1}[-+#0]*[0-9]*((.)[0-9]+){0,1}([cdi]){1}");
286 static std::regex unsignedIntegerPattern(
"(%){1}[-+#0]*[0-9]*((.)[0-9]+){0,1}([uoxX]){1}");
287 static std::regex floatPattern(
"(%){1}[-+#0]*[0-9]*((.)[0-9]+){0,1}([fFeEgGaA]){1}");
288 static std::regex pointerPattern(
"(%){1}[ps]");
289 static std::regex doubleAmpersandPattern(
"(%){2}");
291 static inline void processPrintfPackets(
PrintfPacket* packets,
const unsigned int numPackets) {
293 for (
unsigned int i = 0; i < numPackets; ) {
295 unsigned int numPrintfArgs = packets[i++].data.ui;
296 if (numPrintfArgs == 0)
300 unsigned int formatStringIndex = i++;
301 assert(packets[formatStringIndex].type == PRINTF_CHAR_PTR
302 || packets[formatStringIndex].type == PRINTF_CONST_CHAR_PTR);
303 std::string formatString((
const char*)packets[formatStringIndex].data.cptr);
304 std::smatch specifierMatches;
307 std::printf(
"%s:%d \t number of matches = %d\n", __FUNCTION__, __LINE__, (
int)specifierMatches.size());
310 for (
unsigned int j = 1; j < numPrintfArgs; ++j, ++i) {
312 if (!std::regex_search(formatString, specifierMatches, specifierPattern)) {
318 std::string specifier = specifierMatches.str();
320 std::cout <<
" (specifier found: " << specifier <<
") ";
325 std::string prefix = specifierMatches.prefix();
326 prefix = std::regex_replace(prefix,doubleAmpersandPattern,
"%");
327 std::printf(
"%s",prefix.c_str());
329 std::smatch specifierTypeMatch;
330 if (std::regex_search(specifier, specifierTypeMatch, unsignedIntegerPattern)) {
331 std::printf(specifier.c_str(), packets[i].data.ui);
332 }
else if (std::regex_search(specifier, specifierTypeMatch, signedIntegerPattern)) {
333 std::printf(specifier.c_str(), packets[i].data.i);
334 }
else if (std::regex_search(specifier, specifierTypeMatch, floatPattern)) {
335 if (packets[i].type == PRINTF_FLOAT)
336 std::printf(specifier.c_str(), packets[i].data.f);
338 std::printf(specifier.c_str(), packets[i].data.d);
339 }
else if (std::regex_search(specifier, specifierTypeMatch, pointerPattern)) {
340 std::printf(specifier.c_str(), packets[i].data.cptr);
345 formatString = specifierMatches.suffix();
349 formatString = std::regex_replace(formatString,doubleAmpersandPattern,
"%");
350 std::printf(
"%s",formatString.c_str());
352 std::flush(std::cout);
355 static inline void processPrintfBuffer(
PrintfPacket* gpuBuffer) {
357 if (gpuBuffer ==
nullptr)
return;
359 unsigned int cursor = gpuBuffer[PRINTF_OFFSETS].data.uia[0];
362 if (cursor != PRINTF_HEADER_SIZE) {
363 unsigned int bufferSize = gpuBuffer[PRINTF_BUFFER_SIZE].data.ui;
364 unsigned int numPackets = ((bufferSize<cursor)?bufferSize:cursor) - PRINTF_HEADER_SIZE;
366 processPrintfPackets(gpuBuffer+PRINTF_HEADER_SIZE, numPackets);
369 gpuBuffer[PRINTF_OFFSETS].data.uia[0] = PRINTF_HEADER_SIZE;
370 gpuBuffer[PRINTF_OFFSETS].data.uia[1] = 0;
Definition: hc_printf.hpp:29
am_status_t am_free(void *ptr)
Free a block of memory previously allocated with am_alloc.
Heterogeneous C++ (HC) namespace.
Definition: grid_launch.h:10
Definition: hc_printf.hpp:71