File indexing completed on 2024-04-28 09:36:46

0001 /*
0002     This file is part of KCachegrind.
0003 
0004     SPDX-FileCopyrightText: 2002-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only
0007 */
0008 
0009 #ifndef EVENTTYPE_H
0010 #define EVENTTYPE_H
0011 
0012 #include <QString>
0013 
0014 #include "subcost.h"
0015 #include "costitem.h"
0016 
0017 class EventTypeSet;
0018 
0019 /**
0020  * A cost type, e.g. "L1 Read Miss", short "l1rm".
0021  *
0022  * We distinguish "real" cost types, where the values come
0023  * from the trace file, and "virtual" cost types, which
0024  * are calculated from the real ones.
0025  *
0026  * For a virtual cost type, set a formula to calculate it:
0027  * e.g. for "Read Misses" : "l1rm + l2rm".
0028  * To allow for parsing, you must specify a EventTypeSet
0029  * with according cost types (e.g. "l1rm" and "l2rm" for above formula).
0030  *
0031  * The cost type with empty name is the "const" cost type.
0032  */
0033 class EventType
0034 {
0035 public:
0036 
0037     /**
0038      * @param name is a short (non-localized) identifier for the cost type,
0039      *   e.g. "l1rm".
0040      * @param longName is a long localized string, e.g. "L1 Read Miss"
0041      * @param formula uses short names to reference other types
0042      */
0043     explicit EventType(const QString& name,
0044                        const QString& longName = QString(),
0045                        const QString& formula = QString());
0046 
0047     void setName(const QString& n) { _name = n; }
0048     void setLongName(const QString& n) { _longName = n; }
0049     void setEventTypeSet(EventTypeSet* m);
0050     // enforces event to be derived, even with empty formula
0051     void setFormula(const QString&);
0052     // default arg is for specifying a real type, but index unknown
0053     void setRealIndex(int r = ProfileCostArray::MaxRealIndex);
0054 
0055     const QString& name() { return _name; }
0056     const QString& longName() { return _longName; }
0057     const QString& formula() { return _formula; }
0058     EventTypeSet* set() { return _set; }
0059     int realIndex() { return _realIndex; }
0060     bool isReal() { return _isReal; }
0061 
0062     /*
0063      * returns true if all cost type names can be resolved in formula
0064      */
0065     bool parseFormula();
0066     QString parsedFormula();
0067     QString parsedRealFormula();
0068 
0069     SubCost subCost(ProfileCostArray*);
0070 
0071     /*
0072      * For virtual costs, returns a histogram for use with
0073      * partitionPixmap().
0074      * Returns maximal real index.
0075      */
0076     int histCost(ProfileCostArray* c, double total, double* hist);
0077 
0078     // application wide known types, referenced by short name
0079     // next 2 functions return a new event type instance
0080     static EventType* cloneKnownRealType(const QString&);
0081     static EventType* cloneKnownDerivedType(const QString&);
0082     static bool hasKnownRealType(const QString&);
0083     static bool hasKnownDerivedType(const QString&);
0084     static void add(EventType*, bool overwriteExisting = true);
0085     static bool remove(const QString&);
0086     static int knownTypeCount();
0087     static EventType* knownType(int);
0088 
0089 private:
0090 
0091     QString _name, _longName, _formula, _parsedFormula;
0092     EventTypeSet* _set;
0093     bool _parsed, _inParsing, _isReal;
0094     // index MaxRealIndex is for constant addition
0095     int _coefficient[MaxRealIndexValue];
0096     int _realIndex;
0097 
0098     static QList<EventType*>* _knownTypes;
0099 };
0100 
0101 
0102 /**
0103  * A class for managing a set of event types.
0104  *
0105  * Each event type has an index:
0106  * - Real events are in range [0 .. ProfileCostArray:MaxRealIndex[
0107  * - Derived events are in range [MaxRealIndex, ...]
0108  */
0109 class EventTypeSet
0110 {
0111 public:
0112     EventTypeSet();
0113     ~EventTypeSet();
0114 
0115     /**
0116      * Defines a mapping from indexes into a list of costs to real event types
0117      * @param types the types
0118      */
0119     EventTypeMapping* createMapping(const QString& types);
0120 
0121     // "knows" about some real types
0122     int addReal(const QString&);
0123     int add(EventType*);
0124     bool remove(EventType*);
0125     int realCount() { return _realCount; }
0126     int derivedCount() { return _derivedCount; }
0127     int minDerivedIndex() { return ProfileCostArray::MaxRealIndex; }
0128     EventType* type(int);
0129     EventType* realType(int);
0130     EventType* derivedType(int);
0131     EventType* type(const QString&);
0132     EventType* typeForLong(const QString&);
0133     int realIndex(const QString&);
0134     int index(const QString&);
0135 
0136     /**
0137      * Adds all known derived event types that can be parsed
0138      */
0139     int addKnownDerivedTypes();
0140 
0141 private:
0142     // we support only a fixed number of real and derived types
0143     EventType* _real[MaxRealIndexValue];
0144     EventType* _derived[MaxRealIndexValue];
0145     int _realCount, _derivedCount;
0146 };
0147 
0148 /**
0149  * A index list into a EventTypeSet
0150  *
0151  * This ordered list maps from indexes into real cost types
0152  * of a set.
0153  *
0154  * You can define a set of event types by requesting submaps by name.
0155  * Every new event type name will get a new real type index.
0156  *  EventTypeSet s;
0157  *  m1 = s.createMapping("Event1 Cost1 Cost2");  // returns mapping [0,1,2]
0158  *  m2 = s.createMapping("Event2 Cost3 Event1"); // returns mapping [3,4,0]
0159  * Real types of s will be:
0160  *  (0:Event1, 1:Cost1, 2:Cost2, 3:Event2, 4:Cost3)
0161  */
0162 class EventTypeMapping
0163 {
0164 public:
0165     explicit EventTypeMapping(EventTypeSet*);
0166 
0167     bool append(const QString&, bool create=true);
0168     bool append(int);
0169     void clear();
0170 
0171     EventTypeSet* set() { return _set; }
0172 
0173     /**
0174      * Get number of used indexes
0175      */
0176     int count() { return _count; }
0177 
0178     /**
0179      * Is this mapping the identity( i.e. realIndex(i)=i ) ?
0180      * This often allows for optimizations.
0181      */
0182     bool isIdentity() { return _isIdentity; }
0183     int realIndex(int i)
0184     { return (i<0 || i>=_count) ? ProfileCostArray::InvalidIndex : _realIndex[i]; }
0185 
0186     /**
0187      * Get maximal real index for the first @p count mapping indexes.
0188      * @param count the count
0189      */
0190     int maxRealIndex(int count);
0191 
0192     /**
0193      * Allows an iteration over the sorted list of all real indexes not used in
0194      * this mapping, up to topIndex (use ProfileCostArray::MaxRealIndex for all).
0195      * Usage: for(i = firstUnused(); i < topIndex; i = nextUnused(i)) { LOOP }
0196      */
0197     int firstUnused() { return _firstUnused; }
0198     int nextUnused(int i) {
0199         if (i<0 || i>=ProfileCostArray::MaxRealIndex) return ProfileCostArray::InvalidIndex;
0200         return _nextUnused[i]; }
0201 
0202 private:
0203     EventTypeSet* _set;
0204     int _count, _firstUnused;
0205     bool _isIdentity;
0206     int _realIndex[MaxRealIndexValue];
0207     int _nextUnused[MaxRealIndexValue];
0208 };
0209 
0210 
0211 #endif // EVENTTYPE_H