xref: /aosp_15_r20/external/intel-media-driver/media_driver/agnostic/common/cm/cm_printf_host.h (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
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