When collecting on device trace, allow 4 * FSYNC frames to be used as padding or barrier frames to split data from trace runs.
Allows linux drivers to work correctly with tools such as perf that will grab multiple buffers of data and concatenate them in the output without the ability for the decoder to spot the breaks.
Updates frame indexing to account for skipped FSYNCs on resets. Allows frame index to be forwarded downstream reset operation.
Signed-off-by: Mike Leach mike.leach@linaro.org --- decoder/include/common/trc_pkt_proc_base.h | 10 ++-- decoder/include/ocsd_if_types.h | 3 +- decoder/source/trc_frame_deformatter.cpp | 82 +++++++++++++++++++++++------ decoder/source/trc_frame_deformatter_impl.h | 3 +- 4 files changed, 74 insertions(+), 24 deletions(-)
diff --git a/decoder/include/common/trc_pkt_proc_base.h b/decoder/include/common/trc_pkt_proc_base.h index f09ad61..3098a3d 100644 --- a/decoder/include/common/trc_pkt_proc_base.h +++ b/decoder/include/common/trc_pkt_proc_base.h @@ -185,7 +185,7 @@ protected:
private: /* decode control */ - ocsd_datapath_resp_t Reset(); + ocsd_datapath_resp_t Reset(const ocsd_trc_index_t index); ocsd_datapath_resp_t Flush(); ocsd_datapath_resp_t EOT();
@@ -247,7 +247,7 @@ template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, break;
case OCSD_OP_RESET: - resp = Reset(); + resp = Reset(index); break;
default: @@ -259,13 +259,13 @@ template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, }
-template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::Reset() +template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt, Pc>::Reset(const ocsd_trc_index_t index) { ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
// reset the trace decoder attachment on main data path. if(m_pkt_out_i.hasAttachedAndEnabled()) - resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_RESET,0,0); + resp = m_pkt_out_i.first()->PacketDataIn(OCSD_OP_RESET,index,0);
// reset the packet processor implmentation if(!OCSD_DATA_RESP_IS_FATAL(resp)) @@ -273,7 +273,7 @@ template<class P,class Pt, class Pc> ocsd_datapath_resp_t TrcPktProcBase<P, Pt,
// packet monitor if(m_pkt_raw_mon_i.hasAttachedAndEnabled()) - m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_RESET,0,0,0,0); + m_pkt_raw_mon_i.first()->RawPacketDataMon(OCSD_OP_RESET,index,0,0,0);
return resp; } diff --git a/decoder/include/ocsd_if_types.h b/decoder/include/ocsd_if_types.h index 14056e6..43df2ae 100644 --- a/decoder/include/ocsd_if_types.h +++ b/decoder/include/ocsd_if_types.h @@ -242,7 +242,8 @@ typedef enum _ocsd_dcd_tree_src_t { #define OCSD_DFRMTR_FRAME_MEM_ALIGN 0x04 /**< Deformatter Config : formatted frames are memory aligned, no syncs. Input data 16 byte frame aligned. */ #define OCSD_DFRMTR_PACKED_RAW_OUT 0x08 /**< Deformatter Config : output raw packed frame data if raw monitor attached. */ #define OCSD_DFRMTR_UNPACKED_RAW_OUT 0x10 /**< Deformatter Config : output raw unpacked frame data if raw monitor attached. */ -#define OCSD_DFRMTR_VALID_MASK 0x1F /**< Deformatter Config : valid mask for deformatter configuration */ +#define OCSD_DFRMTR_RESET_ON_4X_FSYNC 0x20 /**< Deformatter Config : reset downstream decoders if frame aligned 4x consecutive fsyncs spotted. (perf workaround) */ +#define OCSD_DFRMTR_VALID_MASK 0x3F /**< Deformatter Config : valid mask for deformatter configuration */
#define OCSD_DFRMTR_FRAME_SIZE 0x10 /**< CoreSight frame formatter frame size constant in bytes. */
diff --git a/decoder/source/trc_frame_deformatter.cpp b/decoder/source/trc_frame_deformatter.cpp index 57a7197..769c38c 100644 --- a/decoder/source/trc_frame_deformatter.cpp +++ b/decoder/source/trc_frame_deformatter.cpp @@ -181,7 +181,8 @@ ocsd_datapath_resp_t TraceFmtDcdImpl::Flush() return highestDataPathResp(); }
-ocsd_datapath_resp_t TraceFmtDcdImpl::executeNoneDataOpAllIDs(ocsd_datapath_op_t op) +ocsd_datapath_resp_t TraceFmtDcdImpl::executeNoneDataOpAllIDs(ocsd_datapath_op_t op, + const ocsd_trc_index_t index /* = 0*/) { ITrcDataIn *pTrcComp = 0; for(uint8_t id = 0; id < 128; id++) @@ -191,7 +192,7 @@ ocsd_datapath_resp_t TraceFmtDcdImpl::executeNoneDataOpAllIDs(ocsd_datapath_op_t pTrcComp = m_IDStreams[id].first(); while(pTrcComp) { - CollateDataPathResp(pTrcComp->TraceDataIn(op,0,0,0,0)); + CollateDataPathResp(pTrcComp->TraceDataIn(op,index,0,0,0)); pTrcComp = m_IDStreams[id].next(); } } @@ -402,9 +403,54 @@ void TraceFmtDcdImpl::outputUnsyncedBytes(uint32_t /*num_bytes*/) //**TBD: }
+int TraceFmtDcdImpl::checkForResetFSyncPatterns() +{ + const uint32_t FSYNC_PATTERN = 0x7FFFFFFF; // LE host pattern for FSYNC + bool check_for_fsync = true; + int num_fsyncs = 0; + const uint8_t *dataPtr = m_in_block_base + m_in_block_processed; + + while (check_for_fsync && (m_in_block_processed < m_in_block_size)) + { + // look for consecutive fsyncs as padding or for reset downstream - both cases will reset downstream.... + if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) + { + dataPtr += sizeof(uint32_t); + num_fsyncs++; + } + else + check_for_fsync = false; + } + + if (num_fsyncs) + { + printf("Frame deformatter: Found %d FSYNCS\n",num_fsyncs); + if ((num_fsyncs % 4) == 0) + { + // reset the upstream decoders + executeNoneDataOpAllIDs(OCSD_OP_RESET,m_trc_curr_idx); + + // reset the intra frame parameters + m_curr_src_ID = OCSD_BAD_CS_SRC_ID; + m_ex_frm_n_bytes = 0; + m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX; + } + else + { + // TBD: throw processing error, none frame size block of fsyncs + } + } + return num_fsyncs * 4; +} + + bool TraceFmtDcdImpl::extractFrame() { - bool cont_process = true; // continue processing after extraction. + const uint32_t FSYNC_PATTERN = 0x7FFFFFFF; // LE host pattern for FSYNC + const uint16_t HSYNC_PATTERN = 0x7FFF; // LE host pattern for HSYNC + + + bool cont_process = true; // continue processing after extraction. uint32_t f_sync_bytes = 0; // skipped f sync bytes uint32_t h_sync_bytes = 0; // skipped h sync bytes uint32_t ex_bytes = 0; // extracted bytes @@ -412,18 +458,23 @@ bool TraceFmtDcdImpl::extractFrame() // memory aligned sources are always multiples of frames, aligned to start. if( m_cfgFlags & OCSD_DFRMTR_FRAME_MEM_ALIGN) { - if(m_in_block_processed == m_in_block_size) + // some linux drivers (e.g. for perf) will insert FSYNCS to pad or differentiate + // between blocks of aligned data, always in frame aligned complete 16 byte frames. + if( m_cfgFlags & OCSD_DFRMTR_RESET_ON_4X_FSYNC) + f_sync_bytes = checkForResetFSyncPatterns(); + + if((m_in_block_processed+f_sync_bytes) == m_in_block_size) { m_ex_frm_n_bytes = 0; cont_process = false; // end of input data. } - else - { - // always a complete frame. - m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE; - memcpy(m_ex_frm_data, m_in_block_base+m_in_block_processed,m_ex_frm_n_bytes); - m_trc_curr_idx_sof = m_trc_curr_idx; - ex_bytes = OCSD_DFRMTR_FRAME_SIZE; + else + { + // always a complete frame. + m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE; + memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes); + m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes; + ex_bytes = OCSD_DFRMTR_FRAME_SIZE; } } else @@ -431,9 +482,6 @@ bool TraceFmtDcdImpl::extractFrame() // extract data accounting for frame syncs and hsyncs if present. // we know we are aligned at this point - could be FSYNC or HSYNCs here.
- #define FSYNC_PATTERN 0x7FFFFFFF // LE host pattern for FSYNC - #define HSYNC_PATTERN 0x7FFF // LE host pattern for HSYNC - // check what we a looking for bool hasFSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS); bool hasHSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS); @@ -446,7 +494,7 @@ bool TraceFmtDcdImpl::extractFrame() // can have FSYNCS at start of frame (in middle is an error). if(hasFSyncs && cont_process && (m_ex_frm_n_bytes == 0)) { - while((*((uint32_t *)(dataPtr)) == (uint32_t)FSYNC_PATTERN) && cont_process) + while((*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) && cont_process) { f_sync_bytes += 4; dataPtr += 4; @@ -462,7 +510,7 @@ bool TraceFmtDcdImpl::extractFrame() // check for illegal out of sequence FSYNC if((m_ex_frm_n_bytes % 4) == 0) { - if(*((uint32_t *)(dataPtr)) == (uint32_t)FSYNC_PATTERN) + if(*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) { // throw an illegal FSYNC error } @@ -478,7 +526,7 @@ bool TraceFmtDcdImpl::extractFrame() ex_bytes +=2;
// check pair is not HSYNC - if(*((uint16_t *)(dataPtr)) == (uint16_t)HSYNC_PATTERN) + if(*((uint16_t *)(dataPtr)) == HSYNC_PATTERN) { if(hasHSyncs) { diff --git a/decoder/source/trc_frame_deformatter_impl.h b/decoder/source/trc_frame_deformatter_impl.h index 8e3f1ba..488bfad 100644 --- a/decoder/source/trc_frame_deformatter_impl.h +++ b/decoder/source/trc_frame_deformatter_impl.h @@ -76,7 +76,7 @@ private: ocsd_err_t SetForcedSyncIndex(ocsd_trc_index_t index, bool bSet);
private: - ocsd_datapath_resp_t executeNoneDataOpAllIDs(ocsd_datapath_op_t op); + 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, const uint32_t dataBlockSize, const uint8_t *pDataBlock, @@ -113,6 +113,7 @@ private: void setRawChanFilterAll(bool bEnable); const bool rawChanEnabled(const uint8_t id) const;
+ int checkForResetFSyncPatterns();
friend class TraceFormatterFrameDecoder;