summaryrefslogtreecommitdiff
path: root/decoder/source/trc_frame_deformatter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'decoder/source/trc_frame_deformatter.cpp')
-rw-r--r--decoder/source/trc_frame_deformatter.cpp856
1 files changed, 856 insertions, 0 deletions
diff --git a/decoder/source/trc_frame_deformatter.cpp b/decoder/source/trc_frame_deformatter.cpp
new file mode 100644
index 000000000000..b4f40a2f9b44
--- /dev/null
+++ b/decoder/source/trc_frame_deformatter.cpp
@@ -0,0 +1,856 @@
+/*
+ * \file trc_frame_deformatter.cpp
+ * \brief OpenCSD :
+ *
+ * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
+ */
+
+/*
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <cstring>
+
+#include "common/trc_frame_deformatter.h"
+#include "trc_frame_deformatter_impl.h"
+
+/***************************************************************/
+/* Implementation */
+/***************************************************************/
+
+#ifdef __GNUC__
+// G++ doesn't like the ## pasting
+#define DEFORMATTER_NAME "DFMT_CSFRAMES"
+#else
+// VC is fine
+#define DEFORMATTER_NAME OCSD_CMPNAME_PREFIX_FRAMEDEFORMATTER##"_CSFRAMES"
+#endif
+
+TraceFmtDcdImpl::TraceFmtDcdImpl() : TraceComponent(DEFORMATTER_NAME),
+ m_cfgFlags(0),
+ m_force_sync_idx(0),
+ 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)
+
+{
+ resetStateParams();
+ setRawChanFilterAll(true);
+}
+
+TraceFmtDcdImpl::TraceFmtDcdImpl(int instNum) : TraceComponent(DEFORMATTER_NAME, instNum),
+ m_cfgFlags(0),
+ m_force_sync_idx(0),
+ m_use_force_sync(false),
+ m_alignment(16)
+{
+ resetStateParams();
+ setRawChanFilterAll(true);
+}
+
+TraceFmtDcdImpl::~TraceFmtDcdImpl()
+{
+}
+
+ocsd_datapath_resp_t TraceFmtDcdImpl::TraceDataIn(
+ const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index,
+ const uint32_t dataBlockSize,
+ const uint8_t *pDataBlock,
+ uint32_t *numBytesProcessed)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_FATAL_INVALID_OP;
+ InitCollateDataPathResp();
+
+ m_b_output_packed_raw = m_RawTraceFrame.num_attached() && ((m_cfgFlags & OCSD_DFRMTR_PACKED_RAW_OUT) != 0);
+ m_b_output_unpacked_raw = m_RawTraceFrame.num_attached() && ((m_cfgFlags & OCSD_DFRMTR_UNPACKED_RAW_OUT) != 0);
+
+ switch(op)
+ {
+ case OCSD_OP_RESET:
+ resp = Reset();
+ break;
+
+ case OCSD_OP_FLUSH:
+ resp = Flush();
+ break;
+
+ case OCSD_OP_EOT:
+ // local 'flush' here?
+ // pass on EOT to connected ID streams
+ resp = executeNoneDataOpAllIDs(OCSD_OP_EOT);
+ break;
+
+ case OCSD_OP_DATA:
+ if((dataBlockSize <= 0) || ( pDataBlock == 0) || (numBytesProcessed == 0))
+ resp = OCSD_RESP_FATAL_INVALID_PARAM;
+ else
+ resp = processTraceData(index,dataBlockSize, pDataBlock, numBytesProcessed);
+ break;
+
+ default:
+ break;
+ }
+
+ return resp;
+}
+
+/* enable / disable ID streams - default as all enabled */
+ocsd_err_t TraceFmtDcdImpl::OutputFilterIDs(std::vector<uint8_t> &id_list, bool bEnable)
+{
+ ocsd_err_t err = OCSD_OK;
+ std::vector<uint8_t>::iterator iter = id_list.begin();
+ uint8_t id = 0;
+
+ while((iter < id_list.end()) && (err == OCSD_OK))
+ {
+ id = *iter;
+ if(id > 128)
+ err = OCSD_ERR_INVALID_ID;
+ else
+ {
+ m_IDStreams[id].set_enabled(bEnable);
+ m_raw_chan_enable[id] = bEnable;
+ }
+ iter++;
+ }
+ return err;
+}
+
+ocsd_err_t TraceFmtDcdImpl::OutputFilterAllIDs(bool bEnable)
+{
+ for(uint8_t id = 0; id < 128; id++)
+ {
+ m_IDStreams[id].set_enabled(bEnable);
+ }
+ setRawChanFilterAll(bEnable);
+ return OCSD_OK;
+}
+
+void TraceFmtDcdImpl::setRawChanFilterAll(bool bEnable)
+{
+ for(int i=0; i<128; i++)
+ {
+ m_raw_chan_enable[i] = bEnable;
+ }
+}
+
+const bool TraceFmtDcdImpl::rawChanEnabled(const uint8_t id) const
+{
+ if(id < 128)
+ return m_raw_chan_enable[id];
+ return false;
+}
+
+/* decode control */
+ocsd_datapath_resp_t TraceFmtDcdImpl::Reset()
+{
+ resetStateParams();
+ InitCollateDataPathResp();
+ return executeNoneDataOpAllIDs(OCSD_OP_RESET);
+}
+
+ocsd_datapath_resp_t TraceFmtDcdImpl::Flush()
+{
+ executeNoneDataOpAllIDs(OCSD_OP_FLUSH); // flush any upstream data.
+ if(dataPathCont())
+ outputFrame(); // try to flush any partial frame data remaining
+ return highestDataPathResp();
+}
+
+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++)
+ {
+ if(m_IDStreams[id].num_attached())
+ {
+ pTrcComp = m_IDStreams[id].first();
+ while(pTrcComp)
+ {
+ CollateDataPathResp(pTrcComp->TraceDataIn(op,index,0,0,0));
+ pTrcComp = m_IDStreams[id].next();
+ }
+ }
+ }
+
+ if( m_RawTraceFrame.num_attached())
+ {
+ if(m_RawTraceFrame.first())
+ m_RawTraceFrame.first()->TraceRawFrameIn(op,0,OCSD_FRM_NONE,0,0,0);
+ }
+ return highestDataPathResp();
+}
+
+void TraceFmtDcdImpl::outputRawMonBytes(const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index,
+ const ocsd_rawframe_elem_t frame_element,
+ const int dataBlockSize,
+ const uint8_t *pDataBlock,
+ const uint8_t traceID)
+{
+ if( m_RawTraceFrame.num_attached())
+ {
+ if(m_RawTraceFrame.first())
+ m_RawTraceFrame.first()->TraceRawFrameIn(op,index,frame_element,dataBlockSize, pDataBlock,traceID);
+ }
+}
+
+void TraceFmtDcdImpl::CollateDataPathResp(const ocsd_datapath_resp_t resp)
+{
+ // simple most severe error across multiple IDs.
+ if(resp > m_highestResp) m_highestResp = resp;
+}
+
+ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData(
+ const ocsd_trc_index_t index,
+ const uint32_t dataBlockSize,
+ const uint8_t *pDataBlock,
+ uint32_t *numBytesProcessed
+ )
+{
+ try {
+
+ if(!m_first_data) // is this the initial data block?
+ {
+ m_trc_curr_idx = index;
+ }
+ else
+ {
+ if(m_trc_curr_idx != index) // none continuous trace data - throw an error.
+ throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_DFMTR_NOTCONTTRACE,index);
+ }
+
+ if(dataBlockSize % m_alignment) // must be correctly aligned data
+ {
+ ocsdError err(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PARAM_VAL);
+ char msg_buffer[64];
+ sprintf(msg_buffer,"Input block incorrect size, must be %d byte multiple", m_alignment);
+ err.setMessage(msg_buffer);
+ throw ocsdError(&err);
+ }
+
+ // record the incoming block for extraction routines to use.
+ m_in_block_base = pDataBlock;
+ m_in_block_size = dataBlockSize;
+ m_in_block_processed = 0;
+
+ // processing loop...
+ if(checkForSync())
+ {
+ bool bProcessing = true;
+ while(bProcessing)
+ {
+ bProcessing = extractFrame(); // will stop on end of input data.
+ if(bProcessing)
+ bProcessing = unpackFrame();
+ if(bProcessing)
+ bProcessing = outputFrame(); // will stop on data path halt.
+ }
+ }
+ }
+ catch(const ocsdError &err) {
+ LogError(err);
+ CollateDataPathResp(OCSD_RESP_FATAL_INVALID_DATA);
+ }
+ catch(...) {
+ LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_FAIL));
+ CollateDataPathResp(OCSD_RESP_FATAL_SYS_ERR);
+ }
+
+ if(!m_first_data)
+ m_first_data = true;
+
+ // update the outputs.
+ *numBytesProcessed = m_in_block_processed;
+
+ return highestDataPathResp();
+}
+
+ocsd_err_t TraceFmtDcdImpl::DecodeConfigure(uint32_t flags)
+{
+ const char *pszErrMsg = "";
+ ocsd_err_t err = OCSD_OK;
+
+ if((flags & ~OCSD_DFRMTR_VALID_MASK) != 0)
+ {
+ err = OCSD_ERR_INVALID_PARAM_VAL;
+ pszErrMsg = "Unknown Config Flags";
+ }
+
+ if((flags & OCSD_DFRMTR_VALID_MASK) == 0)
+ {
+ err = OCSD_ERR_INVALID_PARAM_VAL;
+ pszErrMsg = "No Config Flags Set";
+ }
+
+ if((flags & (OCSD_DFRMTR_HAS_FSYNCS | OCSD_DFRMTR_HAS_HSYNCS)) &&
+ (flags & OCSD_DFRMTR_FRAME_MEM_ALIGN)
+ )
+ {
+ err = OCSD_ERR_INVALID_PARAM_VAL;
+ pszErrMsg = "Invalid Config Flag Combination Set";
+ }
+
+ if(err != OCSD_OK)
+ {
+ ocsdError errObj(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL);
+ errObj.setMessage(pszErrMsg);
+ LogError(errObj);
+ }
+ else
+ {
+ m_cfgFlags = flags;
+ m_alignment = 16;
+ if(flags & OCSD_DFRMTR_HAS_FSYNCS)
+ m_alignment = 4;
+ else if(flags & OCSD_DFRMTR_HAS_HSYNCS)
+ m_alignment = 2;
+ }
+ return err;
+}
+
+void TraceFmtDcdImpl::resetStateParams()
+{
+ // overall dynamic state - intra frame
+ m_trc_curr_idx = OCSD_BAD_TRC_INDEX; /* source index of current trace data */
+ m_frame_synced = false;
+ m_first_data = false;
+ m_curr_src_ID = OCSD_BAD_CS_SRC_ID;
+
+ // current frame processing
+ m_ex_frm_n_bytes = 0;
+ m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX;
+}
+
+bool TraceFmtDcdImpl::checkForSync()
+{
+ // we can sync on:-
+ // 16 byte alignment - standard input buffers such as ETB
+ // FSYNC packets in the stream
+ // forced index programmed into the object.
+ uint32_t unsynced_bytes = 0;
+
+ if(!m_frame_synced)
+ {
+ if(m_use_force_sync)
+ {
+ // is the force sync point in this block?
+ if((m_force_sync_idx >= m_trc_curr_idx) && (m_force_sync_idx < (m_trc_curr_idx + m_in_block_size)))
+ {
+ unsynced_bytes = m_force_sync_idx - m_trc_curr_idx;
+ m_frame_synced = true;
+ }
+ else
+ {
+ unsynced_bytes = m_in_block_size;
+ }
+ }
+ else if( m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) // memory aligned data
+ {
+ unsynced_bytes = findfirstFSync();
+
+ }
+ else
+ {
+ // OCSD_DFRMTR_FRAME_MEM_ALIGN - this has guaranteed 16 byte frame size and alignment.
+ m_frame_synced = true;
+ }
+
+ if(unsynced_bytes)
+ {
+ outputUnsyncedBytes(unsynced_bytes);
+ m_in_block_processed = unsynced_bytes;
+ m_trc_curr_idx += unsynced_bytes;
+ }
+ }
+ return m_frame_synced;
+}
+
+uint32_t TraceFmtDcdImpl::findfirstFSync()
+{
+ uint32_t unsynced = m_in_block_size; // consider entire block as unsynced at present.
+ //**TBD - handle fsync patterns in TPIU captured code
+ return unsynced;
+}
+
+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()
+{
+ 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
+
+ // memory aligned sources are always multiples of frames, aligned to start.
+ if( m_cfgFlags & OCSD_DFRMTR_FRAME_MEM_ALIGN)
+ {
+ // 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();
+
+ /* in this case the FSYNC pattern is output on both packed and unpacked cases */
+ if (f_sync_bytes && (m_b_output_packed_raw || m_b_output_unpacked_raw))
+ {
+ outputRawMonBytes(OCSD_OP_DATA,
+ m_trc_curr_idx,
+ OCSD_FRM_FSYNC,
+ f_sync_bytes,
+ m_in_block_base + m_in_block_processed,
+ 0);
+ }
+ }
+
+ 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 + 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
+ {
+ // extract data accounting for frame syncs and hsyncs if present.
+ // we know we are aligned at this point - could be FSYNC or HSYNCs here.
+
+ // 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);
+
+ const uint8_t *dataPtr = m_in_block_base+m_in_block_processed;
+ const uint8_t *eodPtr = m_in_block_base+m_in_block_size;
+
+ cont_process = (bool)(dataPtr < eodPtr);
+
+ // 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)) == FSYNC_PATTERN) && cont_process)
+ {
+ f_sync_bytes += 4;
+ dataPtr += 4;
+ cont_process = (bool)(dataPtr < eodPtr);
+
+ // TBD: output raw FSYNC data on raw frame channel.
+ }
+ }
+
+ // not an FSYNC
+ while((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && cont_process)
+ {
+ // check for illegal out of sequence FSYNC
+ if((m_ex_frm_n_bytes % 4) == 0)
+ {
+ if(*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
+ {
+ // throw an illegal FSYNC error
+ }
+ }
+
+ // mark start of frame after FSyncs
+ if(m_ex_frm_n_bytes == 0)
+ m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;
+
+ m_ex_frm_data[m_ex_frm_n_bytes] = dataPtr[0];
+ m_ex_frm_data[m_ex_frm_n_bytes+1] = dataPtr[1];
+ m_ex_frm_n_bytes+=2;
+ ex_bytes +=2;
+
+ // check pair is not HSYNC
+ if(*((uint16_t *)(dataPtr)) == HSYNC_PATTERN)
+ {
+ if(hasHSyncs)
+ {
+ m_ex_frm_n_bytes-=2;
+ ex_bytes -= 2;
+ h_sync_bytes+=2;
+
+ // TBD: output raw HSYNC data on raw frame channel.
+ }
+ else
+ {
+ // throw illegal HSYNC error.
+ }
+ }
+
+ dataPtr += 2;
+ cont_process = (bool)(dataPtr < eodPtr);
+ }
+
+ // if we hit the end of data but still have a complete frame waiting,
+ // need to continue processing to allow it to be used.
+ if(!cont_process && (m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE))
+ cont_process = true;
+ }
+
+ // output raw data on raw frame channel - packed raw.
+ if ((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) && m_b_output_packed_raw)
+ {
+ outputRawMonBytes( OCSD_OP_DATA,
+ m_trc_curr_idx,
+ OCSD_FRM_PACKED,
+ ex_bytes + f_sync_bytes + h_sync_bytes,
+ m_in_block_base+m_in_block_processed,
+ 0);
+ }
+
+ // update the processed count for the buffer
+ m_in_block_processed += m_ex_frm_n_bytes + f_sync_bytes + h_sync_bytes;
+
+ // update index past the processed data
+ m_trc_curr_idx += m_ex_frm_n_bytes + f_sync_bytes + h_sync_bytes;
+
+ return cont_process;
+}
+
+bool TraceFmtDcdImpl::unpackFrame()
+{
+ // unpack cannot fail as never called on incomplete frame.
+ uint8_t frameFlagBit = 0x1;
+ uint8_t newSrcID = OCSD_BAD_CS_SRC_ID;
+ bool PrevIDandIDChange = false;
+
+ // init output processing
+ m_out_data_idx = 0;
+ m_out_processed = 0;
+
+ // set up first out data packet...
+ m_out_data[m_out_data_idx].id = m_curr_src_ID;
+ m_out_data[m_out_data_idx].valid = 0;
+ m_out_data[m_out_data_idx].index = m_trc_curr_idx_sof;
+ m_out_data[m_out_data_idx].used = 0;
+
+ // work on byte pairs - bytes 0 - 13.
+ for(int i = 0; i < 14; i+=2)
+ {
+ PrevIDandIDChange = false;
+
+ // it's an ID + data
+ if(m_ex_frm_data[i] & 0x1)
+ {
+ newSrcID = (m_ex_frm_data[i] >> 1) & 0x7f;
+ if(newSrcID != m_curr_src_ID) // ID change
+ {
+ PrevIDandIDChange = ((frameFlagBit & m_ex_frm_data[15]) != 0);
+
+ // following byte for old id?
+ if(PrevIDandIDChange)
+ // 2nd byte always data
+ m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i+1];
+
+ // change ID
+ m_curr_src_ID = newSrcID;
+
+ // if we already have data in this buffer
+ if(m_out_data[m_out_data_idx].valid > 0)
+ {
+ m_out_data_idx++; // move to next buffer
+ m_out_data[m_out_data_idx].valid = 0;
+ m_out_data[m_out_data_idx].used = 0;
+ m_out_data[m_out_data_idx].index = m_trc_curr_idx_sof + i;
+ }
+
+ // set new ID on buffer
+ m_out_data[m_out_data_idx].id = m_curr_src_ID;
+
+ /// TBD - ID indexing in here.
+ }
+ }
+ else
+ // it's just data
+ {
+ m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i] | ((frameFlagBit & m_ex_frm_data[15]) ? 0x1 : 0x0);
+ }
+
+ // 2nd byte always data
+ if(!PrevIDandIDChange) // output only if we didn't for an ID change + prev ID.
+ m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i+1];
+
+ frameFlagBit <<= 1;
+ }
+
+ // unpack byte 14;
+
+ // it's an ID
+ if(m_ex_frm_data[14] & 0x1)
+ {
+ // 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;
+ }
+ // it's data
+ else
+ {
+ 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;
+ return true;
+}
+
+// output data to channels.
+bool TraceFmtDcdImpl::outputFrame()
+{
+ bool cont_processing = true;
+ ITrcDataIn *pDataIn = 0;
+ uint32_t bytes_used;
+
+ // output each valid ID within the frame - stopping if we get a wait or error
+ while((m_out_processed < (m_out_data_idx + 1)) && cont_processing)
+ {
+
+ // may have data prior to a valid ID appearing
+ if(m_out_data[m_out_processed].id != OCSD_BAD_CS_SRC_ID)
+ {
+ if((pDataIn = m_IDStreams[m_out_data[m_out_processed].id].first()) != 0)
+ {
+ // log the stuff we are about to put out early so as to make it visible before interpretation
+ // however, don't re-output if only part used first time round.
+ if(m_b_output_unpacked_raw && (m_out_data[m_out_processed].used == 0) && rawChanEnabled( m_out_data[m_out_processed].id))
+ {
+ outputRawMonBytes( OCSD_OP_DATA,
+ m_out_data[m_out_processed].index,
+ OCSD_FRM_ID_DATA,
+ m_out_data[m_out_processed].valid,
+ m_out_data[m_out_processed].data,
+ m_out_data[m_out_processed].id);
+ }
+
+ // output to the connected packet process
+ CollateDataPathResp(pDataIn->TraceDataIn(OCSD_OP_DATA,
+ m_out_data[m_out_processed].index + m_out_data[m_out_processed].used,
+ m_out_data[m_out_processed].valid - m_out_data[m_out_processed].used,
+ m_out_data[m_out_processed].data + m_out_data[m_out_processed].used,
+ &bytes_used));
+
+ if(!dataPathCont())
+ {
+ cont_processing = false;
+ m_out_data[m_out_processed].used += bytes_used;
+ if(m_out_data[m_out_processed].used == m_out_data[m_out_processed].valid)
+ m_out_processed++; // we have used up all this data.
+ }
+ else
+ {
+ m_out_processed++; // we have sent this data;
+ }
+ }
+ else
+ {
+ // optional raw output for debugging / monitor tools
+ if(m_b_output_unpacked_raw && rawChanEnabled( m_out_data[m_out_processed].id))
+ {
+ outputRawMonBytes( OCSD_OP_DATA,
+ m_out_data[m_out_processed].index,
+ OCSD_FRM_ID_DATA,
+ m_out_data[m_out_processed].valid,
+ m_out_data[m_out_processed].data,
+ m_out_data[m_out_processed].id);
+ }
+ m_out_processed++; // skip past this data.
+ }
+ }
+ else
+ {
+ // optional raw output for debugging / monitor tools of unknown src ID data
+ if(m_b_output_unpacked_raw)
+ {
+ outputRawMonBytes( OCSD_OP_DATA,
+ m_out_data[m_out_processed].index,
+ OCSD_FRM_ID_DATA,
+ m_out_data[m_out_processed].valid,
+ m_out_data[m_out_processed].data,
+ m_out_data[m_out_processed].id);
+ }
+ m_out_processed++; // skip past this data.
+ }
+ }
+ return cont_processing;
+}
+
+/***************************************************************/
+/* interface */
+/***************************************************************/
+TraceFormatterFrameDecoder::TraceFormatterFrameDecoder() : m_pDecoder(0)
+{
+ m_instNum = -1;
+}
+
+TraceFormatterFrameDecoder::TraceFormatterFrameDecoder(int instNum) : m_pDecoder(0)
+{
+ m_instNum = instNum;
+}
+
+TraceFormatterFrameDecoder::~TraceFormatterFrameDecoder()
+{
+ if(m_pDecoder)
+ {
+ delete m_pDecoder;
+ m_pDecoder = 0;
+ }
+}
+
+ /* the data input interface from the reader / source */
+ocsd_datapath_resp_t TraceFormatterFrameDecoder::TraceDataIn( const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t index,
+ const uint32_t dataBlockSize,
+ const uint8_t *pDataBlock,
+ uint32_t *numBytesProcessed)
+{
+ return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed);
+}
+
+/* attach a data processor to a stream ID output */
+componentAttachPt<ITrcDataIn> *TraceFormatterFrameDecoder::getIDStreamAttachPt(uint8_t ID)
+{
+ componentAttachPt<ITrcDataIn> *pAttachPt = 0;
+ if((ID < 128) && (m_pDecoder != 0))
+ pAttachPt = &(m_pDecoder->m_IDStreams[ID]);
+ return pAttachPt;
+}
+
+/* attach a data processor to the raw frame output */
+componentAttachPt<ITrcRawFrameIn> *TraceFormatterFrameDecoder::getTrcRawFrameAttachPt()
+{
+ return (m_pDecoder != 0) ? &m_pDecoder->m_RawTraceFrame : 0;
+}
+
+
+componentAttachPt<ITrcSrcIndexCreator> *TraceFormatterFrameDecoder::getTrcSrcIndexAttachPt()
+{
+ return (m_pDecoder != 0) ? &m_pDecoder->m_SrcIndexer : 0;
+}
+
+componentAttachPt<ITraceErrorLog> *TraceFormatterFrameDecoder::getErrLogAttachPt()
+{
+ return (m_pDecoder != 0) ? m_pDecoder->getErrorLogAttachPt() : 0;
+}
+
+/* configuration - set operational mode for incoming stream (has FSYNCS etc) */
+ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags)
+{
+ if(!m_pDecoder)
+ {
+ if(m_instNum >= 0)
+ m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(m_instNum);
+ else
+ m_pDecoder = new (std::nothrow) TraceFmtDcdImpl();
+ if(!m_pDecoder) return OCSD_ERR_MEM;
+ }
+ m_pDecoder->m_cfgFlags = cfg_flags;
+ return OCSD_OK;
+}
+
+const uint32_t TraceFormatterFrameDecoder::getConfigFlags() const
+{
+ uint32_t flags = 0;
+ if(m_pDecoder)
+ flags = m_pDecoder->m_cfgFlags;
+ return flags;
+}
+
+
+/* enable / disable ID streams - default as all enabled */
+ocsd_err_t TraceFormatterFrameDecoder::OutputFilterIDs(std::vector<uint8_t> &id_list, bool bEnable)
+{
+ return (m_pDecoder == 0) ? OCSD_ERR_NOT_INIT : m_pDecoder->OutputFilterIDs(id_list,bEnable);
+}
+
+ocsd_err_t TraceFormatterFrameDecoder::OutputFilterAllIDs(bool bEnable)
+{
+ return (m_pDecoder == 0) ? OCSD_ERR_NOT_INIT : m_pDecoder->OutputFilterAllIDs(bEnable);
+}
+
+/* decode control */
+ocsd_datapath_resp_t TraceFormatterFrameDecoder::Reset()
+{
+ return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Reset();
+}
+
+ocsd_datapath_resp_t TraceFormatterFrameDecoder::Flush()
+{
+ return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Flush();
+}
+
+
+/* End of File trc_frame_deformatter.cpp */