blob: 4dc72ee7d66f0a4bfde141dc278bf3b48e9009c1 [file] [log] [blame]
Basil Eljuse4b14afb2020-09-30 13:07:23 +01001/*!
2##############################################################################
3# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6##############################################################################
7*/
8// Implements the trace plugin interface for the MTI interface to trace
9// source data from Arm FVP.
10
11#include "MTI/PluginInterface.h"
12#include "MTI/PluginFactory.h"
13#include "MTI/PluginInstance.h"
14#include "MTI/ModelTraceInterface.h"
15
16#include "plugin_utils.h"
17#include "trace_sources.h"
18
19#include <errno.h>
20#include <string>
21#include <algorithm>
22#include <cstdio>
23#include <sstream>
24#include <vector>
25#include <map>
26#include <typeinfo>
27#include <typeindex>
28#include <utility>
29
30#ifdef SG_MODEL_BUILD
31 #include "builddata.h"
32 #define PLUGIN_VERSION FULL_VERSION_STRING
33#else
34 #define PLUGIN_VERSION "unreleased"
35#endif
36
37using namespace eslapi;
38using namespace MTI;
39using namespace std;
40
41// Implements the plugin interface for trace coverage
42class CoverageTrace :public PluginInstance
43{
44public:
45 virtual CAInterface * ObtainInterface(if_name_t ifName,
46 if_rev_t minRev,
47 if_rev_t * actualRev);
48
49 CoverageTrace(const char *instance_name, const char *trace_file_prefix);
50 ~CoverageTrace();
51
52 /** This is to associate a plugin with a simulation instance. Exactly one
53 * simulation must be registered.
54 * */
55 virtual eslapi::CADIReturn_t RegisterSimulation(eslapi::CAInterface
56 *simulation);
57
58 // This is called before the plugin .dll/.so is unloaded and should allow
59 // the plugin to do it's cleanup.
60 virtual void Release();
61
62 virtual const char *GetName() const;
63
64private:
65 std::string instance_name;
66
67 bool Error(const char *);
68
69 vector<TraceComponentContext*> trace_components;
70 std::string trace_file_prefix;
71};
72
73CAInterface *CoverageTrace::ObtainInterface(if_name_t ifName,
74 if_rev_t minRev,
75 if_rev_t * actualRev)
76{
77 printf("CoverageTrace::ObtainInterface\n");
78 // If someone is asking for the matching interface
79 if((strcmp(ifName,IFNAME()) == 0) &&
80 // and the revision of this interface implementation is
81 (minRev <= IFREVISION()))
82 // at least what is being asked for
83 {
84 if (actualRev) // Make sure this is not a NULL pointer
85 *actualRev = IFREVISION();
86 return this;
87 }
88
89 if((strcmp(ifName, CAInterface::IFNAME()) == 0) &&
90 minRev <= CAInterface::IFREVISION())
91 {
92 if (actualRev != NULL)
93 *actualRev = CAInterface::IFREVISION();
94 return this;// Dynamic_cast<TracePluginInterface *>(this);
95 }
96 return NULL;
97}
98
99
100CoverageTrace::CoverageTrace(const char *instance_name_,
101 const char *trace_file_prefix_) :
102 instance_name(instance_name_),
103 trace_file_prefix(trace_file_prefix_)
104{
105 printf("CoverageTrace::CoverageTrace\n");
106}
107
108CoverageTrace::~CoverageTrace()
109{
110 printf("CoverageTrace::~CoverageTrace\n");
111}
112
113bool
114CoverageTrace::Error(const char *msg)
115{
116 fprintf(stderr, "%s\n", msg);
117 return false;
118}
119
120// Method that registers the simulation traces events. In this case registers
121// for trace sources with the 'INST' name.
122CADIReturn_t
123CoverageTrace::RegisterSimulation(CAInterface *ca_interface)
124{
125 printf("CoverageTrace::RegisterSimulation\n");
126 if (!ca_interface) {
127 Error("Received CAInterface NULL pointer.");
128 return CADI_STATUS_IllegalArgument;
129 }
130 std::stringstream ss;
131
132 SystemTraceInterface *sys_if =
133 ca_interface->ObtainPointer<SystemTraceInterface>();
134 if (sys_if == 0) {
135 Error("Got a NULL SystemTraceInterface.");
136 return CADI_STATUS_GeneralError;
137 }
138
139 for(SystemTraceInterface::TraceComponentIndex tci=0;
140 tci < sys_if->GetNumOfTraceComponents(); ++tci) {
141 const char* tpath = sys_if->GetComponentTracePath(tci);
142 CAInterface *caif = sys_if->GetComponentTrace(tci);
143 ComponentTraceInterface *cti =
144 caif->ObtainPointer<ComponentTraceInterface>();
145 if (cti == 0) {
146 Error("Could not get TraceInterface for component.");
147 continue;
148 }
149
150 if (cti->GetTraceSource("INST") != 0) {
151 TraceComponentContext *trace_component = new
152 TraceComponentContext(tpath);
153
154 // To register a new trace source the arguments are the
155 // name of the trace source followed by a vector of
156 // pairs of (field name,field type).
157 InstructionTraceContext *inst_cont = new InstructionTraceContext(
158 "INST",
159 { {"PC", u32},
160 {"SIZE", u32}}
161 );
162 inst_cont->nb_insts = 0;
163 inst_cont->CreateEvent(&cti, inst_cont->Callback);
164 trace_component->AddTraceSource(inst_cont);
165 trace_components.push_back(trace_component);
166 }
167 }
168
169 return CADI_STATUS_OK;
170}
171
172// This is called before the plugin .dll/.so is unloaded and should allow the
173// plugin to do it's cleanup.
174void
175CoverageTrace::Release()
176{
177 printf("CoverageTrace::Release\n");
178 // We can dump our data now
179 int error = 0;
180 char* fname;
181 int ret;
182 std::vector<TraceComponentContext*>::iterator tcc;
183 for (tcc = trace_components.begin(); tcc < trace_components.end(); ++tcc) {
184 TraceComponentContext *tcont = *tcc;
185 // Print some overall stats
186 InstructionTraceContext* rtc = (InstructionTraceContext*)
187 tcont->trace_sources["INST"];
188 printf("Trace path: %s\n", tcont->trace_path.c_str());
189
190 // Construct a trace file name
191 int status = asprintf(&fname, "%s-%s.log",
192 this->trace_file_prefix.c_str(),
193 tcont->trace_path.c_str());
194 if ( status != 0)
195 {
196 printf("Error in asprintf: %d\n", status);
197 printf("Error description is : %s\n", strerror(errno));
198 }
199
200 // Open it
201 FILE* fp = fopen(fname, "w");
202 if (fp == NULL) {
203 fprintf(stderr, "Can't open file %s for writing.\n", fname);
204 error = 1;
205 break;
206 }
207
208 InstStatMap::iterator map_it;
209 // Dump the detailed stats
210 for (map_it = rtc->stats.begin(); map_it != rtc->stats.end();
211 ++map_it) {
212 fprintf(fp, "%08x %lu %lu\n", map_it->first, map_it->second.cnt,
213 map_it->second.size);
214 }
215
216 // Close the file
217 ret = fclose(fp);
218 if (ret != 0) {
219 fprintf(stderr, "Failed to close %s: %s.", fname, strerror(errno));
220 error = 1;
221 break;
222 }
223
224 free(fname);
225 }
226if (error != 0)
227 delete this;
228}
229
230const char *
231CoverageTrace::GetName() const
232{
233 printf("CoverageTrace::GetName\n");
234 return instance_name.c_str();
235}
236
237// Class used to return a static object CAInterface. CAInterface provides a
238// basis for a software model built around ’components’ and ’interfaces’.
239// A component provides concrete implementations of one or more interfaces.
240// Interfaces are identified by a string name (of type if_name_t), and an
241// integer revision (type if_rev_t). A higher revision number indicates a newer
242// revision of the same interface.
243class ThePluginFactory :public PluginFactory
244{
245public:
246 virtual CAInterface *ObtainInterface(if_name_t ifName,
247 if_rev_t minRev,
248 if_rev_t * actualRev);
249
250 virtual uint32_t GetNumberOfParameters();
251
252 virtual eslapi::CADIReturn_t
253 GetParameterInfos(eslapi::CADIParameterInfo_t *parameter_info_list);
254
255 virtual CAInterface *Instantiate(const char *instance_name,
256 uint32_t number_of_parameters,
257 eslapi::CADIParameterValue_t *parameter_values);
258
259 virtual void Release();
260
261 virtual const char *GetType() const { return "CoverageTrace"; }
262 virtual const char *GetVersion() const { return PLUGIN_VERSION; }
263};
264
265// Allows a client to obtain a reference to any of the interfaces that the
266// component implements. The client specifies the id and revision of the
267// interface that it wants to request. The component can return NULL if it
268// doesn’t implement that interface, or only implements a lower revision.
269// The client in this case is the Arm FVP model.
270CAInterface *ThePluginFactory::ObtainInterface(if_name_t ifName,
271 if_rev_t minRev,
272 if_rev_t * actualRev)
273{
274 printf("ThePluginFactory::ObtainInterface\n");
275 // If someone is asking for the matching interface
276 if((strcmp(ifName,IFNAME()) == 0) &&
277 // and the revision of this interface implementation is
278 (minRev <= IFREVISION()))
279 // at least what is being asked for
280 {
281 if (actualRev) // Make sure this is not a NULL pointer
282 *actualRev = IFREVISION();
283 return static_cast<ThePluginFactory *>(this);
284 }
285
286 if((strcmp(ifName, CAInterface::IFNAME()) == 0) &&
287 minRev <= CAInterface::IFREVISION())
288 {
289 if (actualRev) // Make sure this is not a NULL pointer
290 *actualRev = CAInterface::IFREVISION();
291 return static_cast<CAInterface *>(this);
292 }
293 return NULL;
294}
295
296uint32_t ThePluginFactory::GetNumberOfParameters()
297{
298 printf("ThePluginFactory::GetNumberOfParameters\n");
299 return 1;
300}
301
302eslapi::CADIReturn_t
303ThePluginFactory::GetParameterInfos(
304eslapi::CADIParameterInfo_t *parameter_info_list)
305{
306 printf("ThePluginFactory::GetParameterInfos\n");
307 *parameter_info_list = CADIParameterInfo_t(
308 0, "trace-file-prefix", CADI_PARAM_STRING,
309 "Prefix of the trace files.", 0, 0, 0, 0, "covtrace"
310 );
311 return CADI_STATUS_OK;
312}
313
314// Method that creates a new instance of the trace plugin
315CAInterface *ThePluginFactory::Instantiate(const char *instance_name,
316 uint32_t param_nb,
317 eslapi::CADIParameterValue_t *values)
318{
319 printf("ThePluginFactory::Instantiate\n");
320 const char *trace_file_prefix = 0;
321 printf("CoverageTrace: number of params: %d\n", param_nb);
322 for (uint32_t i = 0; i < param_nb; ++i) {
323 if (values[i].parameterID == 0) {
324 trace_file_prefix = values[i].stringValue;
325 } else {
326 printf("\tCoverageTrace: got unexpected param %d\n",
327 values[i].parameterID);
328 }
329 }
330 return new CoverageTrace(instance_name, trace_file_prefix);
331}
332
333void ThePluginFactory::Release()
334{
335 printf("ThePluginFactory::Release\n");
336}
337
338static ThePluginFactory factory_instance;
339
340// Entry point for the instantiation of the plugin.
341// Returns a pointer to an static object to create the interface for the
342// plugin.
343CAInterface *GetCAInterface()
344{
345 printf("********->GetCAInterface\n");
346 return &factory_instance;
347}
348
349// End of file CoverageTrace.cpp