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; };