1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #ifndef _OPTION_H_
10 #define _OPTION_H_
11 
12 #include <iostream>
13 #include <iomanip>
14 #include "visa_igc_common_header.h"
15 #include "VISAOptions.h"
16 #include "common.h"
17 #include <vector>
18 #include <unordered_map>
19 #include <algorithm>
20 
21 #define MAX_OPTION_STR_LENGTH 256
22 #define MAX_LABEL_STR_LENGTH 256
23 
24 enum Stepping {
25     Step_A = 0,
26     Step_B = 1,
27     Step_C = 2,
28     Step_D = 3,
29     Step_E = 4,
30     Step_F = 5,
31     Step_none = 6
32 };
33 
34 enum EntryType {
35     ET_UNINIT = 0,
36     ET_BOOL,
37     ET_INT32,
38     ET_2xINT32,
39     ET_INT64,
40     ET_CSTR,
41     ET_MAX
42 };
43 
44 union EntryValue {
45     bool boolean;
46     uint32_t int32;
47     uint64_t int64;
48     const char *cstr;
49 };
50 
51 struct VISAOptionsEntry {
52     EntryType type = ET_UNINIT;
53     EntryValue val;
getTypeVISAOptionsEntry54     EntryType getType(void) const { return type; }
dumpVISAOptionsEntry55     virtual void dump(void) const { std::cerr << "BASE"; }
~VISAOptionsEntryVISAOptionsEntry56     virtual ~VISAOptionsEntry() {}
57 };
58 
59 struct VISAOptionsEntryBool : VISAOptionsEntry {
VISAOptionsEntryBoolVISAOptionsEntryBool60     VISAOptionsEntryBool(bool Val) {
61         val.boolean = Val;
62         type = ET_BOOL;
63     }
dumpVISAOptionsEntryBool64     virtual void dump(void) const override {
65         std::cerr << std::left << std::setw(10)
66                   << ((val.boolean) ? "true" : "false");
67     }
getValVISAOptionsEntryBool68     bool getVal(void) const { return val.boolean; }
69 };
70 struct VISAOptionsEntryUint32 : VISAOptionsEntry {
VISAOptionsEntryUint32VISAOptionsEntryUint3271     VISAOptionsEntryUint32(uint32_t Val) {
72         val.int32 = Val;
73         type = ET_INT32;
74     }
dumpVISAOptionsEntryUint3275     virtual void dump(void) const override {
76         std::cerr << std::left << std::setw(10) << val.int32;
77     }
getValVISAOptionsEntryUint3278     uint32_t getVal(void) const { return val.int32; }
79 };
80 struct VISAOptionsEntryUint64 : VISAOptionsEntry {
VISAOptionsEntryUint64VISAOptionsEntryUint6481     VISAOptionsEntryUint64(uint64_t Val) {
82         val.int64 = Val;
83         type = ET_INT64;
84     }
dumpVISAOptionsEntryUint6485     virtual void dump(void) const override {
86         std::cerr << std::left << std::setw(10) << val.int64;
87     }
getValVISAOptionsEntryUint6488     uint64_t getVal(void) const { return val.int64; }
89 };
90 struct VISAOptionsEntryCstr : VISAOptionsEntry {
VISAOptionsEntryCstrVISAOptionsEntryCstr91     VISAOptionsEntryCstr(const char *Val) {
92         val.cstr = Val;
93         type = ET_CSTR;
94     }
dumpVISAOptionsEntryCstr95     virtual void dump(void) const override {
96         if (val.cstr) {
97             std::cerr << std::left << std::setw(10) << val.cstr;
98         } else {
99             std::cerr << std::left << std::setw(10) << "NULL";
100         }
101     }
getValVISAOptionsEntryCstr102     const char *getVal(void) const { return val.cstr; }
103 };
104 
105 
106 class Options {
107     std::unordered_map<std::string, vISAOptions> argToOption;
108     const char *vISAOptionsToStr[vISA_NUM_OPTIONS];
109     void initializeArgToOption(void);
110     void initialize_vISAOptionsToStr(void);
111     void initialize_m_vISAOptions(void);
112 
113 public:
114     Options();
115 
get_vISAOptionsToStr(vISAOptions opt)116     const char *get_vISAOptionsToStr(vISAOptions opt) {
117         return vISAOptionsToStr[opt];
118     }
119     bool parseOptions(int argc, const char *argv[]);
120     // This is to check whether an option of any type is set.
121     // It is useful for Cstr or Int arguments because getOption() will give us
122     // the value, not whether they are set or not.
123     bool isOptionSetByUser(vISAOptions option) const;
124 
125     void getOption(vISAOptions option, bool &value) const;
126     bool getOption(vISAOptions option) const;
127     void getOption(vISAOptions option, const char*& buf) const;
128     const char *getOptionCstr(vISAOptions option) const;
129     uint32_t getuInt32Option(vISAOptions option) const;
130     uint64_t getuInt64Option(vISAOptions option) const;
131 
setTarget(VISATarget tTarget)132     void setTarget(VISATarget tTarget) { target = tTarget;}
getTarget()133     VISATarget getTarget() const { return target; }
134 
135     // APIs used by vISA clients (explicitly setting options)
136     void setOption(vISAOptions option, bool val);
137     void setOption(vISAOptions option, uint32_t val);
138     void setOption(vISAOptions options, const char* str);
139 
140     // APIs used by vISA itself to set options internally
141     void setOptionInternally(vISAOptions option, bool val);
142     void setOptionInternally(vISAOptions option, uint32_t val);
143     void setOptionInternally(vISAOptions options, const char* str);
144 
145     static void showUsage(std::ostream& output);
146 
147     std::stringstream& getUserArgString();
148     std::string getFullArgString() const;
149     std::string getEncoderOutputFile() const;
150 
GetStepping()151     Stepping GetStepping() const { return stepping; }
152 
153     void getOptionsFromEV();
154 
155     void dump() const;
156 
157 private:
158     void setGTPin();
159 
160     // This holds the data of a single vISAOptions entry
161     struct VISAOptionsLine {
162         // This is the "-fooBarOption"
163         const char *argStr;
164         // The TYPE
165         EntryType type;
166         // This holds the actual value
167         VISAOptionsEntry *value;
168         // This holds the default value
169         VISAOptionsEntry *defaultValue;
170         // The error message to show when argument is badly formed
171         const char *errorMsg;
172         // This is set to TRUE if this option is passed as an argument
173         bool argIsSet;
174 
VISAOptionsLineVISAOptionsLine175         VISAOptionsLine(void) {
176             argStr = (const char *) nullptr;
177             type = ET_UNINIT;
178             value = nullptr;
179             defaultValue = nullptr;
180             errorMsg = nullptr;
181             argIsSet = false;
182         }
183         // Debug print
dumpVISAOptionsLine184         void dump(void) const {
185             std::cerr << std::setw(30) << argStr
186                       << " [" << argIsSet << "] ";
187             if (value) {
188                 value->dump();
189             } else {
190                 std::cerr << std::left << std::setw(10) << "NULL";
191             }
192             std::cerr << ", (default:";
193             if (defaultValue) {
194                 defaultValue->dump();
195             } else {
196                 std::cerr << std::left << std::setw(10) << "NULL";
197             }
198             std::cerr << ")";
199         }
200     };
201 
202     // gcc 4.9.3 does not support enum as unordered_map key without an explicit hash function
203     struct vISAOptionsHash
204     {
operatorvISAOptionsHash205         size_t operator()(vISAOptions opt) const
206         {
207             return (size_t)opt;
208         }
209     };
210 
211     // The main structure where we hold the options, their "-argument string",
212     // their assigned values, their default values etc.
213     // It is a map from vISAOptions->VISAOptionsLine
214     class VISAOptionsDB {
215     private:
216         Options *options = nullptr;
217         std::unordered_map<vISAOptions, VISAOptionsLine, vISAOptionsHash> optionsMap;
218         // Check if KEY has already a value assigned to it
219         void freeIfAlreadySet(vISAOptions key, bool dontCheckNull = true) {
220             // If already set, free tha last one
221             auto it = optionsMap.find(key);
222             if (it != optionsMap.end()) {
223                 if (dontCheckNull || it->second.value != nullptr) {
224                     delete it->second.value;
225                 }
226             }
227         }
228     public:
229         // Debug print all the options
dump(void)230         void dump(void) const {
231             for (auto pair : optionsMap) {
232                 const VISAOptionsLine &line = pair.second;
233                 std::cerr << std::left << std::setw(34)
234                           << options->get_vISAOptionsToStr(pair.first)
235                           << ": ";
236                 line.dump();
237                 std::cerr << std::endl;
238             }
239         }
240         // Debug print a single entry
dump(vISAOptions key)241         void dump(vISAOptions key) const {
242             optionsMap.at(key).dump();
243         }
244         // If the option is passed as a command line argument
setArgSetByUser(vISAOptions key)245         void setArgSetByUser(vISAOptions key) {
246             optionsMap[key].argIsSet = true;
247         }
248         // Set the value of the option
setBool(vISAOptions key,bool val)249         void setBool(vISAOptions key, bool val) {
250             freeIfAlreadySet(key);
251             optionsMap[key].value = new VISAOptionsEntryBool(val);
252         }
setUint32(vISAOptions key,uint32_t val)253         void setUint32(vISAOptions key, uint32_t val) {
254             freeIfAlreadySet(key);
255             optionsMap[key].value = new VISAOptionsEntryUint32(val);
256         }
setUint64(vISAOptions key,uint64_t val)257         void setUint64(vISAOptions key, uint64_t val) {
258             freeIfAlreadySet(key);
259             optionsMap[key].value = new VISAOptionsEntryUint64(val);
260         }
setCstr(vISAOptions key,const char * val)261         void setCstr(vISAOptions key, const char *val) {
262             freeIfAlreadySet(key, false);
263             if (! val) {
264                 optionsMap[key].value = nullptr;
265             } else {
266                 MUST_BE_TRUE(strlen(val) < MAX_OPTION_STR_LENGTH, ERROR_OPTION);
267                 // size_t strLen = std::min(strlen(val) + 1,
268                 //                          (size_t)MAX_OPTION_STR_LENGTH);
269                 // // Not sure why new space is allocated.
270                 // // It is never freed.
271                 // char *newBuf = (char *) malloc(strLen);
272                 // strncpy_s(newBuf, strLen, val, strLen);
273                 optionsMap[key].value = new VISAOptionsEntryCstr(val);
274             }
275         }
276 
277         // Set the value of the option
setDefaultBool(vISAOptions key,bool val)278         void setDefaultBool(vISAOptions key, bool val) {
279             optionsMap[key].defaultValue = new VISAOptionsEntryBool(val);
280         }
setDefaultUint32(vISAOptions key,uint32_t val)281         void setDefaultUint32(vISAOptions key, uint32_t val) {
282             optionsMap[key].defaultValue = new VISAOptionsEntryUint32(val);
283         }
setDefaultUint64(vISAOptions key,uint64_t val)284         void setDefaultUint64(vISAOptions key, uint64_t val) {
285             optionsMap[key].defaultValue = new VISAOptionsEntryUint64(val);
286         }
setDefaultCstr(vISAOptions key,const char * val)287         void setDefaultCstr(vISAOptions key, const char *val) {
288             optionsMap[key].defaultValue = new VISAOptionsEntryCstr(val);
289         }
290 
291         // Set the "-fooBarOption"
setArgStr(vISAOptions key,const char * argStr)292         void setArgStr(vISAOptions key, const char *argStr) {
293             optionsMap[key].argStr = argStr;
294         }
295 
296         // Set the TYPE
setType(vISAOptions key,EntryType type)297         void setType(vISAOptions key, EntryType type) {
298             optionsMap[key].type = type;
299         }
300 
301         // Set the error message
setErrorMsg(vISAOptions key,const char * errorMsg)302         void setErrorMsg(vISAOptions key, const char *errorMsg) {
303             optionsMap[key].errorMsg = errorMsg;
304         }
305 
306         // Get the argument string "-fooArg"
getArgStr(vISAOptions key)307         const char *getArgStr(vISAOptions key) const {
308             auto it = optionsMap.find(key);
309             if (it != optionsMap.end()) {
310                 const char *argStr = it->second.argStr;
311                 return argStr;
312             } else {
313                 return "UNDEFINED";
314             }
315         }
316 
317         // Get the type of KEY
getType(vISAOptions key)318         EntryType getType(vISAOptions key) const {
319             assert(optionsMap.count(key));
320             return optionsMap.at(key).type;
321         }
322 
323         // Get the type of KEY
getErrorMsg(vISAOptions key)324         const char *getErrorMsg(vISAOptions key) const {
325             assert(optionsMap.count(key));
326             return optionsMap.at(key).errorMsg;
327         }
328 
329 
330         // Get the values
getBool(vISAOptions key)331         bool getBool(vISAOptions key) const {
332             assert(optionsMap.count(key));
333             const VISAOptionsEntry *value = optionsMap.at(key).value;
334             assert(value->getType() == ET_BOOL && "Bad Type");
335             const VISAOptionsEntryBool *Bool
336                 = static_cast<const VISAOptionsEntryBool *>(value);
337             assert(Bool && "Uninitialized?");
338             return Bool->getVal();
339         }
getUint32(vISAOptions key)340         uint32_t getUint32(vISAOptions key) const {
341             assert(optionsMap.count(key));
342             const VISAOptionsEntry *value = optionsMap.at(key).value;
343             assert(value->getType() == ET_INT32 && "Bad Type");
344             const VISAOptionsEntryUint32 *Int32
345                 = static_cast<const VISAOptionsEntryUint32 *>(value);
346             assert(Int32 && "Uninitialized?");
347             return Int32->getVal();
348         }
getUint64(vISAOptions key)349         uint64_t getUint64(vISAOptions key) const {
350             assert(optionsMap.count(key));
351             const VISAOptionsEntry *value = optionsMap.at(key).value;
352             assert(value->getType() == ET_INT64 && "Bad Type");
353             const VISAOptionsEntryUint64 *Int64
354                 = static_cast<const VISAOptionsEntryUint64 *>(value);
355             assert(Int64 && "Uninitialized?");
356             return Int64->getVal();
357         }
getCstr(vISAOptions key)358         const char *getCstr(vISAOptions key) const {
359             assert(optionsMap.count(key));
360             const VISAOptionsEntry *value = optionsMap.at(key).value;
361             if (! value) {
362                 return nullptr;
363             }
364             assert(value->getType() == ET_CSTR && "Bad Type");
365             const VISAOptionsEntryCstr *Cstr
366                 = static_cast<const VISAOptionsEntryCstr *>(value);
367             // assert(Cstr && "Bad option type OR uninit");
368             return Cstr->getVal();
369         }
370 
371         // TRUE if the options is passed as a cmd line argument
isArgSetByUser(vISAOptions key)372         bool isArgSetByUser(vISAOptions key) const {
373             return optionsMap.at(key).argIsSet;
374         }
375         // Get defaults
getDefaultBool(vISAOptions key)376         bool getDefaultBool(vISAOptions key) const {
377             assert(optionsMap.count(key));
378             const VISAOptionsEntry *defValue = optionsMap.at(key).defaultValue;
379             assert(defValue->getType() == ET_BOOL && "Bad Type");
380             const VISAOptionsEntryBool *Bool
381                 = static_cast<const VISAOptionsEntryBool *>(defValue);
382             assert(Bool && "Uninitialized?");
383             return Bool->getVal();
384         }
getDefaultUint32(vISAOptions key)385         uint32_t getDefaultUint32(vISAOptions key) const {
386             assert(optionsMap.count(key));
387             const VISAOptionsEntry *defValue = optionsMap.at(key).defaultValue;
388             assert(defValue->getType() == ET_INT32 && "Bad Type");
389             const VISAOptionsEntryUint32 *Int32
390                 = static_cast<const VISAOptionsEntryUint32 *>(defValue);
391             assert(Int32 && "Uninitialized?");
392             return Int32->getVal();
393         }
getDefaultUint64(vISAOptions key)394         uint64_t getDefaultUint64(vISAOptions key) const {
395             assert(optionsMap.count(key));
396             const VISAOptionsEntry *defValue = optionsMap.at(key).defaultValue;
397             assert(defValue->getType() == ET_INT64 && "Bad Type");
398             const VISAOptionsEntryUint64 *Int64
399                 = static_cast<const VISAOptionsEntryUint64 *>(defValue);
400             assert(Int64 && "Uninitialized?");
401             return Int64->getVal();
402         }
getDefaultCstr(vISAOptions key)403         const char *getDefaultCstr(vISAOptions key) const {
404             assert(optionsMap.count(key));
405             const VISAOptionsEntry *defValue = optionsMap.at(key).defaultValue;
406             assert(defValue->getType() == ET_CSTR && "Bad Type");
407             const VISAOptionsEntryCstr *Cstr
408                 = static_cast<const VISAOptionsEntryCstr *>(defValue);
409             assert(Cstr && "Uninitialized?");
410             return Cstr->getVal();
411         }
VISAOptionsDB()412         VISAOptionsDB() {}
VISAOptionsDB(Options * opt)413         VISAOptionsDB(Options *opt) {
414             options = opt;
415         }
416 
~VISAOptionsDB(void)417         ~VISAOptionsDB(void) {
418             for (auto pair : optionsMap) {
419                 auto *val = pair.second.value;
420                 delete val;
421                 auto *defVal = pair.second.defaultValue;
422                 delete defVal;
423 
424             }
425         }
426     };
427 
428     VISAOptionsDB m_vISAOptions;
429 
430     VISATarget target;
431 
432     // for debugging, store the options passed to command line/vISA builder
433     std::stringstream argString;
434 
435     // legacy stepping setting for offline vISA compile.
436     // FE compilers should not use this and should instead program the appropriate WATable/vISA option flags instead.
437     Stepping stepping = Stepping::Step_none;
438 
SetStepping(const char * str)439     int SetStepping(const char* str) {
440 
441         int retVal = VISA_SUCCESS;
442         char upperchar = (char)std::toupper(*str);
443 
444         switch (upperchar)
445         {
446         case 'A':
447             stepping = Step_A;
448             break;
449         case 'B':
450             stepping = Step_B;
451             break;
452         case 'C':
453             stepping = Step_C;
454             break;
455         case 'D':
456             stepping = Step_D;
457             break;
458         case 'E':
459             stepping = Step_E;
460             break;
461         case 'F':
462             stepping = Step_F;
463             break;
464         default:
465             // err msg?
466             break;
467         }
468         return retVal;
469     }
470 
471 };
472 
473 #endif
474