File indexing completed on 2024-05-05 05:44:23

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 /*
0010  * Global configuration for KCachegrind
0011  */
0012 
0013 #include "globalconfig.h"
0014 
0015 #include <QtDebug>
0016 
0017 #include "config.h"
0018 #include "tracedata.h"
0019 
0020 
0021 // GlobalConfig defaults
0022 #define DEFAULT_SHOWPERCENTAGE   true
0023 #define DEFAULT_SHOWEXPANDED     false
0024 #define DEFAULT_SHOWCYCLES       true
0025 #define DEFAULT_HIDETEMPLATES    false
0026 #define DEFAULT_CYCLECUT         0.0
0027 #define DEFAULT_PERCENTPRECISION 2
0028 #define DEFAULT_MAXSYMBOLLENGTH  30
0029 #define DEFAULT_MAXSYMBOLCOUNT   10
0030 #define DEFAULT_MAXLISTCOUNT     100
0031 #define DEFAULT_CONTEXT          3
0032 #define DEFAULT_NOCOSTINSIDE     20
0033 
0034 
0035 //
0036 // GlobalConfig
0037 //
0038 
0039 // Some predefined event types...
0040 QStringList GlobalConfig::knownTypes()
0041 {
0042     QStringList l;
0043 
0044     l << QStringLiteral("Ir")   << QStringLiteral("Dr")   << QStringLiteral("Dw")
0045       << QStringLiteral("I1mr") << QStringLiteral("D1mr") << QStringLiteral("D1mw") << QStringLiteral("L1m");
0046     // Valgrind < 3.6.0
0047     l << QStringLiteral("I2mr") << QStringLiteral("D2mr") << QStringLiteral("D2mw") << QStringLiteral("L2m");
0048     // Valgrind 3.6.0: L2 events changed to LL (last level) events
0049     l << QStringLiteral("ILmr") << QStringLiteral("DLmr") << QStringLiteral("DLmw") << QStringLiteral("LLm");
0050 
0051     // branch simulation
0052     l << QStringLiteral("Bi") << QStringLiteral("Bim") << QStringLiteral("Bc") << QStringLiteral("Bcm") << QStringLiteral("Bm");
0053 
0054     // global bus events (e.g. CAS)
0055     l << QStringLiteral("Ge");
0056 
0057     l << QStringLiteral("Smp")  << QStringLiteral("Sys")  << QStringLiteral("User") << QStringLiteral("CEst");
0058 
0059     return l;
0060 }
0061 
0062 
0063 QString GlobalConfig::knownFormula(const QString& name)
0064 {
0065     if (name == QLatin1String("L1m")) return QStringLiteral("I1mr + D1mr + D1mw");
0066     if (name == QLatin1String("L2m")) return QStringLiteral("I2mr + D2mr + D2mw");
0067     if (name == QLatin1String("LLm")) return QStringLiteral("ILmr + DLmr + DLmw");
0068     if (name == QLatin1String("Bm"))  return QStringLiteral("Bim + Bcm");
0069     if (name == QLatin1String("CEst"))
0070         return QStringLiteral("Ir + 10 Bm + 10 L1m + 20 Ge + 100 L2m + 100 LLm");
0071 
0072     return QString();
0073 }
0074 
0075 QString GlobalConfig::knownLongName(const QString& name)
0076 {
0077     if (name == QLatin1String("Ir")) return QObject::tr("Instruction Fetch");
0078     if (name == QLatin1String("Dr")) return QObject::tr("Data Read Access");
0079     if (name == QLatin1String("Dw")) return QObject::tr("Data Write Access");
0080     if (name == QLatin1String("I1mr")) return QObject::tr("L1 Instr. Fetch Miss");
0081     if (name == QLatin1String("D1mr")) return QObject::tr("L1 Data Read Miss");
0082     if (name == QLatin1String("D1mw")) return QObject::tr("L1 Data Write Miss");
0083     if (name == QLatin1String("I2mr")) return QObject::tr("L2 Instr. Fetch Miss");
0084     if (name == QLatin1String("D2mr")) return QObject::tr("L2 Data Read Miss");
0085     if (name == QLatin1String("D2mw")) return QObject::tr("L2 Data Write Miss");
0086     if (name == QLatin1String("ILmr")) return QObject::tr("LL Instr. Fetch Miss");
0087     if (name == QLatin1String("DLmr")) return QObject::tr("LL Data Read Miss");
0088     if (name == QLatin1String("DLmw")) return QObject::tr("LL Data Write Miss");
0089     if (name == QLatin1String("L1m")) return QObject::tr("L1 Miss Sum");
0090     if (name == QLatin1String("L2m")) return QObject::tr("L2 Miss Sum");
0091     if (name == QLatin1String("LLm")) return QObject::tr("Last-level Miss Sum");
0092     if (name == QLatin1String("Bi"))  return QObject::tr("Indirect Branch");
0093     if (name == QLatin1String("Bim")) return QObject::tr("Mispredicted Ind. Branch");
0094     if (name == QLatin1String("Bc"))  return QObject::tr("Conditional Branch");
0095     if (name == QLatin1String("Bcm")) return QObject::tr("Mispredicted Cond. Branch");
0096     if (name == QLatin1String("Bm"))  return QObject::tr("Mispredicted Branch");
0097     if (name == QLatin1String("Ge"))  return QObject::tr("Global Bus Event");
0098     if (name == QLatin1String("Smp")) return QObject::tr("Samples");
0099     if (name == QLatin1String("Sys")) return QObject::tr("System Time");
0100     if (name == QLatin1String("User")) return QObject::tr("User Time");
0101     if (name == QLatin1String("CEst")) return QObject::tr("Cycle Estimation");
0102 
0103     return QString();
0104 }
0105 
0106 
0107 GlobalConfig* GlobalConfig::_config = nullptr;
0108 
0109 GlobalConfig::GlobalConfig()
0110 {
0111     _config = nullptr;
0112 
0113     // general presentation options
0114     _showPercentage   = DEFAULT_SHOWPERCENTAGE;
0115     _showExpanded     = DEFAULT_SHOWEXPANDED;
0116     _showCycles       = DEFAULT_SHOWCYCLES;
0117     _cycleCut         = DEFAULT_CYCLECUT;
0118     _percentPrecision = DEFAULT_PERCENTPRECISION;
0119     _hideTemplates    = DEFAULT_HIDETEMPLATES;
0120 
0121     // max symbol count/length in tooltip/popup
0122     _maxSymbolLength  = DEFAULT_MAXSYMBOLLENGTH;
0123     _maxSymbolCount   = DEFAULT_MAXSYMBOLCOUNT;
0124     _maxListCount     = DEFAULT_MAXLISTCOUNT;
0125 
0126     // annotation behaviour
0127     _context          = DEFAULT_CONTEXT;
0128     _noCostInside     = DEFAULT_NOCOSTINSIDE;
0129 }
0130 
0131 GlobalConfig::~GlobalConfig()
0132 {
0133 }
0134 
0135 GlobalConfig* GlobalConfig::config()
0136 {
0137     if (_config == nullptr)
0138         _config = new GlobalConfig();
0139 
0140     return _config;
0141 }
0142 
0143 
0144 void GlobalConfig::saveOptions()
0145 {
0146     // source options
0147     ConfigGroup* sourceConfig = ConfigStorage::group(QStringLiteral("Source"));
0148     sourceConfig->setValue(QStringLiteral("Dirs"), _generalSourceDirs);
0149     QHashIterator<QString,QStringList> it( _objectSourceDirs );
0150     int count = 1;
0151     while( it.hasNext() ) {
0152         it.next();
0153         sourceConfig->setValue( QStringLiteral("Object%1").arg(count),
0154                                 it.key() );
0155         sourceConfig->setValue( QStringLiteral("Dirs%1").arg(count),
0156                                 it.value() );
0157         count++;
0158     }
0159     sourceConfig->setValue(QStringLiteral("Count"), count-1);
0160     delete sourceConfig;
0161 
0162     // general options
0163     ConfigGroup* generalConfig = ConfigStorage::group(QStringLiteral("GeneralSettings"));
0164     generalConfig->setValue(QStringLiteral("ShowPercentage"), _showPercentage,
0165                             DEFAULT_SHOWPERCENTAGE);
0166     generalConfig->setValue(QStringLiteral("ShowExpanded"), _showExpanded,
0167                             DEFAULT_SHOWEXPANDED);
0168     generalConfig->setValue(QStringLiteral("ShowCycles"), _showCycles,
0169                             DEFAULT_SHOWCYCLES);
0170     generalConfig->setValue(QStringLiteral("CycleCut"), _cycleCut,
0171                             DEFAULT_CYCLECUT);
0172     generalConfig->setValue(QStringLiteral("PercentPrecision"), _percentPrecision,
0173                             DEFAULT_PERCENTPRECISION);
0174     generalConfig->setValue(QStringLiteral("MaxSymbolLength"), _maxSymbolLength,
0175                             DEFAULT_MAXSYMBOLLENGTH);
0176     generalConfig->setValue(QStringLiteral("MaxSymbolCount"), _maxSymbolCount,
0177                             DEFAULT_MAXSYMBOLCOUNT);
0178     generalConfig->setValue(QStringLiteral("MaxListCount"), _maxListCount,
0179                             DEFAULT_MAXLISTCOUNT);
0180     generalConfig->setValue(QStringLiteral("Context"), _context,
0181                             DEFAULT_CONTEXT);
0182     generalConfig->setValue(QStringLiteral("NoCostInside"), _noCostInside,
0183                             DEFAULT_NOCOSTINSIDE);
0184     generalConfig->setValue(QStringLiteral("HideTemplates"), _hideTemplates,
0185                             DEFAULT_HIDETEMPLATES);
0186     delete generalConfig;
0187 
0188     // store known event types
0189     ConfigGroup* etConfig = ConfigStorage::group(QStringLiteral("EventTypes"));
0190     int etCount = EventType::knownTypeCount();
0191     int j = 0; // counter for config keys
0192     for (int i = 0; i<etCount; i++) {
0193         EventType* t = EventType::knownType(i);
0194         // do not store derived event types with empty formula
0195         // (these can exist when new type gets added with context menu)
0196         if (!t->isReal() && t->formula().isEmpty()) continue;
0197 
0198         etConfig->setValue( QStringLiteral("Name%1").arg(j+1), t->name());
0199         etConfig->setValue( QStringLiteral("Longname%1").arg(j+1),
0200                             t->longName(),
0201                             knownLongName(t->name()) );
0202         etConfig->setValue( QStringLiteral("Formula%1").arg(j+1),
0203                             t->formula(), knownFormula(t->name()) );
0204         j++;
0205     }
0206     etConfig->setValue( QStringLiteral("Count"), j);
0207     delete etConfig;
0208 }
0209 
0210 void GlobalConfig::readOptions()
0211 {
0212     int i, count;
0213 
0214     // source options
0215     ConfigGroup* sourceConfig = ConfigStorage::group(QStringLiteral("Source"));
0216     QStringList dirs;
0217     dirs = sourceConfig->value(QStringLiteral("Dirs"), QStringList()).toStringList();
0218     if (dirs.count()>0) _generalSourceDirs = dirs;
0219     count = sourceConfig->value(QStringLiteral("Count"), 0).toInt();
0220     _objectSourceDirs.clear();
0221     for(i=1; i<=count; ++i) {
0222         QString n = sourceConfig->value(QStringLiteral("Object%1").arg(i),
0223                                         QString()).toString();
0224         dirs = sourceConfig->value(QStringLiteral("Dirs%1").arg(i),
0225                                    QStringList()).toStringList();
0226 
0227         if (n.isEmpty() || (dirs.isEmpty())) continue;
0228 
0229         _objectSourceDirs.insert(n, dirs);
0230     }
0231     delete sourceConfig;
0232 
0233     // general options
0234     ConfigGroup* generalConfig = ConfigStorage::group(QStringLiteral("GeneralSettings"));
0235     _showPercentage   = generalConfig->value(QStringLiteral("ShowPercentage"),
0236                                              DEFAULT_SHOWPERCENTAGE).toBool();
0237     _showExpanded     = generalConfig->value(QStringLiteral("ShowExpanded"),
0238                                              DEFAULT_SHOWEXPANDED).toBool();
0239     _showCycles       = generalConfig->value(QStringLiteral("ShowCycles"),
0240                                              DEFAULT_SHOWCYCLES).toBool();
0241     _cycleCut         = generalConfig->value(QStringLiteral("CycleCut"),
0242                                              DEFAULT_CYCLECUT).toDouble();
0243     _percentPrecision = generalConfig->value(QStringLiteral("PercentPrecision"),
0244                                              DEFAULT_PERCENTPRECISION).toInt();
0245     _maxSymbolLength  = generalConfig->value(QStringLiteral("MaxSymbolLength"),
0246                                              DEFAULT_MAXSYMBOLLENGTH).toInt();
0247     _maxSymbolCount   = generalConfig->value(QStringLiteral("MaxSymbolCount"),
0248                                              DEFAULT_MAXSYMBOLCOUNT).toInt();
0249     _maxListCount     = generalConfig->value(QStringLiteral("MaxListCount"),
0250                                              DEFAULT_MAXLISTCOUNT).toInt();
0251     _context          = generalConfig->value(QStringLiteral("Context"),
0252                                              DEFAULT_CONTEXT).toInt();
0253     _noCostInside     = generalConfig->value(QStringLiteral("NoCostInside"),
0254                                              DEFAULT_NOCOSTINSIDE).toInt();
0255     _hideTemplates    = generalConfig->value(QStringLiteral("HideTemplates"),
0256                                              DEFAULT_HIDETEMPLATES).toBool();
0257     delete generalConfig;
0258 
0259     // event types
0260     if (EventType::knownTypeCount() >0) return; // already read
0261     ConfigGroup* etConfig = ConfigStorage::group(QStringLiteral("EventTypes"));
0262     int etCount = etConfig->value(QStringLiteral("Count"), 0).toInt();
0263 
0264     for (int i=1;i<=etCount;i++) {
0265         QString n = etConfig->value(QStringLiteral("Name%1").arg(i),
0266                                     QString()).toString();
0267         QString l = etConfig->value(QStringLiteral("Longname%1").arg(i),
0268                                     QString()).toString();
0269         if (l.isEmpty()) l = knownLongName(n);
0270         QString f = etConfig->value(QStringLiteral("Formula%1").arg(i),
0271                                     QString()).toString();
0272         if (f.isEmpty()) f = knownFormula(n);
0273 
0274         EventType::add(new EventType(n, l, f));
0275     }
0276 
0277     // this does only add yet non-existing types
0278     addDefaultTypes();
0279 
0280     delete etConfig;
0281 }
0282 
0283 void GlobalConfig::addDefaultTypes()
0284 {
0285     QString longName, formula;
0286     EventType* ct;
0287     QStringList l = knownTypes();
0288     for ( QStringList::const_iterator it = l.constBegin();
0289           it != l.constEnd(); ++it ) {
0290         longName = knownLongName(*it);
0291         formula  = knownFormula(*it);
0292         ct = new EventType(*it, longName, formula);
0293         EventType::add(ct, false);
0294     }
0295 }
0296 
0297 /* Gives back a list of all Source Base Directories of Objects in
0298  * current trace. If a special object is given in 2nd argument,
0299  * put its Source Base in front.
0300  */
0301 QStringList GlobalConfig::sourceDirs(TraceData* data, TraceObject* o)
0302 {
0303     QStringList l = config()->_generalSourceDirs, ol, ol2;
0304     TraceObjectMap::Iterator oit;
0305     for ( oit = data->objectMap().begin();
0306           oit != data->objectMap().end(); ++oit ) {
0307         ol = config()->_objectSourceDirs[(*oit).name()];
0308         if (&(*oit) == o) {
0309             ol2 = ol;
0310             continue;
0311         }
0312 
0313         for(int i=0;i<ol.count();i++)
0314             l.prepend( ol[i] );
0315     }
0316     for(int i=0;i<ol2.count();i++)
0317         l.prepend( ol2[i] );
0318 
0319     if (0) qDebug() << "GlobalConfig::sourceDirs: " << l.join(QLatin1Char(':'));
0320 
0321     return l;
0322 }
0323 
0324 bool GlobalConfig::showPercentage()
0325 {
0326     return config()->_showPercentage;
0327 }
0328 
0329 bool GlobalConfig::showExpanded()
0330 {
0331     return config()->_showExpanded;
0332 }
0333 
0334 bool GlobalConfig::showCycles()
0335 {
0336     return config()->_showCycles;
0337 }
0338 
0339 bool GlobalConfig::hideTemplates()
0340 {
0341     return config()->_hideTemplates;
0342 }
0343 
0344 void GlobalConfig::setShowPercentage(bool s)
0345 {
0346     GlobalConfig* c = config();
0347     if (c->_showPercentage == s) return;
0348 
0349     c->_showPercentage = s;
0350 }
0351 
0352 void GlobalConfig::setShowExpanded(bool s)
0353 {
0354     GlobalConfig* c = config();
0355     if (c->_showExpanded == s) return;
0356 
0357     c->_showExpanded = s;
0358 }
0359 
0360 void GlobalConfig::setShowCycles(bool s)
0361 {
0362     GlobalConfig* c = config();
0363     if (c->_showCycles == s) return;
0364 
0365     c->_showCycles = s;
0366 }
0367 
0368 void GlobalConfig::setHideTemplates(bool s)
0369 {
0370     GlobalConfig* c = config();
0371     if (c->_hideTemplates == s) return;
0372 
0373     c->_hideTemplates = s;
0374 }
0375 
0376 double GlobalConfig::cycleCut()
0377 {
0378     return config()->_cycleCut;
0379 }
0380 
0381 int GlobalConfig::percentPrecision()
0382 {
0383     return config()->_percentPrecision;
0384 }
0385 
0386 int GlobalConfig::maxSymbolLength()
0387 {
0388     return config()->_maxSymbolLength;
0389 }
0390 
0391 QString GlobalConfig::shortenSymbol(const QString& s)
0392 {
0393     if(s.length() > config()->_maxSymbolLength)
0394         return s.left(config()->_maxSymbolLength) + QStringLiteral("...");
0395     return s;
0396 }
0397 
0398 int GlobalConfig::maxListCount()
0399 {
0400     return config()->_maxListCount;
0401 }
0402 
0403 int GlobalConfig::maxSymbolCount()
0404 {
0405     return config()->_maxSymbolCount;
0406 }
0407 
0408 int GlobalConfig::context()
0409 {
0410     return config()->_context;
0411 }
0412 
0413 int GlobalConfig::noCostInside()
0414 {
0415     return config()->_noCostInside;
0416 }
0417 
0418 void GlobalConfig::setPercentPrecision(int v)
0419 {
0420     if ((v<1) || (v >5)) return;
0421     _percentPrecision = v;
0422 }
0423 
0424 void GlobalConfig::setMaxSymbolLength(int v)
0425 {
0426     if ((v<1) || (v >1000)) return;
0427     _maxSymbolLength = v;
0428 }
0429 
0430 void GlobalConfig::setMaxSymbolCount(int v)
0431 {
0432     if ((v<1) || (v >50)) return;
0433     _maxSymbolCount = v;
0434 }
0435 
0436 void GlobalConfig::setMaxListCount(int v)
0437 {
0438     if ((v<1) || (v >500)) return;
0439     _maxListCount = v;
0440 }
0441 
0442 void GlobalConfig::setContext(int v)
0443 {
0444     if ((v<1) || (v >500)) return;
0445     _context = v;
0446 }
0447 
0448 const QStringList& GlobalConfig::generalSourceDirs()
0449 {
0450     return _generalSourceDirs;
0451 }
0452 
0453 QStringList GlobalConfig::objectSourceDirs(QString obj)
0454 {
0455     if (_objectSourceDirs.contains(obj))
0456         return _objectSourceDirs[obj];
0457     else
0458         return QStringList();
0459 }
0460 
0461 void GlobalConfig::setGeneralSourceDirs(QStringList dirs)
0462 {
0463     _generalSourceDirs = dirs;
0464 }
0465 
0466 void GlobalConfig::setObjectSourceDirs(QString obj, QStringList dirs)
0467 {
0468     if (dirs.isEmpty())
0469         _objectSourceDirs.remove(obj);
0470     else
0471         _objectSourceDirs.insert(obj, dirs);
0472 }
0473 
0474 void GlobalConfig::clearObjectSourceDirs()
0475 {
0476     _objectSourceDirs.clear();
0477 }