xref: /freebsd/contrib/opencsd/decoder/source/trc_frame_deformatter.cpp (revision 46e6e290975f19ea62d03f90ac3e523af4dae557)
1  /*
2   * \file       trc_frame_deformatter.cpp
3   * \brief      OpenCSD :
4   *
5   * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
6   */
7  
8  /*
9   * Redistribution and use in source and binary forms, with or without modification,
10   * are permitted provided that the following conditions are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright notice,
13   * this list of conditions and the following disclaimer.
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright notice,
16   * this list of conditions and the following disclaimer in the documentation
17   * and/or other materials provided with the distribution.
18   *
19   * 3. Neither the name of the copyright holder nor the names of its contributors
20   * may be used to endorse or promote products derived from this software without
21   * specific prior written permission.
22   *
23   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26   * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   */
34  #include <cstring>
35  
36  #include "common/trc_frame_deformatter.h"
37  #include "trc_frame_deformatter_impl.h"
38  
39  /***************************************************************/
40  /* Implementation */
41  /***************************************************************/
42  
43  #ifdef __GNUC__
44  // G++ doesn't like the ## pasting
45  #define DEFORMATTER_NAME "DFMT_CSFRAMES"
46  #else
47  // VC is fine
48  #define DEFORMATTER_NAME OCSD_CMPNAME_PREFIX_FRAMEDEFORMATTER##"_CSFRAMES"
49  #endif
50  
TraceFmtDcdImpl()51  TraceFmtDcdImpl::TraceFmtDcdImpl() : TraceComponent(DEFORMATTER_NAME),
52      m_cfgFlags(0),
53      m_force_sync_idx(0),
54      m_use_force_sync(false),
55      m_alignment(16), // assume frame aligned data as default.
56      m_b_output_packed_raw(false),
57      m_b_output_unpacked_raw(false),
58      m_pStatsBlock(0)
59  
60  {
61      resetStateParams();
62      setRawChanFilterAll(true);
63  }
64  
TraceFmtDcdImpl(int instNum)65  TraceFmtDcdImpl::TraceFmtDcdImpl(int instNum) : TraceComponent(DEFORMATTER_NAME, instNum),
66      m_cfgFlags(0),
67      m_force_sync_idx(0),
68      m_use_force_sync(false),
69      m_alignment(16)
70  {
71      resetStateParams();
72      setRawChanFilterAll(true);
73  }
74  
~TraceFmtDcdImpl()75  TraceFmtDcdImpl::~TraceFmtDcdImpl()
76  {
77  }
78  
TraceDataIn(const ocsd_datapath_op_t op,const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)79  ocsd_datapath_resp_t TraceFmtDcdImpl::TraceDataIn(
80      const ocsd_datapath_op_t op,
81      const ocsd_trc_index_t index,
82      const uint32_t dataBlockSize,
83      const uint8_t *pDataBlock,
84      uint32_t *numBytesProcessed)
85  {
86      ocsd_datapath_resp_t resp = OCSD_RESP_FATAL_INVALID_OP;
87      InitCollateDataPathResp();
88  
89      m_b_output_packed_raw = m_RawTraceFrame.num_attached() && ((m_cfgFlags & OCSD_DFRMTR_PACKED_RAW_OUT) != 0);
90      m_b_output_unpacked_raw = m_RawTraceFrame.num_attached() && ((m_cfgFlags & OCSD_DFRMTR_UNPACKED_RAW_OUT) != 0);
91  
92      switch(op)
93      {
94      case OCSD_OP_RESET:
95          resp = Reset();
96          break;
97  
98      case OCSD_OP_FLUSH:
99          resp = Flush();
100          break;
101  
102      case OCSD_OP_EOT:
103          // local 'flush' here?
104          // pass on EOT to connected ID streams
105          resp = executeNoneDataOpAllIDs(OCSD_OP_EOT);
106          break;
107  
108      case OCSD_OP_DATA:
109          if((dataBlockSize <= 0) || ( pDataBlock == 0) || (numBytesProcessed == 0))
110              resp = OCSD_RESP_FATAL_INVALID_PARAM;
111          else
112              resp = processTraceData(index,dataBlockSize, pDataBlock, numBytesProcessed);
113          break;
114  
115      default:
116          break;
117      }
118  
119      return resp;
120  }
121  
122  /* enable / disable ID streams - default as all enabled */
OutputFilterIDs(std::vector<uint8_t> & id_list,bool bEnable)123  ocsd_err_t TraceFmtDcdImpl::OutputFilterIDs(std::vector<uint8_t> &id_list, bool bEnable)
124  {
125      ocsd_err_t err =  OCSD_OK;
126      std::vector<uint8_t>::iterator iter = id_list.begin();
127      uint8_t id = 0;
128  
129      while((iter < id_list.end()) && (err == OCSD_OK))
130      {
131          id = *iter;
132          if(id > 128)
133              err = OCSD_ERR_INVALID_ID;
134          else
135          {
136              m_IDStreams[id].set_enabled(bEnable);
137              m_raw_chan_enable[id] = bEnable;
138          }
139          iter++;
140      }
141      return err;
142  }
143  
OutputFilterAllIDs(bool bEnable)144  ocsd_err_t TraceFmtDcdImpl::OutputFilterAllIDs(bool bEnable)
145  {
146      for(uint8_t id = 0; id < 128; id++)
147      {
148          m_IDStreams[id].set_enabled(bEnable);
149      }
150      setRawChanFilterAll(bEnable);
151      return OCSD_OK;
152  }
153  
setRawChanFilterAll(bool bEnable)154  void TraceFmtDcdImpl::setRawChanFilterAll(bool bEnable)
155  {
156      for(int i=0; i<128; i++)
157      {
158          m_raw_chan_enable[i] = bEnable;
159      }
160  }
161  
rawChanEnabled(const uint8_t id) const162  const bool TraceFmtDcdImpl::rawChanEnabled(const uint8_t id) const
163  {
164      if(id < 128)
165          return m_raw_chan_enable[id];
166      return false;
167  }
168  
169  /* decode control */
Reset()170  ocsd_datapath_resp_t TraceFmtDcdImpl::Reset()
171  {
172      resetStateParams();
173      InitCollateDataPathResp();
174      return executeNoneDataOpAllIDs(OCSD_OP_RESET);
175  }
176  
Flush()177  ocsd_datapath_resp_t TraceFmtDcdImpl::Flush()
178  {
179      executeNoneDataOpAllIDs(OCSD_OP_FLUSH);    // flush any upstream data.
180      if(dataPathCont())
181          outputFrame();  // try to flush any partial frame data remaining
182      return highestDataPathResp();
183  }
184  
executeNoneDataOpAllIDs(ocsd_datapath_op_t op,const ocsd_trc_index_t index)185  ocsd_datapath_resp_t TraceFmtDcdImpl::executeNoneDataOpAllIDs(ocsd_datapath_op_t op,
186                                                                const ocsd_trc_index_t index /* = 0*/)
187  {
188      ITrcDataIn *pTrcComp = 0;
189      for(uint8_t id = 0; id < 128; id++)
190      {
191          if(m_IDStreams[id].num_attached())
192          {
193              pTrcComp = m_IDStreams[id].first();
194              while(pTrcComp)
195              {
196                  CollateDataPathResp(pTrcComp->TraceDataIn(op,index,0,0,0));
197                  pTrcComp = m_IDStreams[id].next();
198              }
199          }
200      }
201  
202      if( m_RawTraceFrame.num_attached())
203      {
204          if(m_RawTraceFrame.first())
205              m_RawTraceFrame.first()->TraceRawFrameIn(op,0,OCSD_FRM_NONE,0,0,0);
206      }
207      return highestDataPathResp();
208  }
209  
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)210  void TraceFmtDcdImpl::outputRawMonBytes(const ocsd_datapath_op_t op,
211                             const ocsd_trc_index_t index,
212                             const ocsd_rawframe_elem_t frame_element,
213                             const int dataBlockSize,
214                             const uint8_t *pDataBlock,
215                             const uint8_t traceID)
216  {
217      if( m_RawTraceFrame.num_attached())
218      {
219          if(m_RawTraceFrame.first())
220              m_RawTraceFrame.first()->TraceRawFrameIn(op,index,frame_element,dataBlockSize, pDataBlock,traceID);
221      }
222  }
223  
CollateDataPathResp(const ocsd_datapath_resp_t resp)224  void TraceFmtDcdImpl::CollateDataPathResp(const ocsd_datapath_resp_t resp)
225  {
226      // simple most severe error across multiple IDs.
227      if(resp > m_highestResp) m_highestResp = resp;
228  }
229  
processTraceData(const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)230  ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData(
231                                          const ocsd_trc_index_t index,
232                                          const uint32_t dataBlockSize,
233                                          const uint8_t *pDataBlock,
234                                          uint32_t *numBytesProcessed
235                                          )
236  {
237      try {
238  
239          if(!m_first_data)  // is this the initial data block?
240          {
241              m_trc_curr_idx = index;
242          }
243          else
244          {
245              if(m_trc_curr_idx != index) // none continuous trace data - throw an error.
246                  throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_DFMTR_NOTCONTTRACE,index);
247          }
248  
249          // record the incoming block for extraction routines to use.
250          m_in_block_base = pDataBlock;
251          m_in_block_size = dataBlockSize;
252          m_in_block_processed = 0;
253  
254          if(dataBlockSize % m_alignment) // must be correctly aligned data
255          {
256              ocsdError err(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PARAM_VAL);
257              char msg_buffer[64];
258              sprintf(msg_buffer,"Input block incorrect size, must be %d byte multiple", m_alignment);
259              err.setMessage(msg_buffer);
260              throw ocsdError(&err);
261          }
262  
263          // processing loop...
264          if(checkForSync())
265          {
266              bool bProcessing = true;
267              while(bProcessing)
268              {
269                  bProcessing = extractFrame();   // will stop on end of input data.
270                  if(bProcessing)
271                      bProcessing = unpackFrame();
272                  if(bProcessing)
273                      bProcessing = outputFrame(); // will stop on data path halt.
274              }
275          }
276      }
277      catch(const ocsdError &err) {
278          LogError(err);
279          CollateDataPathResp(OCSD_RESP_FATAL_INVALID_DATA);
280      }
281      catch(...) {
282          LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_FAIL));
283          CollateDataPathResp(OCSD_RESP_FATAL_SYS_ERR);
284      }
285  
286      if(!m_first_data)
287          m_first_data = true;
288  
289      // update the outputs.
290      *numBytesProcessed = m_in_block_processed;
291  
292      return highestDataPathResp();
293  }
294  
DecodeConfigure(uint32_t flags)295  ocsd_err_t  TraceFmtDcdImpl::DecodeConfigure(uint32_t flags)
296  {
297      const char *pszErrMsg = "";
298      ocsd_err_t err = OCSD_OK;
299  
300      if((flags & ~OCSD_DFRMTR_VALID_MASK) != 0)
301      {
302          err = OCSD_ERR_INVALID_PARAM_VAL;
303          pszErrMsg = "Unknown Config Flags";
304      }
305  
306      if((flags & OCSD_DFRMTR_VALID_MASK) == 0)
307      {
308          err = OCSD_ERR_INVALID_PARAM_VAL;
309          pszErrMsg = "No Config Flags Set";
310      }
311  
312      if((flags & (OCSD_DFRMTR_HAS_FSYNCS | OCSD_DFRMTR_HAS_HSYNCS)) &&
313         (flags & OCSD_DFRMTR_FRAME_MEM_ALIGN)
314         )
315      {
316          err = OCSD_ERR_INVALID_PARAM_VAL;
317          pszErrMsg = "Invalid Config Flag Combination Set";
318      }
319  
320      if(err != OCSD_OK)
321      {
322          ocsdError errObj(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL);
323          errObj.setMessage(pszErrMsg);
324          LogError(errObj);
325      }
326      else
327      {
328          // alightment is the multiple of bytes the buffer size must be.
329          m_cfgFlags = flags;
330  
331          // using memory aligned buffers, the formatter always outputs 16 byte frames so enforce
332          // this on the input
333          m_alignment = 16;
334          // if we have HSYNCS then always align to 2 byte buffers
335          if(flags & OCSD_DFRMTR_HAS_HSYNCS)
336              m_alignment = 2;
337          // otherwise FSYNCS only can have 4 byte aligned buffers.
338          else if(flags & OCSD_DFRMTR_HAS_FSYNCS)
339              m_alignment = 4;
340      }
341      return err;
342  }
343  
resetStateParams()344  void TraceFmtDcdImpl::resetStateParams()
345  {
346      // overall dynamic state - intra frame
347      m_trc_curr_idx = OCSD_BAD_TRC_INDEX;    /* source index of current trace data */
348      m_frame_synced = false;
349      m_first_data = false;
350      m_curr_src_ID = OCSD_BAD_CS_SRC_ID;
351  
352      // current frame processing
353      m_ex_frm_n_bytes = 0;
354      m_b_fsync_start_eob = false;
355      m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX;
356  }
357  
checkForSync()358  bool TraceFmtDcdImpl::checkForSync()
359  {
360      // we can sync on:-
361      // 16 byte alignment - standard input buffers such as ETB
362      // FSYNC packets in the stream
363      // forced index programmed into the object.
364      uint32_t unsynced_bytes = 0;
365  
366      if(!m_frame_synced)
367      {
368          if(m_use_force_sync)
369          {
370              // is the force sync point in this block?
371              if((m_force_sync_idx >= m_trc_curr_idx) && (m_force_sync_idx < (m_trc_curr_idx + m_in_block_size)))
372              {
373                  unsynced_bytes = m_force_sync_idx - m_trc_curr_idx;
374                  m_frame_synced = true;
375              }
376              else
377              {
378                  unsynced_bytes = m_in_block_size;
379              }
380          }
381          else if( m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS)   // memory aligned data
382          {
383               unsynced_bytes = findfirstFSync();
384  
385          }
386          else
387          {
388              // OCSD_DFRMTR_FRAME_MEM_ALIGN - this has guaranteed 16 byte frame size and alignment.
389              m_frame_synced = true;
390          }
391  
392          if(unsynced_bytes)
393          {
394              outputUnsyncedBytes(unsynced_bytes);
395              m_in_block_processed = unsynced_bytes;
396              m_trc_curr_idx += unsynced_bytes;
397          }
398      }
399      return m_frame_synced;
400  }
401  
findfirstFSync()402  uint32_t TraceFmtDcdImpl::findfirstFSync()
403  {
404      uint32_t processed = 0;
405      const uint32_t FSYNC_PATTERN = 0x7FFFFFFF;    // LE host pattern for FSYNC
406      const uint8_t *dataPtr = m_in_block_base;
407  
408      while (processed < (m_in_block_size - 3))
409      {
410          if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
411          {
412              m_frame_synced = true;
413              break;
414          }
415          processed++;
416          dataPtr++;
417      }
418      return processed;
419  }
420  
outputUnsyncedBytes(uint32_t)421  void TraceFmtDcdImpl::outputUnsyncedBytes(uint32_t /*num_bytes*/)
422  {
423      //**TBD:
424  }
425  
checkForResetFSyncPatterns(uint32_t & f_sync_bytes)426  ocsd_err_t TraceFmtDcdImpl::checkForResetFSyncPatterns(uint32_t &f_sync_bytes)
427  {
428  	const uint32_t FSYNC_PATTERN = 0x7FFFFFFF;    // LE host pattern for FSYNC
429  	bool check_for_fsync = true;
430  	int num_fsyncs = 0;
431      uint32_t bytes_processed = m_in_block_processed;
432  	const uint8_t *dataPtr = m_in_block_base + bytes_processed;
433      ocsd_err_t err = OCSD_OK;
434  
435  	while (check_for_fsync && (bytes_processed < m_in_block_size))
436  	{
437  		// look for consecutive fsyncs as padding or for reset downstream - both cases will reset downstream....
438  		if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
439  		{
440  			dataPtr += sizeof(uint32_t);
441              num_fsyncs++;
442              bytes_processed += sizeof(uint32_t);
443  		}
444  		else
445  			check_for_fsync = false;
446  	}
447  
448  	if (num_fsyncs)
449  	{
450  		if ((num_fsyncs % 4) == 0)
451          {
452              // reset the upstream decoders
453  			executeNoneDataOpAllIDs(OCSD_OP_RESET,m_trc_curr_idx);
454  
455              // reset the intra frame parameters
456              m_curr_src_ID = OCSD_BAD_CS_SRC_ID;
457              m_ex_frm_n_bytes = 0;
458              m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX;
459          }
460  		else
461  		{
462              err = OCSD_ERR_DFMTR_BAD_FHSYNC;
463  		}
464  	}
465      f_sync_bytes += num_fsyncs * 4;
466      return err;
467  }
468  
469  /* Extract a single frame from the input buffer. */
extractFrame()470  bool TraceFmtDcdImpl::extractFrame()
471  {
472  	const uint32_t FSYNC_PATTERN = 0x7FFFFFFF;    // LE host pattern for FSYNC
473  	const uint16_t HSYNC_PATTERN = 0x7FFF;        // LE host pattern for HSYNC
474      const uint16_t FSYNC_START = 0xFFFF;          // LE host pattern for start 2 bytes of fsync
475  
476      ocsd_err_t err;
477      uint32_t f_sync_bytes = 0; // skipped f sync bytes
478      uint32_t h_sync_bytes = 0; // skipped h sync bytes
479      uint32_t ex_bytes = 0;  // extracted this pass (may be filling out part frame)
480      uint32_t buf_left = m_in_block_size - m_in_block_processed; // bytes remaining in buffer this pass.
481  
482      // last call was end of input block - but carried on to process full frame.
483      // exit early here.
484      if (!buf_left)
485          return false;
486  
487      // memory aligned input data is forced to be always multiples of 16 byte frames, aligned to start.
488      if( m_cfgFlags & OCSD_DFRMTR_FRAME_MEM_ALIGN)
489      {
490  		// some linux drivers (e.g. for perf) will insert FSYNCS to pad or differentiate
491          // between blocks of aligned data, always in frame aligned complete 16 byte frames.
492          // we need to skip past these frames, resetting as we go.
493          if (m_cfgFlags & OCSD_DFRMTR_RESET_ON_4X_FSYNC)
494          {
495               err = checkForResetFSyncPatterns(f_sync_bytes);
496  
497              /* in this case the FSYNC pattern is output on both packed and unpacked cases */
498              if (f_sync_bytes && (m_b_output_packed_raw || m_b_output_unpacked_raw))
499              {
500                  outputRawMonBytes(OCSD_OP_DATA,
501                      m_trc_curr_idx,
502                      OCSD_FRM_FSYNC,
503                      f_sync_bytes,
504                      m_in_block_base + m_in_block_processed,
505                      0);
506              }
507  
508              // throw processing error, none frame size block of fsyncs
509              if (err)
510                  throw ocsdError(OCSD_ERR_SEV_ERROR, err, m_trc_curr_idx, "Incorrect FSYNC frame reset pattern");
511  
512              buf_left -= f_sync_bytes;
513          }
514  
515          if (buf_left)
516          {
517              // always a complete frame - the input data has to be 16 byte multiple alignment.
518              m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE;
519              memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes);
520              m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;
521              ex_bytes = OCSD_DFRMTR_FRAME_SIZE;
522          }
523      }
524      else
525      {
526          // extract data accounting for frame syncs and hsyncs if present.
527          // we know we are aligned at this point - could be FSYNC or HSYNCs here.
528          // HSYNC present, library forces input to be aligned 2 byte multiples
529          // FSYNC - w/o HSYNCs, forces input to be aligned 4 byte multiples.
530  
531          // check what we a looking for
532          bool hasFSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS);
533          bool hasHSyncs = ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS);
534  
535          const uint8_t* dataPtr = m_in_block_base + m_in_block_processed;
536          uint16_t data_pair_val;
537  
538          // can have FSYNCS at start of frame (in middle is an error).
539          if (hasFSyncs && (m_ex_frm_n_bytes == 0))
540          {
541              // was there an fsync start at the end of the last buffer?
542              if (m_b_fsync_start_eob) {
543                  // last 2 of FSYNC look like HSYNC
544                  if (*(uint16_t*)(dataPtr) != HSYNC_PATTERN)
545                  {
546                      // this means 0xFFFF followed by something else - invalid ID + ????
547                      throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC pattern before frame or invalid ID.(0x7F)");
548                  }
549                  else
550                  {
551                      f_sync_bytes += 2;
552                      buf_left -= 2;
553                      dataPtr += 2;
554                  }
555                  m_b_fsync_start_eob = false;
556              }
557  
558              // regular fsync checks
559              while ((buf_left >= 4) && (*((uint32_t*)(dataPtr)) == FSYNC_PATTERN))
560              {
561                  f_sync_bytes += 4;
562                  dataPtr += 4;
563                  buf_left -= 4;
564              }
565  
566              // handle possible part fsync at the end of a buffer
567              if (buf_left == 2)
568              {
569                  if (*(uint16_t*)(dataPtr) == FSYNC_START)
570                  {
571                      f_sync_bytes += 2;
572                      buf_left -= 2;
573                      dataPtr += 2;
574                      m_b_fsync_start_eob = true;
575                  }
576              }
577          }
578  
579          // process remaining data in pairs of bytes
580          while ((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && buf_left)
581          {
582              // mark start of frame after FSyncs
583              if (m_ex_frm_n_bytes == 0)
584                  m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;
585  
586              m_ex_frm_data[m_ex_frm_n_bytes] = dataPtr[0];
587              m_ex_frm_data[m_ex_frm_n_bytes + 1] = dataPtr[1];
588  
589              data_pair_val = *((uint16_t*)(dataPtr));
590  
591              // check pair is not HSYNC
592              if (data_pair_val == HSYNC_PATTERN)
593              {
594                  if (hasHSyncs)
595                  {
596                      h_sync_bytes += 2;
597                  }
598                  else
599                  {
600                      // throw illegal HSYNC error.
601                      throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad HSYNC in frame.");
602                  }
603              }
604              // can't have a start of FSYNC here / illegal trace ID
605              else if (data_pair_val == FSYNC_START)
606              {
607                  throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC start in frame or invalid ID (0x7F).");
608              }
609              else
610              {
611                  m_ex_frm_n_bytes += 2;
612                  ex_bytes += 2;
613              }
614  
615              buf_left -= 2;
616              dataPtr += 2;
617          }
618      }
619  
620      // total bytes processed this pass
621      uint32_t total_processed = ex_bytes + f_sync_bytes + h_sync_bytes;
622  
623      // output raw data on raw frame channel - packed raw.
624      if (((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) || (buf_left == 0)) && m_b_output_packed_raw)
625      {
626          outputRawMonBytes(  OCSD_OP_DATA,
627                              m_trc_curr_idx,
628                              OCSD_FRM_PACKED,
629                              total_processed,
630                              m_in_block_base+m_in_block_processed,
631                              0);
632      }
633  
634      // update the processed count for the buffer
635      m_in_block_processed += total_processed;
636  
637      // update index past the processed data
638      m_trc_curr_idx += total_processed;
639  
640      // update any none trace data byte stats
641      addToFrameStats((uint64_t)(f_sync_bytes + h_sync_bytes));
642  
643      // if we are exiting with a full frame then signal processing to continue
644      return (bool)(m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE);
645  }
646  
unpackFrame()647  bool TraceFmtDcdImpl::unpackFrame()
648  {
649      // unpack cannot fail as never called on incomplete frame.
650      uint8_t frameFlagBit = 0x1;
651      uint8_t newSrcID = OCSD_BAD_CS_SRC_ID;
652      bool PrevIDandIDChange = false;
653      uint64_t noneDataBytes = 0;
654  
655      // init output processing
656      m_out_data_idx = 0;
657      m_out_processed = 0;
658  
659      // set up first out data packet...
660      m_out_data[m_out_data_idx].id = m_curr_src_ID;
661      m_out_data[m_out_data_idx].valid = 0;
662      m_out_data[m_out_data_idx].index =  m_trc_curr_idx_sof;
663      m_out_data[m_out_data_idx].used = 0;
664  
665      // work on byte pairs - bytes 0 - 13.
666      for(int i = 0; i < 14; i+=2)
667      {
668          PrevIDandIDChange = false;
669  
670          // it's an ID + data
671          if(m_ex_frm_data[i] & 0x1)
672          {
673              newSrcID = (m_ex_frm_data[i] >> 1) & 0x7f;
674              if(newSrcID != m_curr_src_ID)   // ID change
675              {
676                  PrevIDandIDChange = ((frameFlagBit & m_ex_frm_data[15]) != 0);
677  
678                  // following byte for old id?
679                  if(PrevIDandIDChange)
680                      // 2nd byte always data
681                      m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i+1];
682  
683                  // change ID
684                  m_curr_src_ID = newSrcID;
685  
686                  // if we already have data in this buffer
687                  if(m_out_data[m_out_data_idx].valid > 0)
688                  {
689                      m_out_data_idx++; // move to next buffer
690                      m_out_data[m_out_data_idx].valid = 0;
691                      m_out_data[m_out_data_idx].used = 0;
692                      m_out_data[m_out_data_idx].index = m_trc_curr_idx_sof + i;
693                  }
694  
695                  // set new ID on buffer
696                  m_out_data[m_out_data_idx].id = m_curr_src_ID;
697  
698                  /// TBD - ID indexing in here.
699              }
700              noneDataBytes++;
701          }
702          else
703          // it's just data
704          {
705              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);
706          }
707  
708          // 2nd byte always data
709          if(!PrevIDandIDChange) // output only if we didn't for an ID change + prev ID.
710              m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i+1];
711  
712          frameFlagBit <<= 1;
713      }
714  
715      // unpack byte 14;
716  
717      // it's an ID
718      if(m_ex_frm_data[14] & 0x1)
719      {
720          // no matter if change or not, no associated data in byte 15 anyway so just set.
721          m_curr_src_ID = (m_ex_frm_data[14] >> 1) & 0x7f;
722          noneDataBytes++;
723      }
724      // it's data
725      else
726      {
727          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);
728      }
729      m_ex_frm_n_bytes = 0;   // mark frame as empty;
730  
731      noneDataBytes++;    // byte 15 is always non-data.
732      addToFrameStats(noneDataBytes); // update the non data byte stats.
733      return true;
734  }
735  
736  // output data to channels.
outputFrame()737  bool TraceFmtDcdImpl::outputFrame()
738  {
739      bool cont_processing = true;
740      ITrcDataIn *pDataIn = 0;
741      uint32_t bytes_used;
742  
743      // output each valid ID within the frame - stopping if we get a wait or error
744      while((m_out_processed < (m_out_data_idx + 1)) && cont_processing)
745      {
746  
747          // may have data prior to a valid ID appearing
748          if(m_out_data[m_out_processed].id != OCSD_BAD_CS_SRC_ID)
749          {
750              if((pDataIn = m_IDStreams[m_out_data[m_out_processed].id].first()) != 0)
751              {
752                  // log the stuff we are about to put out early so as to make it visible before interpretation
753                  // however, don't re-output if only part used first time round.
754                  if(m_b_output_unpacked_raw && (m_out_data[m_out_processed].used == 0) && rawChanEnabled( m_out_data[m_out_processed].id))
755                  {
756                      outputRawMonBytes( OCSD_OP_DATA,
757                              m_out_data[m_out_processed].index,
758                              OCSD_FRM_ID_DATA,
759                              m_out_data[m_out_processed].valid,
760                              m_out_data[m_out_processed].data,
761                              m_out_data[m_out_processed].id);
762                  }
763  
764                  // output to the connected packet process
765                  CollateDataPathResp(pDataIn->TraceDataIn(OCSD_OP_DATA,
766                      m_out_data[m_out_processed].index + m_out_data[m_out_processed].used,
767                      m_out_data[m_out_processed].valid - m_out_data[m_out_processed].used,
768                      m_out_data[m_out_processed].data + m_out_data[m_out_processed].used,
769                      &bytes_used));
770  
771                  addToIDStats((uint64_t)bytes_used);
772  
773                  if(!dataPathCont())
774                  {
775                      cont_processing = false;
776                      m_out_data[m_out_processed].used += bytes_used;
777                      if(m_out_data[m_out_processed].used == m_out_data[m_out_processed].valid)
778                          m_out_processed++; // we have used up all this data.
779                  }
780                  else
781                  {
782                      m_out_processed++; // we have sent this data;
783                  }
784              }
785              else
786              {
787                  // optional raw output for debugging / monitor tools
788                  if(m_b_output_unpacked_raw && rawChanEnabled( m_out_data[m_out_processed].id))
789                  {
790                      outputRawMonBytes(  OCSD_OP_DATA,
791                          m_out_data[m_out_processed].index,
792                          OCSD_FRM_ID_DATA,
793                          m_out_data[m_out_processed].valid,
794                          m_out_data[m_out_processed].data,
795                          m_out_data[m_out_processed].id);
796                  }
797  
798                  if (isReservedID(m_out_data[m_out_processed].id))
799                      addToReservedIDStats((uint64_t)m_out_data[m_out_processed].valid);
800                  else
801                      addToNoIDStats((uint64_t)m_out_data[m_out_processed].valid);
802                  m_out_processed++; // skip past this data.
803              }
804          }
805          else
806          {
807              // optional raw output for debugging / monitor tools of unknown src ID data
808              if(m_b_output_unpacked_raw)
809              {
810                  outputRawMonBytes(  OCSD_OP_DATA,
811                      m_out_data[m_out_processed].index,
812                      OCSD_FRM_ID_DATA,
813                      m_out_data[m_out_processed].valid,
814                      m_out_data[m_out_processed].data,
815                      m_out_data[m_out_processed].id);
816              }
817              addToUnknownIDStats((uint64_t)m_out_data[m_out_processed].valid);
818              m_out_processed++; // skip past this data.
819          }
820      }
821      return cont_processing;
822  }
823  
addToIDStats(uint64_t val)824  void TraceFmtDcdImpl::addToIDStats(uint64_t val)
825  {
826      if (m_pStatsBlock)
827          m_pStatsBlock->valid_id_bytes += val;
828  }
829  
addToNoIDStats(uint64_t val)830  void TraceFmtDcdImpl::addToNoIDStats(uint64_t val)
831  {
832      if (m_pStatsBlock)
833          m_pStatsBlock->no_id_bytes += val;
834  }
835  
addToFrameStats(uint64_t val)836  void TraceFmtDcdImpl::addToFrameStats(uint64_t val)
837  {
838      if (m_pStatsBlock)
839          m_pStatsBlock->frame_bytes += val;
840  }
841  
addToUnknownIDStats(uint64_t val)842  void TraceFmtDcdImpl::addToUnknownIDStats(uint64_t val)
843  {
844      if (m_pStatsBlock)
845          m_pStatsBlock->unknown_id_bytes += val;
846  }
847  
addToReservedIDStats(uint64_t val)848  void TraceFmtDcdImpl::addToReservedIDStats(uint64_t val)
849  {
850      if (m_pStatsBlock)
851          m_pStatsBlock->reserved_id_bytes += val;
852  }
853  
854  /***************************************************************/
855  /* interface */
856  /***************************************************************/
TraceFormatterFrameDecoder()857  TraceFormatterFrameDecoder::TraceFormatterFrameDecoder() : m_pDecoder(0)
858  {
859      m_instNum = -1;
860  }
861  
TraceFormatterFrameDecoder(int instNum)862  TraceFormatterFrameDecoder::TraceFormatterFrameDecoder(int instNum) : m_pDecoder(0)
863  {
864      m_instNum = instNum;
865  }
866  
~TraceFormatterFrameDecoder()867  TraceFormatterFrameDecoder::~TraceFormatterFrameDecoder()
868  {
869      if(m_pDecoder)
870      {
871          delete m_pDecoder;
872          m_pDecoder = 0;
873      }
874  }
875  
876      /* the data input interface from the reader / source */
TraceDataIn(const ocsd_datapath_op_t op,const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)877  ocsd_datapath_resp_t TraceFormatterFrameDecoder::TraceDataIn(  const ocsd_datapath_op_t op,
878                                                                  const ocsd_trc_index_t index,
879                                                                  const uint32_t dataBlockSize,
880                                                                  const uint8_t *pDataBlock,
881                                                                  uint32_t *numBytesProcessed)
882  {
883      return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed);
884  }
885  
886  /* attach a data processor to a stream ID output */
getIDStreamAttachPt(uint8_t ID)887  componentAttachPt<ITrcDataIn> *TraceFormatterFrameDecoder::getIDStreamAttachPt(uint8_t ID)
888  {
889      componentAttachPt<ITrcDataIn> *pAttachPt = 0;
890      if((ID < 128) && (m_pDecoder != 0))
891          pAttachPt = &(m_pDecoder->m_IDStreams[ID]);
892      return pAttachPt;
893  }
894  
895  /* attach a data processor to the raw frame output */
getTrcRawFrameAttachPt()896  componentAttachPt<ITrcRawFrameIn> *TraceFormatterFrameDecoder::getTrcRawFrameAttachPt()
897  {
898      return (m_pDecoder != 0) ? &m_pDecoder->m_RawTraceFrame : 0;
899  }
900  
901  
getTrcSrcIndexAttachPt()902  componentAttachPt<ITrcSrcIndexCreator> *TraceFormatterFrameDecoder::getTrcSrcIndexAttachPt()
903  {
904      return (m_pDecoder != 0) ? &m_pDecoder->m_SrcIndexer : 0;
905  }
906  
getErrLogAttachPt()907  componentAttachPt<ITraceErrorLog> *TraceFormatterFrameDecoder::getErrLogAttachPt()
908  {
909      return (m_pDecoder != 0) ? m_pDecoder->getErrorLogAttachPt() : 0;
910  }
911  
Init()912  ocsd_err_t TraceFormatterFrameDecoder::Init()
913  {
914      if (!m_pDecoder)
915      {
916          if (m_instNum >= 0)
917              m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(m_instNum);
918          else
919              m_pDecoder = new (std::nothrow) TraceFmtDcdImpl();
920          if (!m_pDecoder) return OCSD_ERR_MEM;
921      }
922      return OCSD_OK;
923  }
924  
925  /* configuration - set operational mode for incoming stream (has FSYNCS etc) */
Configure(uint32_t cfg_flags)926  ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags)
927  {
928      if (!m_pDecoder)
929          return OCSD_ERR_NOT_INIT;
930      return m_pDecoder->DecodeConfigure(cfg_flags);
931  }
932  
getConfigFlags() const933  const uint32_t TraceFormatterFrameDecoder::getConfigFlags() const
934  {
935      uint32_t flags = 0;
936      if(m_pDecoder)
937          flags = m_pDecoder->m_cfgFlags;
938      return flags;
939  }
940  
941  
942  /* enable / disable ID streams - default as all enabled */
OutputFilterIDs(std::vector<uint8_t> & id_list,bool bEnable)943  ocsd_err_t TraceFormatterFrameDecoder::OutputFilterIDs(std::vector<uint8_t> &id_list, bool bEnable)
944  {
945      return (m_pDecoder == 0) ? OCSD_ERR_NOT_INIT : m_pDecoder->OutputFilterIDs(id_list,bEnable);
946  }
947  
OutputFilterAllIDs(bool bEnable)948  ocsd_err_t TraceFormatterFrameDecoder::OutputFilterAllIDs(bool bEnable)
949  {
950      return (m_pDecoder == 0) ? OCSD_ERR_NOT_INIT : m_pDecoder->OutputFilterAllIDs(bEnable);
951  }
952  
953  /* decode control */
Reset()954  ocsd_datapath_resp_t TraceFormatterFrameDecoder::Reset()
955  {
956      return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Reset();
957  }
958  
Flush()959  ocsd_datapath_resp_t TraceFormatterFrameDecoder::Flush()
960  {
961      return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Flush();
962  }
963  
SetDemuxStatsBlock(ocsd_demux_stats_t * pStatsBlock)964  void TraceFormatterFrameDecoder::SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock)
965  {
966      if (m_pDecoder)
967          m_pDecoder->SetDemuxStatsBlock(pStatsBlock);
968  }
969  
970  /* End of File trc_frame_deformatter.cpp */
971