Adds a generic API to allow packet processors to count the amount of bytes per channel processed and not synced plus any packet header or format errors.
The ETMv4 / ETE packet processor is updated to use this API.
Statistics are also provided for the CoreSight frame demux, which are global across all channels.
Typical output from trc_pkt_lister when run with -stats option to print stats: =============================================================== Trace Packet Lister : Trace buffer done, processed 65536 bytes.
Reading packet decoder statistics....
Decode stats ID 0x10 Total Bytes: 55273; Unsynced Bytes: 1453 Bad Header Errors: 0; Bad Sequence Errors: 0 Decode stats ID 0x11 Total Bytes: 672; Unsynced Bytes: 132 Bad Header Errors: 0; Bad Sequence Errors: 0 Decode stats ID 0x12 Total Bytes: 672; Unsynced Bytes: 648 Bad Header Errors: 0; Bad Sequence Errors: 0 Decode stats ID 0x13 Total Bytes: 698; Unsynced Bytes: 0 Bad Header Errors: 0; Bad Sequence Errors: 0 Decode stats ID 0x14 Total Bytes: 0; Unsynced Bytes: 0 Bad Header Errors: 0; Bad Sequence Errors: 0 Decode stats ID 0x15 Total Bytes: 2783; Unsynced Bytes: 471 Bad Header Errors: 0; Bad Sequence Errors: 0
Frame Demux Stats Trace data bytes sent to registered ID decoders: 60098 Trace data bytes without registered ID decoders: 0 Trace data bytes with unknown ID: 81 Trace data bytes with reserved ID: 22 Frame demux bytes, ID bytes and sync bytes: 5335 Total bytes processed by frame demux: 65536 ================================================================
API adds ocsd_decode_stats_t structure to contain the statistics. (ocsd_if_types.h) C-API (ocsd_c_apo.h) adds functions:-
ocsd_dt_get_decode_stats() - get pointer to stats block.
ocsd_dt_reset_decode_stats() - resets the counts to zero. This function operates independently of the main decoder reset.
This allows for tools such as perf which may reset the decoder multiple times per AUXTRACE_BUFFER to count stats for the entire buffer rather than each capture block.
Changes since v1: 1) stats structure now contains a block for frame demux data. 2) patchset contains a number of additional build and code fixes that will be included in the 1.2.0 release.
James Clark (1): opencsd: Remove noisy printf
Mike Leach (10): opencsd: Add decode statistics API to packet processor. opencsd: ETMv4: ETE: Add packet processing stats to decoders. tests: Update test programs to use the packet decoder statistics API build: tests: Fix build warnings in snapshot parser. build: tests: Fix build warnings in mem_buff_demo test build: tests: Fix build warnings in C-API test program opencsd: stats: Add collection of CoreSight frame demux stats tests: Add printing of CS frame Demux stats to test program. tests: Update test scripts to pass additional options opencsd: Update readme and version info for v1.2.0
Yi Kong (1): opencsd: build: Remove unused variable
README.md | 9 ++- decoder/include/common/ocsd_dcd_tree.h | 29 ++++++++- .../include/common/trc_frame_deformatter.h | 4 ++ decoder/include/common/trc_pkt_proc_base.h | 47 +++++++++++++- decoder/include/opencsd/c_api/opencsd_c_api.h | 30 ++++++++- decoder/include/opencsd/ocsd_if_types.h | 47 ++++++++++++++ decoder/include/opencsd/ocsd_if_version.h | 6 +- decoder/source/c_api/ocsd_c_api.cpp | 18 +++++- decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp | 10 ++- decoder/source/ocsd_dcd_tree.cpp | 64 +++++++++++++++++++ decoder/source/trc_frame_deformatter.cpp | 60 +++++++++++++++-- decoder/source/trc_frame_deformatter_impl.h | 14 +++- decoder/source/trc_printable_elem.cpp | 2 - decoder/tests/run_pkt_decode_single.bash | 7 +- decoder/tests/run_pkt_decode_tests-ete.bash | 11 ++-- decoder/tests/run_pkt_decode_tests.bash | 17 +++-- .../include/snapshot_parser.h | 6 +- .../source/snapshot_parser.cpp | 4 ++ decoder/tests/source/c_api_pkt_print_test.c | 39 ++++++++++- decoder/tests/source/mem_buff_demo.cpp | 9 ++- decoder/tests/source/trc_pkt_lister.cpp | 63 +++++++++++++++++- 21 files changed, 455 insertions(+), 41 deletions(-)
Adds a generic statistics API to the packet processor base class to allow protocol specifc decoders to initialise and use to count total bytes processed, unsynced bytes processed, packet header errors and packet sequence errors.
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/include/common/ocsd_dcd_tree.h | 26 ++++++++++- decoder/include/common/trc_pkt_proc_base.h | 44 ++++++++++++++++++- decoder/include/opencsd/c_api/opencsd_c_api.h | 30 ++++++++++++- decoder/include/opencsd/ocsd_if_types.h | 20 +++++++++ decoder/source/c_api/ocsd_c_api.cpp | 18 +++++++- decoder/source/ocsd_dcd_tree.cpp | 39 ++++++++++++++++ 6 files changed, 171 insertions(+), 6 deletions(-)
diff --git a/decoder/include/common/ocsd_dcd_tree.h b/decoder/include/common/ocsd_dcd_tree.h index e4e74f2..a7297b2 100644 --- a/decoder/include/common/ocsd_dcd_tree.h +++ b/decoder/include/common/ocsd_dcd_tree.h @@ -168,6 +168,30 @@ public: */ ocsd_err_t removeDecoder(const uint8_t CSID);
+ /*! + * Get the stats block for the channel indicated. + * Caller must check p_stats_block->version to esure that the block + * is filled in a compatible manner. + * + * @param CSID : Configured CoreSight trace ID for the decoder. + * @param p_stats_block: block pointer to set to reference the stats block. + * + * @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned, + * OCSD_ERR_NOTINIT if decoder does not support stats counting. + */ + ocsd_err_t getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block); + + /*! + * Reset the stats block for the chosens decode channel. + * stats block is reset independently of the decoder reset to allow counts across + * multiple decode runs. + * + * @param handle : Handle to decode tree. + * @param CSID : Configured CoreSight trace ID for the decoder. + * + * @return ocsd_err_t : Library error code - OCSD_OK if successful. + */ + ocsd_err_t resetDecoderStats(const uint8_t CSID);
/* get decoder elements currently in use */
@@ -387,7 +411,7 @@ private: void destroyMemAccMapper(); ocsd_err_t initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context); - + TrcPktProcI *getPktProcI(const uint8_t CSID);
ocsd_dcd_tree_src_t m_dcd_tree_type;
diff --git a/decoder/include/common/trc_pkt_proc_base.h b/decoder/include/common/trc_pkt_proc_base.h index 3098a3d..e7c43f5 100644 --- a/decoder/include/common/trc_pkt_proc_base.h +++ b/decoder/include/common/trc_pkt_proc_base.h @@ -43,6 +43,7 @@
#include "trc_component.h" #include "comp_attach_pt_t.h" +#include "opencsd/ocsd_if_version.h"
/** @defgroup ocsd_pkt_proc OpenCSD Library : Packet Processors. @brief Classes providing Protocol Packet Processing capability. @@ -76,6 +77,8 @@ public: const uint8_t *pDataBlock, uint32_t *numBytesProcessed) = 0;
+ virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats) = 0; + virtual void resetStats() = 0; protected:
/* implementation packet processing interface */ @@ -155,6 +158,10 @@ public: //!< Get the configuration for the decoder. virtual const Pc *getProtocolConfig() const { return m_config; };
+/* stats block access - derived class must init stats for the block to be returned. */ + virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats); + virtual void resetStats(); /* reset the counts - operates separately from decoder reset. */ + protected:
/* data output functions */ @@ -183,6 +190,14 @@ protected:
const bool checkInit(); // return true if init (configured and at least one output sink attached), false otherwise.
+ /* stats block updates - called by derived protocol specific decoder */ + void statsAddTotalCount(const uint64_t count) { m_stats.channel_total += count; }; + void statsAddUnsyncCount(const uint64_t count) { m_stats.channel_unsynced += count; }; + void statsAddBadSeqCount(const uint32_t count) { m_stats.bad_sequence_errs += count; }; + void statsAddBadHdrCount(const uint32_t count) { m_stats.bad_header_errs += count; }; + void statsInit() { m_stats_init = true; }; /* mark stats as in use */ + + private: /* decode control */ ocsd_datapath_resp_t Reset(const ocsd_trc_index_t index); @@ -195,20 +210,29 @@ private: componentAttachPt<ITrcPktIndexer<Pt>> m_pkt_indexer_i;
bool m_b_is_init; + + /* decode statistics block */ + ocsd_decode_stats_t m_stats; + bool m_stats_init; /*< true if the specific decoder is using the stats */ + };
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name) : TrcPktProcI(component_name), m_config(0), - m_b_is_init(false) + m_b_is_init(false), + m_stats_init(false) { + resetStats(); }
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name, int instIDNum) : TrcPktProcI(component_name, instIDNum), m_config(0), - m_b_is_init(false) + m_b_is_init(false), + m_stats_init(false) { + resetStats(); }
template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::~TrcPktProcBase() @@ -405,6 +429,22 @@ template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::check return m_b_is_init; }
+template<class P,class Pt, class Pc> ocsd_err_t TrcPktProcBase<P, Pt, Pc>::getStatsBlock(ocsd_decode_stats_t **pp_stats) +{ + + *pp_stats = &m_stats; + return m_stats_init ? OCSD_OK : OCSD_ERR_NOT_INIT; +} + +template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::resetStats() +{ + m_stats.version = OCSD_VER_NUM; + m_stats.channel_total = 0; + m_stats.channel_unsynced = 0; + m_stats.bad_header_errs = 0; + m_stats.bad_sequence_errs = 0; +} + /** @}*/
#endif // ARM_TRC_PKT_PROC_BASE_H_INCLUDED diff --git a/decoder/include/opencsd/c_api/opencsd_c_api.h b/decoder/include/opencsd/c_api/opencsd_c_api.h index 25e9487..ebbba87 100644 --- a/decoder/include/opencsd/c_api/opencsd_c_api.h +++ b/decoder/include/opencsd/c_api/opencsd_c_api.h @@ -210,10 +210,36 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h const void *p_context);
+/*! + * Get the stats block for the channel indicated. + * Caller must check p_stats_block->version to esure that the block + * is filled in a compatible manner. + * + * @param handle : Handle to decode tree. + * @param CSID : Configured CoreSight trace ID for the decoder. + * @param p_stats_block: block pointer to set to reference the stats block. + * + * @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned, + * OCSD_ERR_NOTINIT if decoder does not support stats counting. + */ +OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats( const dcd_tree_handle_t handle, + const unsigned char CSID, + ocsd_decode_stats_t **p_stats_block); +
+/*! + * Reset the stats block for the chosens decode channel. + * stats block is reset independently of the decoder reset to allow counts across + * multiple decode runs. + * + * @param handle : Handle to decode tree. + * @param CSID : Configured CoreSight trace ID for the decoder. + * + * @return ocsd_err_t : Library error code - OCSD_OK if successful. + */ +OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats( const dcd_tree_handle_t handle, + const unsigned char CSID);
- - /** @}*/ /*---------------------- Memory Access for traced opcodes ----------------------------------------------------------------------------------*/ /** @name Library Memory Accessor configuration on decode tree. diff --git a/decoder/include/opencsd/ocsd_if_types.h b/decoder/include/opencsd/ocsd_if_types.h index 2550f96..df6339b 100644 --- a/decoder/include/opencsd/ocsd_if_types.h +++ b/decoder/include/opencsd/ocsd_if_types.h @@ -633,6 +633,26 @@ typedef struct _ocsd_swt_info {
/** @}*/
+/** @name Decode statistics + + Contains statistics for bytes decoded by the packet decoder, if statistics are supported. + + Stats block instantiated in the base class - derived protocol specific decoder must initialise and + use as required. + +@{*/ + +typedef struct _ocsd_decode_stats { + uint32_t version; /**< library version number - defines decode stat struct format */ + uint64_t channel_total; /**< total bytes processed for this channel */ + uint64_t channel_unsynced; /**< number of unsynced bytes processed on this channel */ + uint32_t bad_header_errs; /**< number of bad packet header errors */ + uint32_t bad_sequence_errs; /**< number of bad packet sequence errors */ +} ocsd_decode_stats_t; + +/** @}*/ + + /** @}*/ #endif // ARM_OCSD_IF_TYPES_H_INCLUDED
diff --git a/decoder/source/c_api/ocsd_c_api.cpp b/decoder/source/c_api/ocsd_c_api.cpp index 66bfce8..750c847 100644 --- a/decoder/source/c_api/ocsd_c_api.cpp +++ b/decoder/source/c_api/ocsd_c_api.cpp @@ -234,8 +234,24 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h return err; }
-/*** Decode tree set element output */ +OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats(const dcd_tree_handle_t handle, + const unsigned char CSID, + ocsd_decode_stats_t **p_stats_block) +{ + DecodeTree *pDT = static_cast<DecodeTree *>(handle); + + return pDT->getDecoderStats(CSID, p_stats_block); +} + +OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats(const dcd_tree_handle_t handle, + const unsigned char CSID) +{ + DecodeTree *pDT = static_cast<DecodeTree *>(handle);
+ return pDT->resetDecoderStats(CSID); +} + +/*** Decode tree set element output */ OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_outfn(const dcd_tree_handle_t handle, FnTraceElemIn pFn, const void *p_context) {
diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp index b8c27a0..88e675c 100644 --- a/decoder/source/ocsd_dcd_tree.cpp +++ b/decoder/source/ocsd_dcd_tree.cpp @@ -486,6 +486,45 @@ ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID) return err; }
+ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block) +{ + TrcPktProcI *pPktProc = getPktProcI(CSID); + if (!pPktProc) + return OCSD_ERR_INVALID_PARAM_VAL; + return pPktProc->getStatsBlock(p_stats_block); +} + +ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID) +{ + TrcPktProcI *pPktProc = getPktProcI(CSID); + if (!pPktProc) + return OCSD_ERR_INVALID_PARAM_VAL; + pPktProc->resetStats(); + return OCSD_OK; +} + +TrcPktProcI *DecodeTree::getPktProcI(const uint8_t CSID) +{ + TrcPktProcI *pPktProc = 0; + TraceComponent *pComp, *pAssoc; + DecodeTreeElement *pElem = getDecoderElement(CSID); + + if (pElem) + { + pComp = pElem->getDecoderHandle(); + if (pComp) + { + /* if this is a full decoder then the associated component is the packet processor */ + pAssoc = pComp->getAssocComponent(); + if (pAssoc) + pPktProc = dynamic_cast<TrcPktProcI *>(pAssoc); + else + pPktProc = dynamic_cast<TrcPktProcI *>(pComp); + } + } + return pPktProc; +} + DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const { DecodeTreeElement *ret_elem = 0;
Just one comment below, otherwise looks good to me and produces reasonable stats on the files I tested with.
On 9/20/21 11:04 PM, Mike Leach wrote:
Adds a generic statistics API to the packet processor base class to allow protocol specifc decoders to initialise and use to count total bytes processed, unsynced bytes processed, packet header errors and packet sequence errors.
Signed-off-by: Mike Leach mike.leach@linaro.org
decoder/include/common/ocsd_dcd_tree.h | 26 ++++++++++- decoder/include/common/trc_pkt_proc_base.h | 44 ++++++++++++++++++- decoder/include/opencsd/c_api/opencsd_c_api.h | 30 ++++++++++++- decoder/include/opencsd/ocsd_if_types.h | 20 +++++++++ decoder/source/c_api/ocsd_c_api.cpp | 18 +++++++- decoder/source/ocsd_dcd_tree.cpp | 39 ++++++++++++++++ 6 files changed, 171 insertions(+), 6 deletions(-)
diff --git a/decoder/include/common/ocsd_dcd_tree.h b/decoder/include/common/ocsd_dcd_tree.h index e4e74f2..a7297b2 100644 --- a/decoder/include/common/ocsd_dcd_tree.h +++ b/decoder/include/common/ocsd_dcd_tree.h @@ -168,6 +168,30 @@ public: */ ocsd_err_t removeDecoder(const uint8_t CSID);
- /*!
- Get the stats block for the channel indicated.
- Caller must check p_stats_block->version to esure that the block
- is filled in a compatible manner.
- @param CSID : Configured CoreSight trace ID for the decoder.
- @param p_stats_block: block pointer to set to reference the stats block.
- @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned,
OCSD_ERR_NOTINIT if decoder does not support stats counting.
- */
- ocsd_err_t getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block);
- /*!
- Reset the stats block for the chosens decode channel.
- stats block is reset independently of the decoder reset to allow counts across
- multiple decode runs.
- @param handle : Handle to decode tree.
- @param CSID : Configured CoreSight trace ID for the decoder.
- @return ocsd_err_t : Library error code - OCSD_OK if successful.
- */
- ocsd_err_t resetDecoderStats(const uint8_t CSID);
/* get decoder elements currently in use */ @@ -387,7 +411,7 @@ private: void destroyMemAccMapper(); ocsd_err_t initCallbackMemAcc(const ocsd_vaddr_t st_address, const ocsd_vaddr_t en_address, const ocsd_mem_space_acc_t mem_space, void *p_cb_func, bool IDfn, const void *p_context);
- TrcPktProcI *getPktProcI(const uint8_t CSID);
ocsd_dcd_tree_src_t m_dcd_tree_type; diff --git a/decoder/include/common/trc_pkt_proc_base.h b/decoder/include/common/trc_pkt_proc_base.h index 3098a3d..e7c43f5 100644 --- a/decoder/include/common/trc_pkt_proc_base.h +++ b/decoder/include/common/trc_pkt_proc_base.h @@ -43,6 +43,7 @@ #include "trc_component.h" #include "comp_attach_pt_t.h" +#include "opencsd/ocsd_if_version.h" /** @defgroup ocsd_pkt_proc OpenCSD Library : Packet Processors. @brief Classes providing Protocol Packet Processing capability. @@ -76,6 +77,8 @@ public: const uint8_t *pDataBlock, uint32_t *numBytesProcessed) = 0;
- virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats) = 0;
- virtual void resetStats() = 0;
protected: /* implementation packet processing interface */ @@ -155,6 +158,10 @@ public: //!< Get the configuration for the decoder. virtual const Pc *getProtocolConfig() const { return m_config; }; +/* stats block access - derived class must init stats for the block to be returned. */
- virtual ocsd_err_t getStatsBlock(ocsd_decode_stats_t **pp_stats);
- virtual void resetStats(); /* reset the counts - operates separately from decoder reset. */
protected: /* data output functions */ @@ -183,6 +190,14 @@ protected: const bool checkInit(); // return true if init (configured and at least one output sink attached), false otherwise.
- /* stats block updates - called by derived protocol specific decoder */
- void statsAddTotalCount(const uint64_t count) { m_stats.channel_total += count; };
- void statsAddUnsyncCount(const uint64_t count) { m_stats.channel_unsynced += count; };
- void statsAddBadSeqCount(const uint32_t count) { m_stats.bad_sequence_errs += count; };
- void statsAddBadHdrCount(const uint32_t count) { m_stats.bad_header_errs += count; };
- void statsInit() { m_stats_init = true; }; /* mark stats as in use */
private: /* decode control */ ocsd_datapath_resp_t Reset(const ocsd_trc_index_t index); @@ -195,20 +210,29 @@ private: componentAttachPt<ITrcPktIndexer<Pt>> m_pkt_indexer_i; bool m_b_is_init;
- /* decode statistics block */
- ocsd_decode_stats_t m_stats;
- bool m_stats_init; /*< true if the specific decoder is using the stats */
}; template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name) : TrcPktProcI(component_name), m_config(0),
- m_b_is_init(false)
- m_b_is_init(false),
- m_stats_init(false)
{
- resetStats();
} template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::TrcPktProcBase(const char *component_name, int instIDNum) : TrcPktProcI(component_name, instIDNum), m_config(0),
- m_b_is_init(false)
- m_b_is_init(false),
- m_stats_init(false)
{
- resetStats();
} template<class P,class Pt, class Pc> TrcPktProcBase<P, Pt, Pc>::~TrcPktProcBase() @@ -405,6 +429,22 @@ template<class P,class Pt, class Pc> const bool TrcPktProcBase<P, Pt, Pc>::check return m_b_is_init; } +template<class P,class Pt, class Pc> ocsd_err_t TrcPktProcBase<P, Pt, Pc>::getStatsBlock(ocsd_decode_stats_t **pp_stats) +{
- *pp_stats = &m_stats;
- return m_stats_init ? OCSD_OK : OCSD_ERR_NOT_INIT;
+}
+template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::resetStats() +{
- m_stats.version = OCSD_VER_NUM;
- m_stats.channel_total = 0;
- m_stats.channel_unsynced = 0;
- m_stats.bad_header_errs = 0;
- m_stats.bad_sequence_errs = 0;
+}
/** @}*/ #endif // ARM_TRC_PKT_PROC_BASE_H_INCLUDED diff --git a/decoder/include/opencsd/c_api/opencsd_c_api.h b/decoder/include/opencsd/c_api/opencsd_c_api.h index 25e9487..ebbba87 100644 --- a/decoder/include/opencsd/c_api/opencsd_c_api.h +++ b/decoder/include/opencsd/c_api/opencsd_c_api.h @@ -210,10 +210,36 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h const void *p_context); +/*!
- Get the stats block for the channel indicated.
- Caller must check p_stats_block->version to esure that the block
- is filled in a compatible manner.
- @param handle : Handle to decode tree.
- @param CSID : Configured CoreSight trace ID for the decoder.
- @param p_stats_block: block pointer to set to reference the stats block.
- @return ocsd_err_t : Library error code - OCSD_OK if valid block pointer returned,
OCSD_ERR_NOTINIT if decoder does not support stats counting.
- */
+OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats( const dcd_tree_handle_t handle,
const unsigned char CSID,
ocsd_decode_stats_t **p_stats_block);
+/*!
- Reset the stats block for the chosens decode channel.
- stats block is reset independently of the decoder reset to allow counts across
- multiple decode runs.
- @param handle : Handle to decode tree.
- @param CSID : Configured CoreSight trace ID for the decoder.
- @return ocsd_err_t : Library error code - OCSD_OK if successful.
- */
+OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats( const dcd_tree_handle_t handle,
const unsigned char CSID);
/** @}*/ /*---------------------- Memory Access for traced opcodes ----------------------------------------------------------------------------------*/ /** @name Library Memory Accessor configuration on decode tree. diff --git a/decoder/include/opencsd/ocsd_if_types.h b/decoder/include/opencsd/ocsd_if_types.h index 2550f96..df6339b 100644 --- a/decoder/include/opencsd/ocsd_if_types.h +++ b/decoder/include/opencsd/ocsd_if_types.h @@ -633,6 +633,26 @@ typedef struct _ocsd_swt_info { /** @}*/ +/** @name Decode statistics
- Contains statistics for bytes decoded by the packet decoder, if statistics are supported.
- Stats block instantiated in the base class - derived protocol specific decoder must initialise and
- use as required.
+@{*/
+typedef struct _ocsd_decode_stats {
- uint32_t version; /**< library version number - defines decode stat struct format */
I guess the version is there so that we can warn, or error out if the program using this was made for older version. If this is the intent, we would have to update users of this API every time there is a release of OpenCSD. It would probably be better to have a separate versioning that only changes when the stats structure changes.
- uint64_t channel_total; /**< total bytes processed for this channel */
- uint64_t channel_unsynced; /**< number of unsynced bytes processed on this channel */
- uint32_t bad_header_errs; /**< number of bad packet header errors */
- uint32_t bad_sequence_errs; /**< number of bad packet sequence errors */
+} ocsd_decode_stats_t;
+/** @}*/
/** @}*/ #endif // ARM_OCSD_IF_TYPES_H_INCLUDED diff --git a/decoder/source/c_api/ocsd_c_api.cpp b/decoder/source/c_api/ocsd_c_api.cpp index 66bfce8..750c847 100644 --- a/decoder/source/c_api/ocsd_c_api.cpp +++ b/decoder/source/c_api/ocsd_c_api.cpp @@ -234,8 +234,24 @@ OCSD_C_API ocsd_err_t ocsd_dt_attach_packet_callback( const dcd_tree_handle_t h return err; } -/*** Decode tree set element output */ +OCSD_C_API ocsd_err_t ocsd_dt_get_decode_stats(const dcd_tree_handle_t handle,
const unsigned char CSID,
ocsd_decode_stats_t **p_stats_block)
+{
- DecodeTree *pDT = static_cast<DecodeTree *>(handle);
- return pDT->getDecoderStats(CSID, p_stats_block);
+}
+OCSD_C_API ocsd_err_t ocsd_dt_reset_decode_stats(const dcd_tree_handle_t handle,
const unsigned char CSID)
+{
- DecodeTree *pDT = static_cast<DecodeTree *>(handle);
- return pDT->resetDecoderStats(CSID);
+}
+/*** Decode tree set element output */ OCSD_C_API ocsd_err_t ocsd_dt_set_gen_elem_outfn(const dcd_tree_handle_t handle, FnTraceElemIn pFn, const void *p_context) { diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp index b8c27a0..88e675c 100644 --- a/decoder/source/ocsd_dcd_tree.cpp +++ b/decoder/source/ocsd_dcd_tree.cpp @@ -486,6 +486,45 @@ ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID) return err; } +ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block) +{
- TrcPktProcI *pPktProc = getPktProcI(CSID);
- if (!pPktProc)
return OCSD_ERR_INVALID_PARAM_VAL;
- return pPktProc->getStatsBlock(p_stats_block);
+}
+ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID) +{
- TrcPktProcI *pPktProc = getPktProcI(CSID);
- if (!pPktProc)
return OCSD_ERR_INVALID_PARAM_VAL;
- pPktProc->resetStats();
- return OCSD_OK;
+}
+TrcPktProcI *DecodeTree::getPktProcI(const uint8_t CSID) +{
- TrcPktProcI *pPktProc = 0;
- TraceComponent *pComp, *pAssoc;
- DecodeTreeElement *pElem = getDecoderElement(CSID);
- if (pElem)
- {
pComp = pElem->getDecoderHandle();
if (pComp)
{
/* if this is a full decoder then the associated component is the packet processor */
pAssoc = pComp->getAssocComponent();
if (pAssoc)
pPktProc = dynamic_cast<TrcPktProcI *>(pAssoc);
else
pPktProc = dynamic_cast<TrcPktProcI *>(pComp);
}
- }
- return pPktProc;
+}
DecodeTreeElement * DecodeTree::getDecoderElement(const uint8_t CSID) const { DecodeTreeElement *ret_elem = 0;
Update the protocol decoders to used the packet statics API
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp b/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp index 4c92d9e..07b372c 100644 --- a/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp +++ b/decoder/source/etmv4/trc_pkt_proc_etmv4i.cpp @@ -75,6 +75,7 @@ ocsd_err_t TrcPktProcEtmV4I::onProtocolConfig() BuildIPacketTable(); // packet table based on config m_curr_packet.setProtocolVersion(m_config.FullVersion()); m_isInit = true; + statsInit(); return OCSD_OK; }
@@ -156,6 +157,10 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t inde (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR)) { // send invalid packets up the pipe to let the next stage decide what to do. + if (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR) + statsAddBadHdrCount(1); + else + statsAddBadSeqCount(1); m_process_state = SEND_PKT; done = false; } @@ -175,6 +180,7 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::processData( const ocsd_trc_index_t inde } } while (!done);
+ statsAddTotalCount(m_trcIn.processed()); *numBytesProcessed = m_trcIn.processed(); return resp; } @@ -245,8 +251,8 @@ ocsd_datapath_resp_t TrcPktProcEtmV4I::outputUnsyncedRawPacket() { ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
- - outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]); + statsAddUnsyncCount(m_dump_unsynced_bytes); + outputRawPacketToMonitor(m_packet_index,&m_curr_packet,m_dump_unsynced_bytes,&m_currPacketData[0]);
if(!m_sent_notsync_packet) {
Update the trc_pkt_lister and C-API tests to use the stats API. Command line -stats on both programs will activate use of this feature.
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/tests/source/c_api_pkt_print_test.c | 37 ++++++++++++++++++++- decoder/tests/source/trc_pkt_lister.cpp | 37 ++++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/decoder/tests/source/c_api_pkt_print_test.c b/decoder/tests/source/c_api_pkt_print_test.c index caa67e9..01e48cf 100644 --- a/decoder/tests/source/c_api_pkt_print_test.c +++ b/decoder/tests/source/c_api_pkt_print_test.c @@ -119,6 +119,9 @@ static int test_lib_printers = 0; /* test the last error / error code api */ static int test_error_api = 0;
+/* log statistics */ +static int stats = 0; + /* Process command line options - choose the operation to use for the test. */ static int process_cmd_line(int argc, char *argv[]) { @@ -185,6 +188,10 @@ static int process_cmd_line(int argc, char *argv[]) { frame_raw_unpacked = 1; } + else if (strcmp(argv[idx], "-stats") == 0) + { + stats = 1; + } else if (strcmp(argv[idx], "-raw_packed") == 0) { frame_raw_packed = 1; @@ -648,6 +655,7 @@ static ocsd_err_t create_decoder_etmv4(dcd_tree_handle_t dcd_tree_h) { trace_config.reg_traceidr = (uint32_t)test_trc_id_override; } + test_trc_id_override = trace_config.reg_traceidr; /* remember what ID we actually used */
trace_config.reg_idr0 = 0x28000EA1; trace_config.reg_idr1 = 0x4100F403; @@ -683,6 +691,7 @@ static ocsd_err_t create_decoder_etmv3(dcd_tree_handle_t dcd_tree_h) { trace_config_etmv3.reg_trc_id = (uint32_t)test_trc_id_override; } + test_trc_id_override = trace_config_etmv3.reg_trc_id; /* remember what ID we actually used */
/* create an ETMV3 decoder - no context needed as we have a single stream to a single handler. */ return create_generic_decoder(dcd_tree_h,OCSD_BUILTIN_DCD_ETMV3,(void *)&trace_config_etmv3,0); @@ -708,6 +717,7 @@ static ocsd_err_t create_decoder_ptm(dcd_tree_handle_t dcd_tree_h) { trace_config_ptm.reg_trc_id = (uint32_t)test_trc_id_override; } + test_trc_id_override = trace_config_ptm.reg_trc_id; /* remember what ID we actually used */
/* create an PTM decoder - no context needed as we have a single stream to a single handler. */ return create_generic_decoder(dcd_tree_h,OCSD_BUILTIN_DCD_PTM,(void *)&trace_config_ptm,0); @@ -754,6 +764,7 @@ static ocsd_err_t create_decoder_extern(dcd_tree_handle_t dcd_tree_h) { trace_cfg_ext.cs_id = (uint32_t)test_trc_id_override; } + test_trc_id_override = trace_cfg_ext.cs_id;
/* create an external decoder - no context needed as we have a single stream to a single handler. */ return create_generic_decoder(dcd_tree_h, EXT_DCD_NAME, (void *)&trace_cfg_ext, 0); @@ -881,6 +892,28 @@ ocsd_err_t process_data_block(dcd_tree_handle_t dcd_tree_h, int block_index, uin return ret; }
+void print_statistics(dcd_tree_handle_t dcdtree_handle) +{ + ocsd_decode_stats_t *p_stats = 0; + ocsd_err_t err; + + sprintf(packet_str, "\nReading packet decoder statistics for ID:0x%02x...\n", test_trc_id_override); + ocsd_def_errlog_msgout(packet_str); + + err = ocsd_dt_get_decode_stats(dcdtree_handle, test_trc_id_override, &p_stats); + if (!err && p_stats) + { + sprintf(packet_str, "Total Bytes %lld; Unsynced Bytes: %lld\nBad Header Errors: %d; Bad sequence errors: %d\n", p_stats->channel_total, + p_stats->channel_unsynced, p_stats->bad_header_errs, p_stats->bad_sequence_errs); + ocsd_dt_reset_decode_stats(dcdtree_handle, test_trc_id_override); + } + else + { + sprintf(packet_str, "Not available for this ID.\n"); + } + ocsd_def_errlog_msgout(packet_str); +} + int process_trace_data(FILE *pf) { ocsd_err_t ret = OCSD_OK; @@ -943,7 +976,9 @@ int process_trace_data(FILE *pf) if(ret == OCSD_OK) ocsd_dt_process_data(dcdtree_handle, OCSD_OP_EOT, 0,0,NULL,NULL);
- + if (stats) { + print_statistics(dcdtree_handle); + } /* shut down the mem acc CB if in use. */ if(using_mem_acc_cb) { diff --git a/decoder/tests/source/trc_pkt_lister.cpp b/decoder/tests/source/trc_pkt_lister.cpp index 6c8614e..2a54905 100644 --- a/decoder/tests/source/trc_pkt_lister.cpp +++ b/decoder/tests/source/trc_pkt_lister.cpp @@ -74,6 +74,7 @@ static bool dstream_format = false; static bool tpiu_format = false; static bool has_hsync = false; static bool src_addr_n = false; +static bool stats = false;
int main(int argc, char* argv[]) { @@ -195,6 +196,7 @@ void print_help() oss << "-o_raw_unpacked Output raw unpacked trace data per ID\n"; oss << "-test_waits <N> Force wait from packet printer for N packets - test the wait/flush mechanisms for the decoder\n"; oss << "-src_addr_n ETE protocol: Split source address ranges on N atoms\n"; + oss << "-stats Output packet processing statistics (if available).\n"; oss << "\nOutput:\n"; oss << " Setting any of these options cancels the default output to file & stdout,\n using _only_ the options supplied.\n\n"; oss << "-logstdout Output to stdout -> console.\n"; @@ -396,6 +398,10 @@ bool process_cmd_line_opts(int argc, char* argv[]) { src_addr_n = true; } + else if (strcmp(argv[optIdx], "-stats") == 0) + { + stats = true; + } else if((strcmp(argv[optIdx], "-help") == 0) || (strcmp(argv[optIdx], "--help") == 0) || (strcmp(argv[optIdx], "-h") == 0)) { print_help(); @@ -536,6 +542,34 @@ void ConfigureFrameDeMux(DecodeTree *dcd_tree, RawFramePrinter **framePrinter) } }
+void PrintDecodeStats(DecodeTree *dcd_tree) +{ + uint8_t elemID; + std::ostringstream oss; + ocsd_decode_stats_t *pStats = 0; + ocsd_err_t err; + + oss << "\nReading packet decoder statistics....\n\n"; + logger.LogMsg(oss.str()); + + DecodeTreeElement *pElement = dcd_tree->getFirstElement(elemID); + while (pElement) + { + oss.str(""); + err = dcd_tree->getDecoderStats(elemID, &pStats); + if (!err && pStats) + { + oss << "Decode stats ID 0x" << std::hex << (uint32_t)elemID << "\n"; + oss << "Total Bytes: " << std::dec << pStats->channel_total << "; Unsynced Bytes: " << std::dec << pStats->channel_unsynced << "\n"; + oss << "Bad Header Errors: " << std::dec << pStats->bad_header_errs << "; Bad Sequence Errors: " << std::dec << pStats->bad_sequence_errs << "\n"; + } + else + oss << "Decode stats unavailable on Trace ID 0x" << std::hex << (uint32_t)elemID << "\n"; + logger.LogMsg(oss.str()); + pElement = dcd_tree->getNextElement(elemID); + } +} + void ListTracePackets(ocsdDefaultErrorLogger &err_logger, SnapShotReader &reader, const std::string &trace_buffer_name) { CreateDcdTreeFromSnapShot tree_creator; @@ -679,7 +713,8 @@ void ListTracePackets(ocsdDefaultErrorLogger &err_logger, SnapShotReader &reader std::ostringstream oss; oss << "Trace Packet Lister : Trace buffer done, processed " << trace_index << " bytes.\n"; logger.LogMsg(oss.str()); - + if (stats) + PrintDecodeStats(dcd_tree); } else {
Moved static vars into .cpp file from .h to remove warnings when including .h file in client code.
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/tests/snapshot_parser_lib/include/snapshot_parser.h | 6 +++--- .../tests/snapshot_parser_lib/source/snapshot_parser.cpp | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/decoder/tests/snapshot_parser_lib/include/snapshot_parser.h b/decoder/tests/snapshot_parser_lib/include/snapshot_parser.h index 8b91712..9e5b371 100644 --- a/decoder/tests/snapshot_parser_lib/include/snapshot_parser.h +++ b/decoder/tests/snapshot_parser_lib/include/snapshot_parser.h @@ -135,9 +135,9 @@ namespace Parser std::vectorstd::string GetBufferNameList(ParsedTrace &metadata);
- static ITraceErrorLog *s_pErrorLogger = 0; - static ocsd_hndl_err_log_t s_errlog_handle = 0; - static bool s_verbose_logging = true; + //static ITraceErrorLog *s_pErrorLogger = 0; + //static ocsd_hndl_err_log_t s_errlog_handle = 0; + //static bool s_verbose_logging = true;
void SetIErrorLogger(ITraceErrorLog *i_err_log); void SetVerboseLogging(bool verbose); diff --git a/decoder/tests/snapshot_parser_lib/source/snapshot_parser.cpp b/decoder/tests/snapshot_parser_lib/source/snapshot_parser.cpp index 6e62d1e..4570700 100644 --- a/decoder/tests/snapshot_parser_lib/source/snapshot_parser.cpp +++ b/decoder/tests/snapshot_parser_lib/source/snapshot_parser.cpp @@ -49,6 +49,10 @@ using namespace Parser;
#include "opencsd.h"
+static ITraceErrorLog *s_pErrorLogger = 0; +static ocsd_hndl_err_log_t s_errlog_handle = 0; +static bool s_verbose_logging = true; + /************************************************************************* * Note, this file handles the parsring of the general (device specific) * ini file and the (much smaller) device_list file
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/tests/source/mem_buff_demo.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/decoder/tests/source/mem_buff_demo.cpp b/decoder/tests/source/mem_buff_demo.cpp index cacc227..052870f 100644 --- a/decoder/tests/source/mem_buff_demo.cpp +++ b/decoder/tests/source/mem_buff_demo.cpp @@ -126,6 +126,7 @@ static int initDataBuffers() FILE *fp; std::string filename; long size; + size_t bytes_read;
/* the file names to create the data buffers */ #ifdef _WIN32 @@ -158,8 +159,10 @@ static int initDataBuffers() return OCSD_ERR_MEM; } rewind(fp); - fread(input_trace_data, 1, input_trace_data_size, fp); + bytes_read = fread(input_trace_data, 1, input_trace_data_size, fp); fclose(fp); + if (bytes_read < (size_t)input_trace_data_size) + return OCSD_ERR_FILE_ERROR;
/* load up a memory image */ filename = default_base_snapshot_path; @@ -178,8 +181,10 @@ static int initDataBuffers() return OCSD_ERR_MEM; } rewind(fp); - fread(program_image_buffer, 1, program_image_size, fp); + bytes_read = fread(program_image_buffer, 1, program_image_size, fp); fclose(fp); + if (bytes_read < (size_t)program_image_size) + return OCSD_ERR_FILE_ERROR; program_image_address = mem_dump_address; return OCSD_OK; }
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/tests/source/c_api_pkt_print_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/decoder/tests/source/c_api_pkt_print_test.c b/decoder/tests/source/c_api_pkt_print_test.c index 01e48cf..fa9f48d 100644 --- a/decoder/tests/source/c_api_pkt_print_test.c +++ b/decoder/tests/source/c_api_pkt_print_test.c @@ -903,7 +903,7 @@ void print_statistics(dcd_tree_handle_t dcdtree_handle) err = ocsd_dt_get_decode_stats(dcdtree_handle, test_trc_id_override, &p_stats); if (!err && p_stats) { - sprintf(packet_str, "Total Bytes %lld; Unsynced Bytes: %lld\nBad Header Errors: %d; Bad sequence errors: %d\n", p_stats->channel_total, + sprintf(packet_str, "Total Bytes %ld; Unsynced Bytes: %ld\nBad Header Errors: %d; Bad sequence errors: %d\n", p_stats->channel_total, p_stats->channel_unsynced, p_stats->bad_header_errs, p_stats->bad_sequence_errs); ocsd_dt_reset_decode_stats(dcdtree_handle, test_trc_id_override); } @@ -1042,7 +1042,7 @@ int test_err_api() ocsd_err_str(ret, err_buffer, ERR_BUFFER_SIZE); printf("testing error API for code %d: %s\n", ret, err_buffer); err_test = ocsd_get_last_err(&err_index, &cs_id, err_buffer, ERR_BUFFER_SIZE); - printf("get last error:\ncode = 0x%02x; trace index %ld; cs_id 0x%02x;\nstring: %s\n", err_test, err_index, cs_id, err_buffer); + printf("get last error:\ncode = 0x%02x; trace index %d; cs_id 0x%02x;\nstring: %s\n", err_test, err_index, cs_id, err_buffer);
} return ret;
Updates to the statistics block to allow for the collection of CoreSight frame demultiplexor stats.
This is a global stats block applying to all channels when CoreSight framing is in use.
The same channel stats block call is used, with the global block appearing identical for all channels.
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/include/common/ocsd_dcd_tree.h | 3 + .../include/common/trc_frame_deformatter.h | 4 ++ decoder/include/common/trc_pkt_proc_base.h | 3 + decoder/include/opencsd/ocsd_if_types.h | 27 +++++++++ decoder/source/ocsd_dcd_tree.cpp | 27 ++++++++- decoder/source/trc_frame_deformatter.cpp | 59 ++++++++++++++++++- decoder/source/trc_frame_deformatter_impl.h | 14 ++++- 7 files changed, 132 insertions(+), 5 deletions(-)
diff --git a/decoder/include/common/ocsd_dcd_tree.h b/decoder/include/common/ocsd_dcd_tree.h index a7297b2..b1c3dc6 100644 --- a/decoder/include/common/ocsd_dcd_tree.h +++ b/decoder/include/common/ocsd_dcd_tree.h @@ -441,6 +441,9 @@ private:
/**! default instruction decoder */ static TrcIDecode s_instruction_decoder; + + /**! demux stats block */ + ocsd_demux_stats_t m_demux_stats; };
/** @}*/ diff --git a/decoder/include/common/trc_frame_deformatter.h b/decoder/include/common/trc_frame_deformatter.h index e4297a4..b6476a2 100644 --- a/decoder/include/common/trc_frame_deformatter.h +++ b/decoder/include/common/trc_frame_deformatter.h @@ -85,9 +85,13 @@ public: ocsd_datapath_resp_t Reset(); /* reset the decode to the start state, drop partial data - propogate to attached components */ ocsd_datapath_resp_t Flush(); /* flush existing data if possible, retain state - propogate to attached components */
+ /* demux stats */ + void SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock); + private: TraceFmtDcdImpl *m_pDecoder; int m_instNum; + };
/** @}*/ diff --git a/decoder/include/common/trc_pkt_proc_base.h b/decoder/include/common/trc_pkt_proc_base.h index e7c43f5..5570781 100644 --- a/decoder/include/common/trc_pkt_proc_base.h +++ b/decoder/include/common/trc_pkt_proc_base.h @@ -443,6 +443,9 @@ template<class P,class Pt, class Pc> void TrcPktProcBase<P, Pt, Pc>::resetStats( m_stats.channel_unsynced = 0; m_stats.bad_header_errs = 0; m_stats.bad_sequence_errs = 0; + m_stats.demux.frame_bytes = 0; + m_stats.demux.no_id_bytes = 0; + m_stats.demux.valid_id_bytes = 0; }
/** @}*/ diff --git a/decoder/include/opencsd/ocsd_if_types.h b/decoder/include/opencsd/ocsd_if_types.h index df6339b..8a930b6 100644 --- a/decoder/include/opencsd/ocsd_if_types.h +++ b/decoder/include/opencsd/ocsd_if_types.h @@ -633,6 +633,25 @@ typedef struct _ocsd_swt_info {
/** @}*/
+/** @name Demux Statistics + + Contains statistics for the CoreSight frame demultiplexor. + + Counts total bytes sent to decoders registered against a trace ID, bytes in the input stream that are + associated with a trace ID that has no registered decoder, and frame bytes that are not trace data, but + are used to decode the frames - ID bytes, sync bytes etc. +@{*/ + +typedef struct _ocsd_demux_stats { + uint64_t valid_id_bytes; /**< number of bytes associated with an ID that has a registered decoder */ + uint64_t no_id_bytes; /**< number of bytes associated with an ID that has no decoder */ + uint64_t reserved_id_bytes; /**< number of bytes associated with reserved IDs */ + uint64_t unknown_id_bytes; /**< bytes processed before ID seen in input frames */ + uint64_t frame_bytes; /**< number of non-data bytes used for frame de-mux - ID bytes, sync etc */ +} ocsd_demux_stats_t; + +/** @}*/ + /** @name Decode statistics
Contains statistics for bytes decoded by the packet decoder, if statistics are supported. @@ -640,14 +659,22 @@ typedef struct _ocsd_swt_info { Stats block instantiated in the base class - derived protocol specific decoder must initialise and use as required.
+ The single channel block contains the stats for the requested channel via the API call. + + The global demux block contains the totals for all channels and non-data bytes used in CoreSight + frame demux. This block will show identical data for every requested channel via the API. + @{*/
typedef struct _ocsd_decode_stats { uint32_t version; /**< library version number - defines decode stat struct format */ + /* single channel block */ uint64_t channel_total; /**< total bytes processed for this channel */ uint64_t channel_unsynced; /**< number of unsynced bytes processed on this channel */ uint32_t bad_header_errs; /**< number of bad packet header errors */ uint32_t bad_sequence_errs; /**< number of bad packet sequence errors */ + + ocsd_demux_stats_t demux; /**< global demux stats block */ } ocsd_decode_stats_t;
/** @}*/ diff --git a/decoder/source/ocsd_dcd_tree.cpp b/decoder/source/ocsd_dcd_tree.cpp index 88e675c..b423f7d 100644 --- a/decoder/source/ocsd_dcd_tree.cpp +++ b/decoder/source/ocsd_dcd_tree.cpp @@ -101,6 +101,13 @@ DecodeTree::DecodeTree() : { for(int i = 0; i < 0x80; i++) m_decode_elements[i] = 0; + + // reset the global demux stats. + m_demux_stats.frame_bytes = 0; + m_demux_stats.no_id_bytes = 0; + m_demux_stats.valid_id_bytes = 0; + m_demux_stats.unknown_id_bytes = 0; + m_demux_stats.reserved_id_bytes = 0; }
DecodeTree::~DecodeTree() @@ -488,10 +495,20 @@ ocsd_err_t DecodeTree::removeDecoder(const uint8_t CSID)
ocsd_err_t DecodeTree::getDecoderStats(const uint8_t CSID, ocsd_decode_stats_t **p_stats_block) { + ocsd_err_t err = OCSD_OK; TrcPktProcI *pPktProc = getPktProcI(CSID); if (!pPktProc) return OCSD_ERR_INVALID_PARAM_VAL; - return pPktProc->getStatsBlock(p_stats_block); + err = pPktProc->getStatsBlock(p_stats_block); + if (err == OCSD_OK) { + // copy in the global demux stats. + (*p_stats_block)->demux.frame_bytes = m_demux_stats.frame_bytes; + (*p_stats_block)->demux.no_id_bytes = m_demux_stats.no_id_bytes; + (*p_stats_block)->demux.valid_id_bytes = m_demux_stats.valid_id_bytes; + (*p_stats_block)->demux.unknown_id_bytes = m_demux_stats.unknown_id_bytes; + (*p_stats_block)->demux.reserved_id_bytes = m_demux_stats.reserved_id_bytes; + } + return err; }
ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID) @@ -500,6 +517,13 @@ ocsd_err_t DecodeTree::resetDecoderStats(const uint8_t CSID) if (!pPktProc) return OCSD_ERR_INVALID_PARAM_VAL; pPktProc->resetStats(); + + // reset the global demux stats. + m_demux_stats.frame_bytes = 0; + m_demux_stats.no_id_bytes = 0; + m_demux_stats.valid_id_bytes = 0; + m_demux_stats.unknown_id_bytes = 0; + m_demux_stats.reserved_id_bytes = 0; return OCSD_OK; }
@@ -577,6 +601,7 @@ bool DecodeTree::initialise(const ocsd_dcd_tree_src_t type, uint32_t formatterCf m_frame_deformatter_root->Configure(formatterCfgFlags); m_frame_deformatter_root->getErrLogAttachPt()->attach(DecodeTree::s_i_error_logger); m_i_decoder_root = dynamic_cast<ITrcDataIn*>(m_frame_deformatter_root); + m_frame_deformatter_root->SetDemuxStatsBlock(&m_demux_stats); } else initOK = false; diff --git a/decoder/source/trc_frame_deformatter.cpp b/decoder/source/trc_frame_deformatter.cpp index 4d46854..4f7c403 100644 --- a/decoder/source/trc_frame_deformatter.cpp +++ b/decoder/source/trc_frame_deformatter.cpp @@ -54,7 +54,8 @@ TraceFmtDcdImpl::TraceFmtDcdImpl() : TraceComponent(DEFORMATTER_NAME), m_use_force_sync(false), m_alignment(16), // assume frame aligned data as default. m_b_output_packed_raw(false), - m_b_output_unpacked_raw(false) + m_b_output_unpacked_raw(false), + m_pStatsBlock(0)
{ resetStateParams(); @@ -595,6 +596,9 @@ bool TraceFmtDcdImpl::extractFrame() // update index past the processed data m_trc_curr_idx += total_processed;
+ // update any none trace data byte stats + addToFrameStats((uint64_t)(f_sync_bytes + h_sync_bytes)); + return cont_process; }
@@ -604,6 +608,7 @@ bool TraceFmtDcdImpl::unpackFrame() uint8_t frameFlagBit = 0x1; uint8_t newSrcID = OCSD_BAD_CS_SRC_ID; bool PrevIDandIDChange = false; + uint64_t noneDataBytes = 0;
// init output processing m_out_data_idx = 0; @@ -650,6 +655,7 @@ bool TraceFmtDcdImpl::unpackFrame()
/// TBD - ID indexing in here. } + noneDataBytes++; } else // it's just data @@ -671,6 +677,7 @@ bool TraceFmtDcdImpl::unpackFrame() { // no matter if change or not, no associated data in byte 15 anyway so just set. m_curr_src_ID = (m_ex_frm_data[14] >> 1) & 0x7f; + noneDataBytes++; } // it's data else @@ -678,6 +685,9 @@ bool TraceFmtDcdImpl::unpackFrame() m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[14] | ((frameFlagBit & m_ex_frm_data[15]) ? 0x1 : 0x0); } m_ex_frm_n_bytes = 0; // mark frame as empty; + + noneDataBytes++; // byte 15 is always non-data. + addToFrameStats(noneDataBytes); // update the non data byte stats. return true; }
@@ -716,6 +726,8 @@ bool TraceFmtDcdImpl::outputFrame() m_out_data[m_out_processed].data + m_out_data[m_out_processed].used, &bytes_used));
+ addToIDStats((uint64_t)bytes_used); + if(!dataPathCont()) { cont_processing = false; @@ -739,7 +751,12 @@ bool TraceFmtDcdImpl::outputFrame() m_out_data[m_out_processed].valid, m_out_data[m_out_processed].data, m_out_data[m_out_processed].id); - } + } + + if (isReservedID(m_out_data[m_out_processed].id)) + addToReservedIDStats((uint64_t)m_out_data[m_out_processed].valid); + else + addToNoIDStats((uint64_t)m_out_data[m_out_processed].valid); m_out_processed++; // skip past this data. } } @@ -754,13 +771,44 @@ bool TraceFmtDcdImpl::outputFrame() m_out_data[m_out_processed].valid, m_out_data[m_out_processed].data, m_out_data[m_out_processed].id); - } + } + addToUnknownIDStats((uint64_t)m_out_data[m_out_processed].valid); m_out_processed++; // skip past this data. } } return cont_processing; } + +void TraceFmtDcdImpl::addToIDStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->valid_id_bytes += val; +} + +void TraceFmtDcdImpl::addToNoIDStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->no_id_bytes += val; +}
+void TraceFmtDcdImpl::addToFrameStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->frame_bytes += val; +} + +void TraceFmtDcdImpl::addToUnknownIDStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->unknown_id_bytes += val; +} + +void TraceFmtDcdImpl::addToReservedIDStats(uint64_t val) +{ + if (m_pStatsBlock) + m_pStatsBlock->reserved_id_bytes += val; +} + /***************************************************************/ /* interface */ /***************************************************************/ @@ -865,5 +913,10 @@ ocsd_datapath_resp_t TraceFormatterFrameDecoder::Flush() return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Flush(); }
+void TraceFormatterFrameDecoder::SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock) +{ + if (m_pDecoder) + m_pDecoder->SetDemuxStatsBlock(pStatsBlock); +}
/* End of File trc_frame_deformatter.cpp */ diff --git a/decoder/source/trc_frame_deformatter_impl.h b/decoder/source/trc_frame_deformatter_impl.h index e1fc17a..8d19bdb 100644 --- a/decoder/source/trc_frame_deformatter_impl.h +++ b/decoder/source/trc_frame_deformatter_impl.h @@ -75,6 +75,8 @@ private: ocsd_err_t DecodeConfigure(uint32_t flags); ocsd_err_t SetForcedSyncIndex(ocsd_trc_index_t index, bool bSet);
+ void SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock) { m_pStatsBlock = pStatsBlock; }; + private: ocsd_datapath_resp_t executeNoneDataOpAllIDs(ocsd_datapath_op_t op, const ocsd_trc_index_t index = 0); ocsd_datapath_resp_t processTraceData(const ocsd_trc_index_t index, @@ -117,8 +119,16 @@ private:
friend class TraceFormatterFrameDecoder;
- // attachment points + // stats updates + void addToIDStats(uint64_t val); + void addToNoIDStats(uint64_t val); + void addToFrameStats(uint64_t val); + void addToUnknownIDStats(uint64_t val); + void addToReservedIDStats(uint64_t val); + + bool isReservedID(uint8_t ID) { return ((ID == 0) || (ID >= 0x70)); };
+ // attachment points componentAttachPt<ITrcDataIn> m_IDStreams[128]; componentAttachPt<ITrcRawFrameIn> m_RawTraceFrame;
@@ -159,6 +169,8 @@ private: bool m_b_output_unpacked_raw;
bool m_raw_chan_enable[128]; + + ocsd_demux_stats_t *m_pStatsBlock; };
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/tests/source/trc_pkt_lister.cpp | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/decoder/tests/source/trc_pkt_lister.cpp b/decoder/tests/source/trc_pkt_lister.cpp index 2a54905..9760351 100644 --- a/decoder/tests/source/trc_pkt_lister.cpp +++ b/decoder/tests/source/trc_pkt_lister.cpp @@ -548,6 +548,8 @@ void PrintDecodeStats(DecodeTree *dcd_tree) std::ostringstream oss; ocsd_decode_stats_t *pStats = 0; ocsd_err_t err; + bool gotDemuxStats = false; + ocsd_demux_stats_t demux_stats;
oss << "\nReading packet decoder statistics....\n\n"; logger.LogMsg(oss.str()); @@ -562,12 +564,36 @@ void PrintDecodeStats(DecodeTree *dcd_tree) oss << "Decode stats ID 0x" << std::hex << (uint32_t)elemID << "\n"; oss << "Total Bytes: " << std::dec << pStats->channel_total << "; Unsynced Bytes: " << std::dec << pStats->channel_unsynced << "\n"; oss << "Bad Header Errors: " << std::dec << pStats->bad_header_errs << "; Bad Sequence Errors: " << std::dec << pStats->bad_sequence_errs << "\n"; + + // demux stats same for all IDs - grab them at the first opportunity.. + if (!gotDemuxStats) { + memcpy(&demux_stats, &pStats->demux, sizeof(ocsd_demux_stats_t)); + gotDemuxStats = true; + } + } else oss << "Decode stats unavailable on Trace ID 0x" << std::hex << (uint32_t)elemID << "\n"; + + logger.LogMsg(oss.str()); pElement = dcd_tree->getNextElement(elemID); } + + // if we have copied over the stats and there is at least 1 frame byte (impossible for there to be 0 if demuxing) + if (gotDemuxStats && demux_stats.frame_bytes) { + uint64_t total = demux_stats.valid_id_bytes + demux_stats.no_id_bytes + demux_stats.unknown_id_bytes + + demux_stats.reserved_id_bytes + demux_stats.frame_bytes; + oss.str(""); + oss << "\nFrame Demux Stats\n"; + oss << "Trace data bytes sent to registered ID decoders: " << std::dec << demux_stats.valid_id_bytes << "\n"; + oss << "Trace data bytes without registered ID decoders: " << std::dec << demux_stats.no_id_bytes << "\n"; + oss << "Trace data bytes with unknown ID: " << std::dec << demux_stats.unknown_id_bytes << "\n"; + oss << "Trace data bytes with reserved ID: " << std::dec << demux_stats.reserved_id_bytes << "\n"; + oss << "Frame demux bytes, ID bytes and sync bytes: " << std::dec << demux_stats.frame_bytes << "\n"; + oss << "Total bytes processed by frame demux: " << std::dec << total << "\n\n"; + logger.LogMsg(oss.str()); + } }
void ListTracePackets(ocsdDefaultErrorLogger &err_logger, SnapShotReader &reader, const std::string &trace_buffer_name)
Allow test scripts to use additional command line options when running the tests.
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/tests/run_pkt_decode_single.bash | 7 ++++--- decoder/tests/run_pkt_decode_tests-ete.bash | 11 +++++++---- decoder/tests/run_pkt_decode_tests.bash | 17 ++++++++++------- 3 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/decoder/tests/run_pkt_decode_single.bash b/decoder/tests/run_pkt_decode_single.bash index b4ca58f..3025240 100755 --- a/decoder/tests/run_pkt_decode_single.bash +++ b/decoder/tests/run_pkt_decode_single.bash @@ -34,10 +34,10 @@ ################################################################################# # Usage options:- # * default: run test on binary + libs in ./bin/linux64/rel -# run_pkt_decode_tests.bash <test> +# run_pkt_decode_tests.bash <test> <options> # # * use installed opencsd libraries & program -# run_pkt_decode_tests.bash use-installed <test> +# run_pkt_decode_tests.bash use-installed <test> <options> # #
@@ -56,6 +56,7 @@ fi
if [ "$1" != "" ]; then TEST=$1 + shift fi
echo "Running trc_pkt_lister on single snapshot ${TEST}" @@ -70,7 +71,7 @@ else fi
# === test the decode set === -${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/${TEST}" -decode -logfilename "${OUT_DIR}/${TEST}.ppl" +${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/${TEST}" $@ -decode -logfilename "${OUT_DIR}/${TEST}.ppl" echo "Done : Return $?"
diff --git a/decoder/tests/run_pkt_decode_tests-ete.bash b/decoder/tests/run_pkt_decode_tests-ete.bash index c00631e..1b8c762 100755 --- a/decoder/tests/run_pkt_decode_tests-ete.bash +++ b/decoder/tests/run_pkt_decode_tests-ete.bash @@ -84,8 +84,11 @@ mkdir -p ${OUT_DIR}
if [ "$1" == "use-installed" ]; then BIN_DIR="" -elif [ "$1" != "" ]; then - BIN_DIR=$1 + shift +elif [ "$1" == "-bindir" ]; then + BIN_DIR=$2 + shift + shift fi
echo "Tests using BIN_DIR = ${BIN_DIR}" @@ -99,13 +102,13 @@ fi for test_dir in "${test_dirs_decode[@]}" do echo "Testing $test_dir..." - ${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/$test_dir" -decode -logfilename "${OUT_DIR}/$test_dir.ppl" + ${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/$test_dir" $@ -decode -logfilename "${OUT_DIR}/$test_dir.ppl" echo "Done : Return $?" done
for test_dir_n in "${test_dirs_decode_src_addr_opt[@]}" do echo "Testing with -src_addr_n $test_dir_n..." - ${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/$test_dir_n" -decode -src_addr_n -logfilename "${OUT_DIR}/${test_dir_n}_src_addr_N.ppl" + ${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/$test_dir_n" $@ -decode -src_addr_n -logfilename "${OUT_DIR}/${test_dir_n}_src_addr_N.ppl" echo "Done : Return $?" done diff --git a/decoder/tests/run_pkt_decode_tests.bash b/decoder/tests/run_pkt_decode_tests.bash index d9b7c8a..9ecb034 100755 --- a/decoder/tests/run_pkt_decode_tests.bash +++ b/decoder/tests/run_pkt_decode_tests.bash @@ -40,10 +40,10 @@ # run_pkt_decode_tests.bash # # * use installed opencsd libraries & program -# run_pkt_decode_tests.bash use-installed +# run_pkt_decode_tests.bash use-installed <options> # # * use supplied path for binary + libs (must have trailing /) -# run_pkt_decode_tests.bash <custom>/<path>/ +# run_pkt_decode_tests.bash -bindir <custom>/<path>/ <options> #
OUT_DIR=./results @@ -75,8 +75,11 @@ mkdir -p ${OUT_DIR}
if [ "$1" == "use-installed" ]; then BIN_DIR="" -elif [ "$1" != "" ]; then - BIN_DIR=$1 + shift +elif [ "$1" == "-bindir" ]; then + BIN_DIR=$2 + shift + shift fi
echo "Tests using BIN_DIR = ${BIN_DIR}" @@ -90,17 +93,17 @@ fi for test_dir in "${test_dirs_decode[@]}" do echo "Testing $test_dir..." - ${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/$test_dir" -decode -logfilename "${OUT_DIR}/$test_dir.ppl" + ${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/$test_dir" $@ -decode -logfilename "${OUT_DIR}/$test_dir.ppl" echo "Done : Return $?" done
# === test a packet only example === echo "Testing init-short-addr..." -${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/init-short-addr" -pkt_mon -logfilename "${OUT_DIR}/init-short-addr.ppl" +${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/init-short-addr" $@ -pkt_mon -logfilename "${OUT_DIR}/init-short-addr.ppl"
# === test the TPIU deformatter === echo "Testing a55-test-tpiu..." -${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/a55-test-tpiu" -dstream_format -o_raw_packed -o_raw_unpacked -logfilename "${OUT_DIR}/a55-test-tpiu.ppl" +${BIN_DIR}trc_pkt_lister -ss_dir "${SNAPSHOT_DIR}/a55-test-tpiu" $@ -dstream_format -o_raw_packed -o_raw_unpacked -logfilename "${OUT_DIR}/a55-test-tpiu.ppl" echo "Done : Return $?"
# === test the C-API lib - this test prog is not installed ===
From: Yi Kong yikong@google.com
Variable LimitMask is set but unused.
Found by Clang -Wunused-but-set-variable warning.
Reported-by: Yi Kong yikong@google.com --- decoder/source/trc_printable_elem.cpp | 2 -- 1 file changed, 2 deletions(-)
diff --git a/decoder/source/trc_printable_elem.cpp b/decoder/source/trc_printable_elem.cpp index 88c7bb2..2b60c03 100644 --- a/decoder/source/trc_printable_elem.cpp +++ b/decoder/source/trc_printable_elem.cpp @@ -52,8 +52,6 @@ void trcPrintableElem::getValStr(std::string &valStr, const int valTotalBitSize,
assert((valTotalBitSize >= 4) && (valTotalBitSize <= 64));
- uint64_t LimitMask = ~0ULL; - LimitMask >>= 64-valTotalBitSize; valStr = "0x";
if(asHex)
From: James Clark james.clark@arm.com
This printf is the only occurrence outside of the tests. When using OpenCSD with perf in TUI mode, printfs can corrupt the UI and make perf's own error messages hard to see. The proper way to print would be pr_warning() or ui__warning() which aren't available here.
I don't see an easy way of making this work, and I don't think this printf is that useful either, so remove it.
Signed-off-by: James Clark james.clark@arm.com --- decoder/source/trc_frame_deformatter.cpp | 1 - 1 file changed, 1 deletion(-)
diff --git a/decoder/source/trc_frame_deformatter.cpp b/decoder/source/trc_frame_deformatter.cpp index 4f7c403..dc12e3f 100644 --- a/decoder/source/trc_frame_deformatter.cpp +++ b/decoder/source/trc_frame_deformatter.cpp @@ -437,7 +437,6 @@ int TraceFmtDcdImpl::checkForResetFSyncPatterns()
if (num_fsyncs) { - printf("Frame deformatter: Found %d FSYNCS\n",num_fsyncs); if ((num_fsyncs % 4) == 0) { // reset the upstream decoders
Signed-off-by: Mike Leach mike.leach@linaro.org --- README.md | 9 ++++++++- decoder/include/opencsd/ocsd_if_version.h | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md index 1647112..0fe4597 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Releases will appear on the master branch in the git repository with an appropri CoreSight Trace Component Support. ----------------------------------
-_Current Version 1.1.1_ +_Current Version 1.2.0_
### Current support:
@@ -250,6 +250,13 @@ Version and Modification Information - _Version 1.1.1_: - __Bugfix__: Fix include and install for ETE decoder headers.
+- _Version 1.2.0_: + - __Update__: Add API for counting packet decode statistics, and Frame debmux statistics. + - __Update__: Update test scripts to allow additional command line options to be passed. + - __Bugfix__: Fix various build warnings. + - __Bugfix__: Remove unused variable (github issue #39 from Yi Kong) + - __Bugfix__: Remove noisy printf (James Clark) + Licence Information ===================
diff --git a/decoder/include/opencsd/ocsd_if_version.h b/decoder/include/opencsd/ocsd_if_version.h index ea2b239..d6f5849 100644 --- a/decoder/include/opencsd/ocsd_if_version.h +++ b/decoder/include/opencsd/ocsd_if_version.h @@ -43,8 +43,8 @@ /** @name Library Versioning @{*/ #define OCSD_VER_MAJOR 0x1 /**< Library Major Version */ -#define OCSD_VER_MINOR 0x1 /**< Library Minor Version */ -#define OCSD_VER_PATCH 0x1 /**< Library Patch Version */ +#define OCSD_VER_MINOR 0x2 /**< Library Minor Version */ +#define OCSD_VER_PATCH 0x0 /**< Library Patch Version */
/** Library version number - MMMMnnpp format. MMMM = major version, @@ -53,7 +53,7 @@ */ #define OCSD_VER_NUM ((OCSD_VER_MAJOR << 16) | (OCSD_VER_MINOR << 8) | OCSD_VER_PATCH)
-#define OCSD_VER_STRING "1.1.1" /**< Library Version string */ +#define OCSD_VER_STRING "1.2.0" /**< Library Version string */ #define OCSD_LIB_NAME "OpenCSD Library" /**< Library name string */ #define OCSD_LIB_SHORT_NAME "OCSD" /**< Library Short name string */ /** @}*/