diff --git a/coverage-tool/coverage-plugin/coverage_trace.cc b/coverage-tool/coverage-plugin/coverage_trace.cc index 4dc72ee7d66f0a4bfde141dc278bf3b48e9009c1..d2b13fdc954d66b2c71b310127e9bd3790a5d247 100644 --- a/coverage-tool/coverage-plugin/coverage_trace.cc +++ b/coverage-tool/coverage-plugin/coverage_trace.cc @@ -1,6 +1,6 @@ /*! ############################################################################## -# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause ############################################################################## @@ -12,6 +12,7 @@ #include "MTI/PluginFactory.h" #include "MTI/PluginInstance.h" #include "MTI/ModelTraceInterface.h" +#include "MTI/ParameterInterface.h" #include "plugin_utils.h" #include "trace_sources.h" @@ -26,6 +27,7 @@ #include #include #include +#include "SimpleCADI.h" #ifdef SG_MODEL_BUILD #include "builddata.h" @@ -34,19 +36,58 @@ #define PLUGIN_VERSION "unreleased" #endif +enum plugin_param_t +{ +TRACE_FILE_PREFIX, +TRACE_MODE, +TOTAL_PARAMETERS +}; using namespace eslapi; using namespace MTI; using namespace std; // Implements the plugin interface for trace coverage -class CoverageTrace :public PluginInstance + +// 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; } +}; + +static ThePluginFactory *GetThePluginFactory(); +class CoverageTrace : + public ParameterInterface, + 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(const char *instance_name, const char *trace_file_prefix, + int _mode); ~CoverageTrace(); /** This is to associate a plugin with a simulation instance. Exactly one @@ -58,9 +99,24 @@ public: // This is called before the plugin .dll/.so is unloaded and should allow // the plugin to do it's cleanup. virtual void Release(); + void Save(void); virtual const char *GetName() const; - + virtual eslapi::CADIReturn_t GetParameterInfos(uint32_t start_index, + uint32_t desired_num_of_params, + uint32_t* actual_num_of_params, + eslapi::CADIParameterInfo_t* params); + + virtual eslapi::CADIReturn_t GetParameterInfo(const char* parameterName, + eslapi::CADIParameterInfo_t* param); + + virtual eslapi::CADIReturn_t GetParameterValues(uint32_t parameter_count, + uint32_t* actual_num_of_params_read, + eslapi::CADIParameterValue_t* param_values_out); + virtual eslapi::CADIReturn_t SetParameterValues(uint32_t parameter_count, + eslapi::CADIParameterValue_t* parameters, + eslapi::CADIFactoryErrorMessage_t* error); + ModeChangeTraceContext *mode_change; private: std::string instance_name; @@ -68,6 +124,7 @@ private: vector trace_components; std::string trace_file_prefix; + int trace_mode; }; CAInterface *CoverageTrace::ObtainInterface(if_name_t ifName, @@ -76,14 +133,14 @@ CAInterface *CoverageTrace::ObtainInterface(if_name_t ifName, { printf("CoverageTrace::ObtainInterface\n"); // If someone is asking for the matching interface - if((strcmp(ifName,IFNAME()) == 0) && + if((strcmp(ifName,PluginInstance::IFNAME()) == 0) && // and the revision of this interface implementation is - (minRev <= IFREVISION())) + (minRev <= PluginInstance::IFREVISION())) // at least what is being asked for { if (actualRev) // Make sure this is not a NULL pointer - *actualRev = IFREVISION(); - return this; + *actualRev = PluginInstance::IFREVISION(); + return dynamic_cast(this); } if((strcmp(ifName, CAInterface::IFNAME()) == 0) && @@ -91,16 +148,25 @@ CAInterface *CoverageTrace::ObtainInterface(if_name_t ifName, { if (actualRev != NULL) *actualRev = CAInterface::IFREVISION(); - return this;// Dynamic_cast(this); + return dynamic_cast(dynamic_cast(this)); + } + if((strcmp(ifName, ParameterInterface::IFNAME()) == 0) && + minRev <= ParameterInterface::IFREVISION()) + { + if (actualRev != NULL) + *actualRev = ParameterInterface::IFREVISION(); + return dynamic_cast(this); } + printf("CoverageTrace::ObtainInterface Failed!\n"); return NULL; } CoverageTrace::CoverageTrace(const char *instance_name_, - const char *trace_file_prefix_) : + const char *trace_file_prefix_, int _mode) : instance_name(instance_name_), - trace_file_prefix(trace_file_prefix_) + trace_file_prefix(trace_file_prefix_), + trace_mode(_mode) { printf("CoverageTrace::CoverageTrace\n"); } @@ -142,6 +208,9 @@ CoverageTrace::RegisterSimulation(CAInterface *ca_interface) CAInterface *caif = sys_if->GetComponentTrace(tci); ComponentTraceInterface *cti = caif->ObtainPointer(); + InstructionTraceContext *inst_cont = NULL; + MTI::EventClass * event = NULL; + if (cti == 0) { Error("Could not get TraceInterface for component."); continue; @@ -154,16 +223,39 @@ CoverageTrace::RegisterSimulation(CAInterface *ca_interface) // 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 = new InstructionTraceContext( + "INST", + { {"PC", u32}, + {"SIZE", u32}} + ); inst_cont->nb_insts = 0; - inst_cont->CreateEvent(&cti, inst_cont->Callback); + event = inst_cont->CreateEvent(&cti, inst_cont->Callback); + event->UnregisterCallback(inst_cont->Callback, inst_cont); trace_component->AddTraceSource(inst_cont); trace_components.push_back(trace_component); } + if (cti->GetTraceSource("MODE_CHANGE") != 0) { + MTI::EventClass * mode_event = NULL; + if(!event) { + Error("Could not set mode_change event"); + continue; + } + // 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). + this->mode_change = new ModeChangeTraceContext( + "MODE_CHANGE", + { {"MODE", u8}, + {"NON_SECURE", u8} + } + ); + mode_event = this->mode_change->CreateEvent(&cti, this->mode_change->Callback); + this->mode_change->event = event; + this->mode_change->itc = inst_cont; + this->mode_change->mode_mask = trace_mode; + mode_event->RegisterCallback(this->mode_change->Callback, mode_change); + } + } return CADI_STATUS_OK; @@ -174,8 +266,14 @@ CoverageTrace::RegisterSimulation(CAInterface *ca_interface) void CoverageTrace::Release() { - printf("CoverageTrace::Release\n"); + printf("CoverageTrace::Release\n"); // We can dump our data now + this->Save(); +} + +void +CoverageTrace::Save(void) +{ int error = 0; char* fname; int ret; @@ -191,7 +289,7 @@ CoverageTrace::Release() int status = asprintf(&fname, "%s-%s.log", this->trace_file_prefix.c_str(), tcont->trace_path.c_str()); - if ( status != 0) + if ( status == -1) { printf("Error in asprintf: %d\n", status); printf("Error description is : %s\n", strerror(errno)); @@ -223,8 +321,9 @@ CoverageTrace::Release() free(fname); } -if (error != 0) - delete this; + printf("Everything saved\n"); + if (error != 0) + delete this; } const char * @@ -234,33 +333,103 @@ CoverageTrace::GetName() const 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 +CADIReturn_t CoverageTrace::GetParameterInfos(uint32_t start_index, + uint32_t desired_num_of_params, + uint32_t* actual_num_of_params, + CADIParameterInfo_t* params) { -public: - virtual CAInterface *ObtainInterface(if_name_t ifName, - if_rev_t minRev, - if_rev_t * actualRev); - virtual uint32_t GetNumberOfParameters(); + *actual_num_of_params = GetThePluginFactory()->GetNumberOfParameters(); + return GetThePluginFactory()->GetParameterInfos(params); - 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); +CADIReturn_t CoverageTrace::GetParameterInfo(const char* parameterName, + CADIParameterInfo_t* param) +{ + uint32_t num_of_params = GetThePluginFactory()->GetNumberOfParameters(); + CADIParameterInfo_t* plugin_parameters = NULL; - virtual void Release(); + GetThePluginFactory()->GetParameterInfos(plugin_parameters); - virtual const char *GetType() const { return "CoverageTrace"; } - virtual const char *GetVersion() const { return PLUGIN_VERSION; } -}; + if (param == nullptr) + { + return CADI_STATUS_IllegalArgument; + } + + printf("Reading parameter info %s \n", parameterName); + for (uint32_t i = 0; i < num_of_params; ++i) + { + if (strcmp(plugin_parameters[i].name, parameterName) == 0) + { + *param = plugin_parameters[i]; + return CADI_STATUS_OK; + } + } + *param = plugin_parameters[0]; + return CADI_STATUS_OK; + +} + +CADIReturn_t CoverageTrace::GetParameterValues(uint32_t parameter_count, + uint32_t* actual_num_of_params_read, + CADIParameterValue_t *param_values_out) +{ + if (param_values_out == nullptr || actual_num_of_params_read == nullptr) + { + return CADI_STATUS_IllegalArgument; + } + + *actual_num_of_params_read = 0; + for (uint32_t i = 0; i < parameter_count; ++i) + { + CADIParameterValue_t ¶m_value = param_values_out[i]; + + switch (param_value.parameterID) + { + case TRACE_FILE_PREFIX: + strncpy(param_value.stringValue, + this->trace_file_prefix.c_str(), + sizeof(param_value.stringValue)); + break; + + case TRACE_MODE: + param_value.intValue = this->mode_change->mode_mask; + break; + default: // unknown ID + + *actual_num_of_params_read = i; + return CADI_STATUS_IllegalArgument; + } + } + + *actual_num_of_params_read = parameter_count; + return CADI_STATUS_OK; +} + +CADIReturn_t CoverageTrace::SetParameterValues(uint32_t parameter_count, + CADIParameterValue_t* parameters, + CADIFactoryErrorMessage_t* error) +{ + for (uint32_t i = 0; i < parameter_count; ++i) + { + CADIParameterValue_t ¶meter = parameters[i]; + switch(parameter.parameterID) + { + case TRACE_FILE_PREFIX: + this->trace_file_prefix = parameter.stringValue; + this->Save(); + break; + case TRACE_MODE: + this->mode_change->mode_mask = parameter.intValue; + break; + default: + ; + break; + } + } + return CADI_STATUS_OK; +} // 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 @@ -296,7 +465,7 @@ CAInterface *ThePluginFactory::ObtainInterface(if_name_t ifName, uint32_t ThePluginFactory::GetNumberOfParameters() { printf("ThePluginFactory::GetNumberOfParameters\n"); - return 1; + return TOTAL_PARAMETERS; } eslapi::CADIReturn_t @@ -304,10 +473,12 @@ 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" - ); + parameter_info_list[0] = CADIParameterInfo_t( + TRACE_FILE_PREFIX, "trace-file-prefix", CADI_PARAM_STRING, + "Prefix of the trace files.", true, 0, 0, 0, "covtrace"); + parameter_info_list[1] = CADIParameterInfo_t( + TRACE_MODE, "trace-mode", CADI_PARAM_INT, + "Selects which modes to trace.", true, 0, 0xffffffff, 0xffffffff, 0); return CADI_STATUS_OK; } @@ -318,16 +489,21 @@ CAInterface *ThePluginFactory::Instantiate(const char *instance_name, { printf("ThePluginFactory::Instantiate\n"); const char *trace_file_prefix = 0; + int mode_value = 0xffffffff; + printf("CoverageTrace: number of params: %d\n", param_nb); for (uint32_t i = 0; i < param_nb; ++i) { - if (values[i].parameterID == 0) { + if (values[i].parameterID == TRACE_FILE_PREFIX) { trace_file_prefix = values[i].stringValue; + } else if (values[i].parameterID == TRACE_MODE) { + mode_value = values[i].intValue; } else { printf("\tCoverageTrace: got unexpected param %d\n", values[i].parameterID); } } - return new CoverageTrace(instance_name, trace_file_prefix); + return (PluginInstance*)new CoverageTrace(instance_name, trace_file_prefix, + mode_value); } void ThePluginFactory::Release() @@ -345,5 +521,9 @@ CAInterface *GetCAInterface() printf("********->GetCAInterface\n"); return &factory_instance; } +static ThePluginFactory *GetThePluginFactory() +{ + return &factory_instance; +} // End of file CoverageTrace.cpp diff --git a/coverage-tool/coverage-plugin/coverage_trace_parameters_change.py b/coverage-tool/coverage-plugin/coverage_trace_parameters_change.py new file mode 100644 index 0000000000000000000000000000000000000000..73841c50f4f345785da0f39effb4d8db1d2e3709 --- /dev/null +++ b/coverage-tool/coverage-plugin/coverage_trace_parameters_change.py @@ -0,0 +1,78 @@ +# !/usr/bin/env python +############################################################################## +# Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +############################################################################## +import iris.debug as debug +import iris.iris as iris +import argparse +import textwrap + +def arg_parser(): + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, + description = textwrap.dedent('''\ + Tool to change the plugin parameters of the FVP coverage-plugin. + + To be able to connect to the model, the model needs to have the iris-servier active. + The -p of the model can be used to show the port to connect to. + When starting a model with the iris-server, the model will wait until a debugger + is connect and ran. We can start the model automatically by using the -R option. + Example: + MODEL --iris-server -R -p + ''')) + parser.add_argument( + "-p", + "--port", + type=int, + default=7100, + help="set the port of the running model" + ) + parser.add_argument( + "-m", + "--mode", + type=lambda x: int(x,0), + default=-1, + help="set the mode to trace as a hex number." + ) + parser.add_argument( + "-f", + "--file", + default="", + help="set the file-prefix of the trace files" + ) + parser.add_argument( + "-s", + "--save", + action='store_true', + help="Save the current trace" + ) + return parser.parse_args() + +def main(): + parsed_args = arg_parser() + model = debug.NetworkModel("localhost", parsed_args.port) + + components = model.get_targets() + for component in components: + if "coverage_trace" in component.instName: + trace_component = component + + if trace_component: + if parsed_args.mode != -1: + trace_component.parameters['trace-mode'] = parsed_args.mode + print("Changed trace mode to " + hex(parsed_args.mode)) + elif parsed_args.file != "": + trace_component.parameters['trace-file-prefix'] = parsed_args.file + print("Changed trace prefix to" + parsed_args.file) + elif parsed_args.save: + trace_component.parameters['trace-file-prefix'] = trace_component.parameters['trace-file-prefix'] + print("Saved trace files to " + trace_component.parameters['trace-file-prefix']) + else: + print("Nothing to do") + else: + print("Could not find plugin component") + + +if __name__ == "__main__": + main() diff --git a/coverage-tool/coverage-plugin/trace_sources.h b/coverage-tool/coverage-plugin/trace_sources.h index 57f646291862da249616390a3c1c8c9a766b19f1..e200bc569f103bd503811f2300afcd392ee51280 100644 --- a/coverage-tool/coverage-plugin/trace_sources.h +++ b/coverage-tool/coverage-plugin/trace_sources.h @@ -26,7 +26,7 @@ struct InstStat { typedef std::map InstStatMap; //Defining types for fields -enum enum_types {u32, boolT}; +enum enum_types {u32, boolT, u8}; typedef enum_types ValueTypes; /* @@ -108,6 +108,9 @@ static T *TraceCallback(void* user_data, case boolT: it->second.value = new bool( record->GetBool(event_class, it->second.index)); break; + case u8: it->second.value = new uint8_t( + record->Get(event_class, it->second.index)); + break; } } return tc; @@ -137,6 +140,10 @@ void PassFieldstoParams(TraceSourceContext *target, target->params[it->first].value = new bool(*((bool*)it->second.value)); break; + case u8: + target->params[it->first].value = + new uint8_t(*((uint8_t*)it->second.value)); + break; } } } @@ -226,4 +233,91 @@ class InstructionTraceContext: public TraceSourceContext { }; }; +struct mode_change_type { + uint8_t mode_value; + char name[5]; +}; +const struct mode_change_type types[] = { + {0x0 , "EL0t"}, //0 + {0x4 , "EL1t"}, //1 + {0x5 , "EL1h"}, //2 + {0x8 , "EL2t"}, //3 + {0x9 , "EL2h"}, //4 + {0xc , "EL3t"}, //5 + {0xd , "EL3h"}, //6 + {0x10 , "usr"}, //7 + {0x11 , "fiq"}, //8 + {0x12 , "irq"}, //9 + {0x13 , "svc"}, //10 + {0x16 , "mon"}, //11 + {0x17 , "abt"}, //12 + {0x1a , "hyp"}, //13 + {0x1b , "und"}, //14 + {0x1f , "sys"}, //15 + /* Secure modes */ + {0x0 , "EL0t"}, //16 + {0x4 , "EL1t"}, //17 + {0x5 , "EL1h"}, //18 + {0x8 , "EL2t"}, //19 + {0x9 , "EL2h"}, //20 + {0xc , "EL3t"}, //21 + {0xd , "EL3h"}, //22 + {0x10 , "usr"}, //23 + {0x11 , "fiq"}, //24 + {0x12 , "irq"}, //25 + {0x13 , "svc"}, //26 + {0x16 , "mon"}, //27 + {0x17 , "abt"}, //28 + {0x1a , "hyp"}, //29 + {0x1b , "und"}, //30 + {0x1f , "sys"} //31 +}; + +class ModeChangeTraceContext: public TraceSourceContext { + public: + using TraceSourceContext::TraceSourceContext; + MTI::EventClass *event; + uint32_t mode_mask; + InstructionTraceContext* itc; + + + static void Callback(void* user_data, + const MTI::EventClass *event_class, + const MTI::EventRecord *record) + { + ModeChangeTraceContext* mtc = static_cast + (user_data); + static bool trace = false; + bool new_trace = false; + uint8_t mode = record->GetAs(event_class, + mtc->fields["MODE"].index); + uint8_t nsecure = record->Get(event_class, + mtc->fields["NON_SECURE"].index); + int start_mask = 0; + + if(nsecure) { + start_mask = 0; + } else { + start_mask = 16; + } + + for (int i = start_mask; i < start_mask + 16; i++) { + if (types[i].mode_value == mode) { + new_trace = new_trace || (mtc->mode_mask & (1 << i)); + break; + } + } + + if (new_trace && !trace) { + mtc->event->RegisterCallback(InstructionTraceContext::Callback, + mtc->itc); + } else if (!new_trace && trace){ + mtc->event->UnregisterCallback( + InstructionTraceContext::Callback, + mtc->itc); + } + trace = new_trace; + }; + +}; #endif // _COVERAGE_TOOL_COVERAGE_PLUGIN_TRACE_SOURCES_H_ diff --git a/coverage-tool/coverage-reporting/intermediate_layer.py b/coverage-tool/coverage-reporting/intermediate_layer.py index be1fab7c595bfbb89a01d75d4ac3a2be6e27c2d5..701aeacb390ba5a49c38f21f826e50a2c6dd4591 100644 --- a/coverage-tool/coverage-reporting/intermediate_layer.py +++ b/coverage-tool/coverage-reporting/intermediate_layer.py @@ -1,6 +1,6 @@ # !/usr/bin/env python ############################################################################### -# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause ############################################################################### @@ -384,7 +384,7 @@ class PostProcessCC(object): """ command = "%s -Sl %s" % (OBJDUMP, elf_filename) dump = os_command(command) - dump += "\n" # For pattern matching the last \n + dump += "\n0 :" # For pattern matching the last function elf_name = os.path.splitext(os.path.basename(elf_filename))[0] # Object that handles the function line numbers in # their filename @@ -400,7 +400,7 @@ class PostProcessCC(object): # The function groups have 2 elements: # Function's block name, Function's block code function_groups = re.findall( - r"(?s)[0-9a-fA-F]+ <([a-zA-Z0-9_]+)>:\n(.+?)(?:\r*\n\n|\n$)", + r"(?s)[0-9a-fA-F]+ <([a-zA-Z0-9_]+)>:\n(.+?)(?=[A-Fa-f0-9]* <[a-zA-Z0-9_]+>:)", dump, re.DOTALL | re.MULTILINE) # Pointer to files dictionary source_files = self.source_files_coverage @@ -598,7 +598,7 @@ OBJDUMP = None READELF = None FUNCTION_LINES_ENABLED = None SOURCE_PATTERN = (r'(?s)([a-zA-Z0-9_]+)?(?:\(\):\n)?(^/.+?):([0-9]+)' - r'(?: \(.+?\))?\n(.+?)(?=\n/|\n$|([a-zA-Z0-9_]+\(\):))') + r'(?: \(.+?\))?\n(.+?)(?=\n/|([a-zA-Z0-9_]+\(\):))') def main(): diff --git a/coverage-tool/docs/design_overview.md b/coverage-tool/docs/design_overview.md index a91aaa2306aa6e07323df37bbd43fa29112f616f..7dd8c4c8af7429ac77352c4c06364096c88e53b0 100644 --- a/coverage-tool/docs/design_overview.md +++ b/coverage-tool/docs/design_overview.md @@ -57,6 +57,13 @@ The following diagram shows an example trace capture output from the coverage tr ... ``` +### Exception level tracing + +The exception level tracing is implemented by registering a callback which will be called for each exception level change. Each time the exception level has changed, we check if the new exception level is enabled in the trace-mode. When it is enabled we register the inst trace callback. If the exception level is not enabled we disable the callback. +This will result in instruction only being recorded for the enabled exception levels. + +![](exception.png) + ### Post-processing stage In this stage coverage information is generated by: diff --git a/coverage-tool/docs/exception.png b/coverage-tool/docs/exception.png new file mode 100644 index 0000000000000000000000000000000000000000..70f3396be4c02adb7e2a669fab5743135244bdf4 Binary files /dev/null and b/coverage-tool/docs/exception.png differ diff --git a/coverage-tool/docs/plugin_user_guide.md b/coverage-tool/docs/plugin_user_guide.md index 5c600ddcfd5b4ea14ef2d71746c9df37d3ae9f61..d248e0e9edf3f8a19c4faac89256a7302ccfc499 100644 --- a/coverage-tool/docs/plugin_user_guide.md +++ b/coverage-tool/docs/plugin_user_guide.md @@ -24,7 +24,78 @@ You can then run your FVP model. The traces will be created at the end of the si BEWARE: Traces aren't numbered and will be overwritten if you do two successive runs. Aggregating results will require moving traces to a separate place or changing the prefix between runs. This is the responsibility of the plugin user. -*NOTE: The plugin captures the traces in memory and on the termination of the simulation it writes the data to a file. If user terminates the simulation forcefully with a Ctrl+C the trace files are not generated. +*NOTE: The plugin captures the traces in memory and on the termination of the simulation it writes the data to a file. If user terminates the simulation forcefully with a Ctrl+C the trace files are not generated. Traces can be saved by interacting with the plugin itself. More info can be found in the [Interacting with the plugin chapter](#interacting-with-the-plugin) . +### Exception level based tracing. + +The coverage tool support only tracing specific exception levels. This is useful when trying to trace a small +part of a bigger system. This is for example used to measure the code coverage of the OP-TEE secure OS. +Where the trace is only being recorded while being inside S-EL1. The exception level can be +specified by passing the `TRACE.coverage_trace.trace-mode` option. The passed value is a 32b bit field. + +|exception Level | Bit Field | +|----------------|------------------| +| **None secure modes** | +|EL0t | 0 | +|EL1t | 1 | +|EL1h | 2 | +|EL2t | 3 | +|EL2h | 4 | +|EL3t | 5 | +|EL3h | 6 | +|usr | 7 | +|fiq | 8 | +|irq | 9 | +|svc | 10 | +|mon | 11 | +|abt | 12 | +|hyp | 13 | +|und | 14 | +|sys | 15 | +| **Secure modes** | +|EL0t | 16 | +|EL1t | 17 | +|EL1h | 18 | +|EL2t | 19 | +|EL2h | 20 | +|EL3t | 21 | +|EL3h | 22 | +|usr | 23 | +|fiq | 24 | +|irq | 25 | +|svc | 26 | +|mon | 27 | +|abt | 28 | +|hyp | 29 | +|und | 30 | +|sys | 31 | + +### Interacting with the plugin + +The `trace-mode` and the `trace-file-prefix` can both be changed at run-time. +Every time the `trace-file-prefix` value is changed, the plugin will save the trace result. +This can be used to save the result without the need for the simulation to end. + +```python +#!/usr/bin/python +import iris.debug as debug +import iris.iris as iris + + +trace_file_prefix = "" +self.model = debug.NetworkModel("localhost",9000) + +self.trace_component = None +components = self.model.get_targets() +for component in components: + if "coverage_trace" in component.instName: + self.trace_component = component + +if not self.trace_component: + fail_msg("Trace component not found") +else: + # Save the trace results + self.trace_component.parameters['trace-file-prefix'] = trace_file_prefix +``` ## License [BSD-3-Clause](../../license.md)