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/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