1 /* 2 * Copyright (c) 2017, Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 //! 23 //! \file cm_printf_host.h 24 //! \brief Contains Class PFParser definitions 25 //! 26 27 #pragma once 28 29 #define CM_KERNEL_PRINTF_ON 1 30 31 #if CM_KERNEL_PRINTF_ON 32 33 #include <string> 34 35 #define PRINT_HEADER_SIZE 32 36 37 #define CM_PRINT_OBJECT_TYPE_ENTRY_INDEX 0 38 #define CM_PRINT_DATA___TYPE_ENTRY_INDEX 1 39 #define CM_PRINT_LOWER32BITS_ENTRY_INDEX 6 40 #define CM_PRINT_UPPER32BITS_ENTRY_INDEX 7 41 42 #define CM_PRINT_DATA_TYPE_CHAR 0 43 #define CM_PRINT_DATA_TYPE_UCHAR 1 44 #define CM_PRINT_DATA_TYPE_FLOAT 2 45 #define CM_PRINT_DATA_TYPE_INT 3 46 #define CM_PRINT_DATA_TYPE_UINT 4 47 #define CM_PRINT_DATA_TYPE_SHORT 5 48 #define CM_PRINT_DATA_TYPE_USHORT 6 49 #define CM_PRINT_DATA_TYPE_QWORD 7 50 #define CM_PRINT_DATA_TYPE_UQWORD 8 51 #define CM_PRINT_DATA_TYPE_DOUBLE 9 52 53 #define CM_PRINT_OBJECT_TYPE_UNKNOWN 0 54 #define CM_PRINT_OBJECT_TYPE_MATRIX 1 55 #define CM_PRINT_OBJECT_TYPE_VECTOR 2 56 #define CM_PRINT_OBJECT_TYPE_SCALAR 3 57 #define CM_PRINT_OBJECT_TYPE_STRING 4 58 #define CM_PRINT_OBJECT_TYPE_FORMAT 5 59 60 /// If you want to change the static 61 /// buffer change these two macros. 62 #define CM_PRINTF_STATIC_BUFFER_ID 1 63 #define CM_PRINT_BUFFER CM_STATIC_BUFFER_1 64 65 #define CM_PRINTF(f_, ...) fprintf((f_), __VA_ARGS__) 66 67 #define PRINT_BUFFER_HEADER_SIZE 32 68 #define PRINT_PAYLOAD_ALIGN 16 69 #define PRINT_HEADER_SIZE 32 70 #define PRINT_FORMAT_STRING_SIZE 128 71 #define CM_PRINT_SIZE_WITH_PAYLOAD(msize) (PRINT_HEADER_SIZE + (msize-1) / PRINT_PAYLOAD_ALIGN * PRINT_PAYLOAD_ALIGN + PRINT_PAYLOAD_ALIGN) 72 73 /// Structure of header: 74 /// vector<int, 8> header 75 /// [0]: Object type: matrix,vector,scalar,string, or format string. 76 /// [1]: Data type: [u]*int[136]*[6248]_t, float, or double. 77 /// [2]: width 78 /// [3]: height 79 /// [4]: tid 80 /// [5]: reserved3 81 /// [6]: Scalar lower 32bits: [u]*int[13]*[628]_t, float. Lower 32bits of double and [u]*int64_t. 82 /// [7]: Scalar upper 32bits: Upper 32bits of double and [u]*int64_t. 83 84 typedef struct _CM_PRINT_HEADER{ 85 unsigned int objectType; 86 unsigned int dataType; 87 unsigned int width; 88 unsigned int height; 89 unsigned int tid; 90 unsigned int reserved3; 91 unsigned long long scalar64; 92 }CM_PRINT_HEADER, *PCM_PRINT_HEADER; 93 94 enum PRINT_FMT_STATUS 95 { 96 PF_FAIL = 0, 97 PF_SUCCESS = 1 98 }; 99 100 // A small class used to contain the state machine used when parsing the printf string 101 // The issue we have to deal with is that there is a format string with some directives in it - the 102 // format string is received as an object from the client as an object in memory 103 // Any arguments are then passed as separate objects in memory. How many objects are required is 104 // determined by the format string. 105 // The cleanest way to deal with this is to use a very simple recursive descent parser on the format 106 // string in order to process the arguments in the correct way 107 // Here's the grammar for printf format strings (using EBNF). Only one format directive is to be 108 // returned from the input at a time: 109 // 110 // format: 111 // { STRING } directive 112 // 113 // 114 // directive: 115 // PERCENT flags { width } { PERIOD precision } { length_modifier } conversion 116 // 117 // flags: 118 // { MINUS } { PLUS } { SPACE } { ZERO } { HASH } 119 // 120 // width: 121 // INTEGER 122 // | STAR 123 // 124 // precision: 125 // INTEGER 126 // | STAR 127 // 128 // length_modifier: 129 // hh_MOD | h_MOD | l_MOD | ll_MOD | j_MOD | t_MOD | z_MOD | L_MOD 130 // 131 // conversion: 132 // PERCENT 133 // | c_CONV 134 // | s_CONV 135 // | d_CONV 136 // | i_CONV 137 // | o_CONV 138 // | x_CONV 139 // | X_CONV 140 // | u_CONV 141 // | f_CONV 142 // | F_CONV 143 // | e_CONV 144 // | E_CONV 145 // | a_CONV 146 // | A_CONV 147 // | g_CONV 148 // | G_CONV 149 // | n_CONV 150 // | p_CONV 151 // 152 // STRING : [any ASCII character that isn't a %]+ 153 // PERCENT : '%' 154 // MINUS : '-' 155 // PLUS : '+' 156 // SPACE : ' ' 157 // ZERO : '0' 158 // INTEGER : [ 159 // PERIOD : '.' 160 // HASH : '#' 161 // hh_MOD : 'hh' 162 // h_MOD : 'h' 163 // l_MOD : 'l' 164 // ll_MOD : 'll' 165 // j_MOD : 'j' 166 // z_MOD : 'z' 167 // t_MOD : 't' 168 // L_MOD : 'L' 169 // STAR : '*' 170 // c_CONV : 'c' 171 // s_CONV : 's' 172 // d_CONV : 'd' 173 // i_CONV : 'i' 174 // o_CONV : 'o' 175 // x_CONV : 'x' 176 // X_CONV : 'X' 177 // u_CONV : 'u' 178 // f_CONV : 'f' 179 // F_CONV : 'F' 180 // e_CONV : 'e' 181 // E_CONV : 'E' 182 // a_CONV : 'a' 183 // A_CONV : 'A' 184 // g_CONV : 'g' 185 // G_CONV : 'G' 186 // n_CONV : 'n' 187 // p_CONV : 'p' 188 189 class PFParser 190 { 191 public: PFParser(FILE * streamout)192 PFParser(FILE* streamout) : mInSpec(false), mInputStart(nullptr), mCurrLoc(nullptr), mArgsExpected(0), 193 mNumMultArg(0), mUnsupported(false), mError(false), mStreamOut(streamout) {}; setStart(char * start)194 void setStart(char *start) 195 { 196 mInputStart= mCurrLoc = start; 197 // Prime the system with the first token 198 getToken(); 199 } 200 void DumpMemory(unsigned char * memory); 201 void flush(void); 202 203 protected: 204 private: 205 class Token 206 { 207 public: 208 enum TokenType { _None_, Error, 209 String, Percent, Minus, Plus, Space, Zero, Integer, Period, Hash, Star, 210 hh_Mod, h_Mod, l_Mod, ll_Mod, j_Mod, z_Mod, t_Mod, L_Mod, 211 c_Conv, s_Conv, d_Conv, i_Conv, o_Conv, x_Conv, X_Conv, u_Conv, f_Conv, 212 F_Conv, e_Conv, E_Conv, a_Conv, A_Conv, g_Conv, G_Conv, n_Conv, p_Conv, 213 End 214 }; 215 Token()216 Token() : mTokenType(_None_), mTokenInt(0) {}; 217 bool operator==(const Token &other) const { 218 return mTokenType == other.mTokenType; 219 } 220 bool operator==(const TokenType &other) const { 221 return mTokenType == other; 222 } 223 bool operator!=(const Token &other) const { 224 return mTokenType != other.mTokenType; 225 } 226 bool operator!=(const TokenType &other) const { 227 return mTokenType != other; 228 } 229 230 TokenType mTokenType; 231 std::string mTokenString; 232 int mTokenInt; 233 }; 234 235 bool mInSpec; // Mode for lexer - in spec mode or not 236 Token mCurrToken; // The currently lexed token 237 Token mPrevToken; // The previously lexed token 238 char *mInputStart; // The start of the input string 239 char *mCurrLoc; // The current point of processing 240 int mArgsExpected; // For multi-arg format directives - how many still to process 241 int mNumMultArg; // Total number of multi-arg format directives in total 242 int mArgs[2]; // Up to 2 int args can be used in multi-arg format directives 243 bool mUnsupported; // Has the latest parsed format directive contained unsupported 244 // directives (VS doesn't support them all so we can't print them) 245 bool mError; // Error in latest parsed format directive 246 FILE *mStreamOut; // Output stream for kernel print 247 248 PRINT_FMT_STATUS GetNextFmtToken(char * tkn, size_t size); 249 bool outputToken(const char *tkn, PCM_PRINT_HEADER header); 250 void getToken(void); reset(void)251 void reset(void) 252 { 253 mInputStart = mCurrLoc; 254 mUnsupported = false; 255 mError = false; 256 mNumMultArg = mArgsExpected = 0; 257 } 258 error()259 void error() 260 { 261 // We don't throw an error in this case 262 // Just set the error flag 263 mError = true; 264 } 265 266 bool accept(Token::TokenType s); 267 bool expect(Token::TokenType s); 268 int format(void); // This function returns the number of args for the next format 0,1,2 or 3 269 int directive(void); 270 void flags(void); 271 int width(void); 272 int precision(void); 273 void length_modifier(void); 274 int conversion(void); 275 }; 276 277 void DumpAllThreadOutput( FILE *streamout, unsigned char * dumpMem, size_t buffersize); 278 279 #endif