Initial commit.

 - qa-tools public release which includes:
    - trace-based coverage tool
    - quality metrics measurement and tracking setup
    - associated in-source documentation.

Signed-off-by: Basil Eljuse <basil.eljuse@arm.com>
diff --git a/coverage-tool/coverage-plugin/Makefile b/coverage-tool/coverage-plugin/Makefile
new file mode 100644
index 0000000..3a2a18f
--- /dev/null
+++ b/coverage-tool/coverage-plugin/Makefile
@@ -0,0 +1,30 @@
+##############################################################################
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+##############################################################################
+
+CPPFLAGS = -I${PVLIB_HOME}/include/fmruntime
+CXXFLAGS = -fpic -Wall -Werror -g
+LDFLAGS  =
+CMAKE_CXX_FLAGS = -std=c++11 -O3
+
+ifeq (${CROSS_COMPILE_32BIT},1)
+CXXFLAGS += -m32
+LDFLAGS  += -m32
+endif
+
+PLUGIN_NAME = coverage_trace
+
+PLUGIN_LIB     = ${PLUGIN_NAME}.so
+PLUGIN_OBJECTS = ${PLUGIN_NAME}.o plugin_utils.o
+
+${PLUGIN_LIB}: ${PLUGIN_OBJECTS}
+	${CXX} -shared -o $@ ${LDFLAGS} $^
+
+.cc.o:
+	${CXX} -c -o $@ ${CXXFLAGS} ${CMAKE_CXX_FLAGS} ${CPPFLAGS} $^
+
+.PHONY: clean
+clean:
+	rm -f ${PLUGIN_OBJECTS} ${PLUGIN_LIB}
diff --git a/coverage-tool/coverage-plugin/coverage_trace.cc b/coverage-tool/coverage-plugin/coverage_trace.cc
new file mode 100644
index 0000000..4dc72ee
--- /dev/null
+++ b/coverage-tool/coverage-plugin/coverage_trace.cc
@@ -0,0 +1,349 @@
+/*!
+##############################################################################
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+##############################################################################
+*/
+// Implements the trace plugin interface for the MTI interface to trace
+// source data from Arm FVP.
+
+#include "MTI/PluginInterface.h"
+#include "MTI/PluginFactory.h"
+#include "MTI/PluginInstance.h"
+#include "MTI/ModelTraceInterface.h"
+
+#include "plugin_utils.h"
+#include "trace_sources.h"
+
+#include <errno.h>
+#include <string>
+#include <algorithm>
+#include <cstdio>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <typeinfo>
+#include <typeindex>
+#include <utility>
+
+#ifdef SG_MODEL_BUILD
+    #include "builddata.h"
+    #define PLUGIN_VERSION FULL_VERSION_STRING
+#else
+    #define PLUGIN_VERSION "unreleased"
+#endif
+
+using namespace eslapi;
+using namespace MTI;
+using namespace std;
+
+// Implements the plugin interface for trace coverage
+class CoverageTrace :public PluginInstance
+{
+public:
+    virtual CAInterface * ObtainInterface(if_name_t    ifName,
+                                          if_rev_t     minRev,
+                                          if_rev_t *   actualRev);
+
+    CoverageTrace(const char *instance_name, const char *trace_file_prefix);
+    ~CoverageTrace();
+
+    /** This is to associate a plugin with a simulation instance. Exactly one
+     * simulation must be registered.
+     * */
+    virtual eslapi::CADIReturn_t RegisterSimulation(eslapi::CAInterface
+                                                    *simulation);
+
+    // This is called before the plugin .dll/.so is unloaded and should allow
+    // the plugin to do it's cleanup.
+    virtual void Release();
+
+    virtual const char *GetName() const;
+
+private:
+    std::string instance_name;
+
+    bool Error(const char *);
+
+    vector<TraceComponentContext*> trace_components;
+    std::string trace_file_prefix;
+};
+
+CAInterface *CoverageTrace::ObtainInterface(if_name_t ifName,
+                            if_rev_t     minRev,
+                            if_rev_t *   actualRev)
+{
+  printf("CoverageTrace::ObtainInterface\n");
+    // If someone is asking for the matching interface
+    if((strcmp(ifName,IFNAME()) == 0) &&
+    // and the revision of this interface implementation is
+       (minRev <= IFREVISION()))
+        // at least what is being asked for
+    {
+        if (actualRev) // Make sure this is not a NULL pointer
+            *actualRev = IFREVISION();
+        return this;
+    }
+
+    if((strcmp(ifName, CAInterface::IFNAME()) == 0) &&
+       minRev <= CAInterface::IFREVISION())
+    {
+        if (actualRev != NULL)
+            *actualRev = CAInterface::IFREVISION();
+        return this;// Dynamic_cast<TracePluginInterface *>(this);
+    }
+    return NULL;
+}
+
+
+CoverageTrace::CoverageTrace(const char *instance_name_,
+                             const char *trace_file_prefix_) :
+    instance_name(instance_name_),
+    trace_file_prefix(trace_file_prefix_)
+{
+  printf("CoverageTrace::CoverageTrace\n");
+}
+
+CoverageTrace::~CoverageTrace()
+{
+  printf("CoverageTrace::~CoverageTrace\n");
+}
+
+bool
+CoverageTrace::Error(const char *msg)
+{
+    fprintf(stderr, "%s\n", msg);
+    return false;
+}
+
+// Method that registers the simulation traces events. In this case registers
+// for trace sources with the 'INST' name.
+CADIReturn_t
+CoverageTrace::RegisterSimulation(CAInterface *ca_interface)
+{
+  printf("CoverageTrace::RegisterSimulation\n");
+    if (!ca_interface) {
+        Error("Received CAInterface NULL pointer.");
+        return CADI_STATUS_IllegalArgument;
+    }
+    std::stringstream ss;
+
+    SystemTraceInterface *sys_if =
+                          ca_interface->ObtainPointer<SystemTraceInterface>();
+    if (sys_if == 0) {
+        Error("Got a NULL SystemTraceInterface.");
+        return CADI_STATUS_GeneralError;
+    }
+
+    for(SystemTraceInterface::TraceComponentIndex tci=0;
+        tci < sys_if->GetNumOfTraceComponents(); ++tci) {
+        const char* tpath = sys_if->GetComponentTracePath(tci);
+        CAInterface *caif = sys_if->GetComponentTrace(tci);
+        ComponentTraceInterface *cti =
+                                 caif->ObtainPointer<ComponentTraceInterface>();
+        if (cti == 0) {
+            Error("Could not get TraceInterface for component.");
+            continue;
+        }
+
+        if (cti->GetTraceSource("INST") != 0) {
+            TraceComponentContext *trace_component = new
+                                                TraceComponentContext(tpath);
+
+            // To register a new trace source the arguments are the
+            // name of the trace source followed by a vector of
+            // pairs of (field name,field type).
+            InstructionTraceContext *inst_cont = new InstructionTraceContext(
+                                            "INST",
+                                            { {"PC", u32},
+                                            {"SIZE", u32}}
+                                        );
+            inst_cont->nb_insts = 0;
+            inst_cont->CreateEvent(&cti, inst_cont->Callback);
+            trace_component->AddTraceSource(inst_cont);
+            trace_components.push_back(trace_component);
+        }
+    }
+
+    return CADI_STATUS_OK;
+}
+
+// This is called before the plugin .dll/.so is unloaded and should allow the
+// plugin to do it's cleanup.
+void
+CoverageTrace::Release()
+{
+  printf("CoverageTrace::Release\n");
+    // We can dump our data now
+    int error = 0;
+    char* fname;
+    int ret;
+    std::vector<TraceComponentContext*>::iterator tcc;
+    for (tcc = trace_components.begin(); tcc < trace_components.end(); ++tcc) {
+        TraceComponentContext *tcont = *tcc;
+        // Print some overall stats
+        InstructionTraceContext* rtc = (InstructionTraceContext*)
+                                    tcont->trace_sources["INST"];
+        printf("Trace path: %s\n", tcont->trace_path.c_str());
+
+        // Construct a trace file name
+        int status = asprintf(&fname, "%s-%s.log",
+                              this->trace_file_prefix.c_str(),
+                              tcont->trace_path.c_str());
+        if ( status != 0)
+        {
+            printf("Error in asprintf: %d\n", status);
+            printf("Error description is : %s\n", strerror(errno));
+          }
+
+        // Open it
+        FILE* fp = fopen(fname, "w");
+        if (fp == NULL) {
+            fprintf(stderr, "Can't open file %s for writing.\n", fname);
+            error = 1;
+            break;
+        }
+
+        InstStatMap::iterator map_it;
+        // Dump the detailed stats
+        for (map_it = rtc->stats.begin(); map_it != rtc->stats.end();
+            ++map_it) {
+            fprintf(fp, "%08x %lu %lu\n", map_it->first, map_it->second.cnt,
+                    map_it->second.size);
+        }
+
+        // Close the file
+        ret = fclose(fp);
+        if (ret != 0) {
+            fprintf(stderr, "Failed to close %s: %s.", fname, strerror(errno));
+            error = 1;
+            break;
+        }
+
+        free(fname);
+    }
+if (error != 0)
+    delete this;
+}
+
+const char *
+CoverageTrace::GetName() const
+{
+  printf("CoverageTrace::GetName\n");
+    return instance_name.c_str();
+}
+
+// Class used to return a static object CAInterface. CAInterface provides a
+// basis for a software model built around ’components’ and ’interfaces’.
+// A component provides concrete implementations of one or more interfaces.
+// Interfaces are identified by a string name (of type if_name_t), and an
+// integer revision (type if_rev_t). A higher revision number indicates a newer
+// revision of the same interface.
+class ThePluginFactory :public PluginFactory
+{
+public:
+    virtual CAInterface *ObtainInterface(if_name_t    ifName,
+                                          if_rev_t     minRev,
+                                          if_rev_t *   actualRev);
+
+    virtual uint32_t GetNumberOfParameters();
+
+    virtual eslapi::CADIReturn_t
+        GetParameterInfos(eslapi::CADIParameterInfo_t *parameter_info_list);
+
+    virtual CAInterface *Instantiate(const char *instance_name,
+                                     uint32_t number_of_parameters,
+                                     eslapi::CADIParameterValue_t *parameter_values);
+
+    virtual void Release();
+
+    virtual const char *GetType() const { return "CoverageTrace"; }
+    virtual const char *GetVersion() const { return PLUGIN_VERSION; }
+};
+
+// Allows a client to obtain a reference to any of the interfaces that the
+// component implements. The client specifies the id and revision of the
+// interface that it wants to request. The component can return NULL if it
+// doesn’t implement that interface, or only implements a lower revision.
+// The client in this case is the Arm FVP model.
+CAInterface *ThePluginFactory::ObtainInterface(if_name_t ifName,
+                                  if_rev_t     minRev,
+                                  if_rev_t *   actualRev)
+{
+  printf("ThePluginFactory::ObtainInterface\n");
+    // If someone is asking for the matching interface
+    if((strcmp(ifName,IFNAME()) == 0) &&
+        // and the revision of this interface implementation is
+       (minRev <= IFREVISION()))
+        // at least what is being asked for
+    {
+        if (actualRev) // Make sure this is not a NULL pointer
+            *actualRev = IFREVISION();
+        return static_cast<ThePluginFactory *>(this);
+    }
+
+    if((strcmp(ifName, CAInterface::IFNAME()) == 0) &&
+       minRev <= CAInterface::IFREVISION())
+    {
+        if (actualRev) // Make sure this is not a NULL pointer
+            *actualRev = CAInterface::IFREVISION();
+        return static_cast<CAInterface *>(this);
+    }
+    return NULL;
+}
+
+uint32_t ThePluginFactory::GetNumberOfParameters()
+{
+  printf("ThePluginFactory::GetNumberOfParameters\n");
+  return 1;
+}
+
+eslapi::CADIReturn_t
+ThePluginFactory::GetParameterInfos(
+eslapi::CADIParameterInfo_t *parameter_info_list)
+{
+    printf("ThePluginFactory::GetParameterInfos\n");
+    *parameter_info_list = CADIParameterInfo_t(
+        0, "trace-file-prefix", CADI_PARAM_STRING,
+        "Prefix of the trace files.", 0, 0, 0, 0, "covtrace"
+    );
+    return CADI_STATUS_OK;
+}
+
+// Method that creates a new instance of the trace plugin
+CAInterface *ThePluginFactory::Instantiate(const char *instance_name,
+                              uint32_t param_nb,
+                              eslapi::CADIParameterValue_t *values)
+{
+    printf("ThePluginFactory::Instantiate\n");
+    const char *trace_file_prefix = 0;
+    printf("CoverageTrace: number of params: %d\n", param_nb);
+    for (uint32_t i = 0; i < param_nb; ++i) {
+        if (values[i].parameterID == 0) {
+            trace_file_prefix = values[i].stringValue;
+        } else {
+            printf("\tCoverageTrace: got unexpected param %d\n",
+                   values[i].parameterID);
+        }
+    }
+    return new CoverageTrace(instance_name, trace_file_prefix);
+}
+
+void ThePluginFactory::Release()
+{
+  printf("ThePluginFactory::Release\n");
+}
+
+static ThePluginFactory factory_instance;
+
+// Entry point for the instantiation of the plugin.
+// Returns a pointer to an static object to create the interface for the
+// plugin.
+CAInterface *GetCAInterface()
+{
+    printf("********->GetCAInterface\n");
+    return &factory_instance;
+}
+
+// End of file CoverageTrace.cpp
diff --git a/coverage-tool/coverage-plugin/plugin_utils.cc b/coverage-tool/coverage-plugin/plugin_utils.cc
new file mode 100644
index 0000000..8eb3024
--- /dev/null
+++ b/coverage-tool/coverage-plugin/plugin_utils.cc
@@ -0,0 +1,65 @@
+/*!
+##############################################################################
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+##############################################################################
+*/
+
+#include "plugin_utils.h"
+
+// Get a named trace source, create an event class from the named subset of
+// event fields, register the event class and look up the field indexes, and
+// register a user-provided MTI callback with the trace source.
+// Writes to error_ss and returns false if anything fails.
+bool RegisterCallbackForComponent(const MTI::ComponentTraceInterface *mti,
+                         const char *trace_source,
+                         ValueBind_t *value_bind, void *this_ptr,
+                         MTI::CallbackT callback,
+                         MTI::EventClass **ptr_event_class,
+                         std::stringstream &error_ss)
+{
+    const MTI::TraceSource *source = mti->GetTraceSource(trace_source);
+    if (!source) {
+        error_ss << "Could not find " << trace_source << " source";
+        return false;
+    }
+
+    MTI::FieldMask mask = 0;
+    const MTI::EventFieldType *eft;
+
+    for(unsigned i=0; value_bind[i].name != 0; i++) {
+        if ((eft = source->GetField( value_bind[i].name )) != 0) {
+            mask |= 1 << eft->GetIndex();
+        } else {
+            error_ss << "No field " << value_bind[i].name <<
+                    " found in " << trace_source << " trace source";
+            return false;
+        }
+    }
+
+    MTI::EventClass *event_class = source->CreateEventClass(mask);
+    if (!event_class) {
+        error_ss << "Unable to register event class for " <<
+                trace_source << " trace source.";
+        return false;
+    }
+    for(unsigned i=0; value_bind[i].name != 0; i++)
+    {
+        MTI::ValueIndex idx = event_class->GetValueIndex(value_bind[i].name);
+        if (idx != -1) {
+            *(value_bind[i].index) = idx;
+       } else {
+           error_ss << "Unable to GetValueIndex for " << trace_source
+                    << "." << value_bind[i].name << ".";
+           return false;
+       }
+    }
+    if (callback &&
+        event_class->RegisterCallback(callback, this_ptr) != MTI::MTI_OK) {
+        error_ss << "RegisterCallback failed for " << trace_source;
+        return false;
+    }
+    *ptr_event_class = event_class;
+    return true;
+}
diff --git a/coverage-tool/coverage-plugin/plugin_utils.h b/coverage-tool/coverage-plugin/plugin_utils.h
new file mode 100644
index 0000000..546e5fc
--- /dev/null
+++ b/coverage-tool/coverage-plugin/plugin_utils.h
@@ -0,0 +1,46 @@
+/*!
+##############################################################################
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+##############################################################################
+*/
+#ifndef _COVERAGE_TOOL_COVERAGE_PLUGIN_PLUGIN_UTILS_H_
+#define _COVERAGE_TOOL_COVERAGE_PLUGIN_PLUGIN_UTILS_H_
+
+#include <sstream>
+#include <map>
+#include <vector>
+#include <string>
+#include "MTI/ModelTraceInterface.h"
+using namespace eslapi;
+using namespace MTI;
+using namespace std;
+
+typedef struct {
+    const char *name;
+    MTI::ValueIndex *index;
+} ValueBind_t;
+
+// Declare an MTI callback method and define a static thunk method to call
+// into this from C code.
+#define CALLBACK_DECL_AND_THUNK(class_name, name) \
+    static void name##Thunk(void * user_data, const MTI::EventClass *event_class, const MTI::EventRecord *record) \
+    {                                                                                                   \
+        reinterpret_cast<class_name *>(user_data)->name(event_class, record);                           \
+    }                                                                                                   \
+    void name(const MTI::EventClass *event_class, const MTI::EventRecord *record)
+
+
+// Get a named trace source, create an event class from the named subset of
+// event fields, register the event class and look up the field indexes, and
+// register a user-provided MTI callback with the trace source.
+// Writes to error_ss and returns false if anything fails.
+bool RegisterCallbackForComponent(const MTI::ComponentTraceInterface *mti,
+                         const char *trace_source,
+                         ValueBind_t *value_bind, void *this_ptr,
+                         MTI::CallbackT callback,
+                         MTI::EventClass **ptr_event_class,
+                         std::stringstream &error_ss);
+
+#endif // _COVERAGE_TOOL_COVERAGE_PLUGIN_PLUGIN_UTILS_H_
diff --git a/coverage-tool/coverage-plugin/trace_sources.h b/coverage-tool/coverage-plugin/trace_sources.h
new file mode 100644
index 0000000..57f6462
--- /dev/null
+++ b/coverage-tool/coverage-plugin/trace_sources.h
@@ -0,0 +1,229 @@
+/*!
+##############################################################################
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+##############################################################################
+*/
+
+#ifndef _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_
+#define _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_
+
+#include <map>
+#include <vector>
+#include <string>
+#include <algorithm>
+#include "MTI/ModelTraceInterface.h"
+
+using namespace MTI;
+using namespace std;
+
+struct InstStat {
+    uint64_t cnt;
+    uint64_t size;
+};
+
+typedef std::map<uint32_t, InstStat> InstStatMap;
+
+//Defining types for fields
+enum enum_types {u32, boolT};
+typedef enum_types ValueTypes;
+
+/*
+ * Structure used to save field data
+ */
+struct TFields{
+    ValueTypes t;
+    MTI::ValueIndex index;
+    void *value;
+};
+// Map of fields => Key -> Field name
+typedef map<string, TFields> TraceFieldsMap;
+
+/*
+ * Structure used to pass field data between trace contexts
+ */
+struct TParams {
+    void *value;
+    ValueTypes t;
+};
+// Map of fields => Key -> Field name
+typedef map<string, TParams> ParamsMap;
+
+/*
+ * Generic function to output errors
+ */
+bool Error(const char *msg)
+{
+    fprintf(stderr, "%s\n", msg);
+    return false;
+}
+
+/*
+ * Base class for Trace Source contexts
+ *
+ */
+class TraceSourceContext {
+    public:
+        string name; //Trace source name
+        TraceFieldsMap fields; //Fields to be used for the event
+        MTI::EventClass *event_class; //Event object to register callback
+        ParamsMap params; //List of parameters from another trace source
+
+/*
+ * Constructor that converts/stores the pairs of <field name, field type>
+ * in the 'fields' member.
+*/
+TraceSourceContext(const char* tname,
+                    vector<pair<string, ValueTypes>> fields_def) {
+    name = tname;
+    string key;
+    // Referenced by field name => field type
+    for (size_t i=0; i < fields_def.size(); ++ i) {
+        key = fields_def[i].first;
+        fields[key].t = fields_def[i].second;
+    }
+}
+
+/*
+ * Generic Callback that can be used by derived objects. It fills the
+ * 'value' member in the 'fields' structure with a void* to the value
+ * retrieved from the component.
+*/
+template <class T>
+static T *TraceCallback(void* user_data,
+                         const MTI::EventClass *event_class,
+                         const MTI::EventRecord *record) {
+    T *tc = static_cast<T*>(user_data);
+    // Filled by Component
+    TraceFieldsMap::iterator it;
+    for (it = tc->fields.begin(); it != tc->fields.end(); ++it) {
+       // Based in the type creates an object with initial
+       // value retrieved from the component using the index
+       // for that field.
+        switch (it->second.t) {
+            case u32: it->second.value = new uint32_t(
+                record->Get<uint32_t>(event_class, it->second.index));
+                break;
+            case boolT: it->second.value = new bool(
+                record->GetBool(event_class, it->second.index));
+                break;
+        }
+    }
+    return tc;
+}
+
+/*
+ * Generic method to copy the fields from this trace source to the params
+ * member in other trace source. Optionally a list of field names can be
+ * passed to filter the list of field names copied.
+ * The params member is a Map of with the Field Id (name)  as the key.
+*/
+void PassFieldstoParams(TraceSourceContext *target,
+                            vector<string> field_names={}) {
+        TraceFieldsMap::iterator it;
+        for (it = fields.begin(); it != fields.end(); ++it) {
+            bool found = std::find(field_names.begin(), field_names.end(),
+                it->first) != field_names.end();
+            if ((!field_names.empty()) && (!found))
+                continue;
+            target->params[it->first].t = it->second.t;
+            switch (it->second.t) {
+                case u32:
+                    target->params[it->first].value =
+                        new uint32_t(*((uint32_t*)it->second.value));
+                    break;
+                case boolT:
+                    target->params[it->first].value =
+                        new bool(*((bool*)it->second.value));
+                    break;
+            }
+        }
+}
+/*
+ * Method that creates an event object in the trace source based in the
+ * fields given in the constructor. It then registers the given callback
+ * to this event.
+*/
+MTI::EventClass *CreateEvent(ComponentTraceInterface **ptr_cti,
+                MTI::CallbackT callback) {
+
+    ComponentTraceInterface *cti = *ptr_cti;
+    std::stringstream ss;
+    ComponentTraceInterface *mti = 0;
+
+    if (cti->GetTraceSource(name.c_str()) != 0) {
+        TraceSource* ts = cti->GetTraceSource(name.c_str());
+        printf("Trace source attached: %s\n", ts->GetName());
+
+        size_t map_size = fields.size();
+        ValueBind_t *values_array = new ValueBind_t[map_size + 1];
+        TraceFieldsMap::iterator it;
+        int i = 0;
+        for (it = fields.begin(); it != fields.end(); ++it) {
+            values_array[i]= ((ValueBind_t) { it->first.c_str(),
+                &it->second.index });
+            ++i;
+        };
+        values_array[map_size] = {0, 0}; //sentinel
+
+        mti = static_cast<ModelTraceInterface *>(cti);
+        if (!RegisterCallbackForComponent(mti, name.c_str(), values_array,
+            this, callback, &event_class, ss)) {
+            Error(ss.str().c_str());
+            return 0;
+        }
+        return event_class;
+    }
+    return 0;
+}
+};
+
+/*
+ * Class and types used to handle trace sources belonging to a
+ * component.
+*/
+typedef map<string, TraceSourceContext*> MapTraceSourcesType;
+class TraceComponentContext {
+    public:
+        string trace_path;
+        MapTraceSourcesType trace_sources;
+
+TraceComponentContext(string tpath) {
+        trace_path = tpath;
+}
+
+void AddTraceSource(TraceSourceContext *ts) {
+        trace_sources[ts->name] = ts;
+}
+};
+
+/*
+ * Class used to instantiate a Instruction trace source
+*/
+class InstructionTraceContext: public TraceSourceContext {
+    public:
+        using TraceSourceContext::TraceSourceContext;
+        InstStatMap stats;
+        uint64_t nb_insts;
+
+    static void Callback(void* user_data,
+                         const MTI::EventClass *event_class,
+                         const MTI::EventRecord *record) {
+        InstructionTraceContext* itc = static_cast<InstructionTraceContext*>
+                                       (user_data);
+        itc->nb_insts++; // Number of instructions
+        // Filled by Component
+        uint32_t pc = record->GetAs<uint32_t>(event_class,
+                                                      itc->fields["PC"].index);
+        uint32_t size = record->Get<uint32_t>(event_class,
+                                                    itc->fields["SIZE"].index);
+        // Save PC stats. If not already present in the map, a counter with
+        // value 0 will be created before incrementing.
+        InstStat& is = itc->stats[pc];
+        is.cnt++;
+        is.size = size;
+    };
+};
+
+#endif // _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_