• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         if(dataBlockSize % m_alignment) // must be correctly aligned data
250         {
251             ocsdError err(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PARAM_VAL);
252             char msg_buffer[64];
253             sprintf(msg_buffer,"Input block incorrect size, must be %d byte multiple", m_alignment);
254             err.setMessage(msg_buffer);
255             throw ocsdError(&err);
256         }
257 
258         // record the incoming block for extraction routines to use.
259         m_in_block_base = pDataBlock;
260         m_in_block_size = dataBlockSize;
261         m_in_block_processed = 0;
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         m_cfgFlags = flags;
329         m_alignment = 16;
330         if(flags & OCSD_DFRMTR_HAS_FSYNCS)
331             m_alignment = 4;
332         else if(flags & OCSD_DFRMTR_HAS_HSYNCS)
333             m_alignment = 2;
334     }
335     return err;
336 }
337 
resetStateParams()338 void TraceFmtDcdImpl::resetStateParams()
339 {
340     // overall dynamic state - intra frame
341     m_trc_curr_idx = OCSD_BAD_TRC_INDEX;    /* source index of current trace data */
342     m_frame_synced = false;
343     m_first_data = false;
344     m_curr_src_ID = OCSD_BAD_CS_SRC_ID;
345 
346     // current frame processing
347     m_ex_frm_n_bytes = 0;
348     m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX;
349 }
350 
checkForSync()351 bool TraceFmtDcdImpl::checkForSync()
352 {
353     // we can sync on:-
354     // 16 byte alignment - standard input buffers such as ETB
355     // FSYNC packets in the stream
356     // forced index programmed into the object.
357     uint32_t unsynced_bytes = 0;
358 
359     if(!m_frame_synced)
360     {
361         if(m_use_force_sync)
362         {
363             // is the force sync point in this block?
364             if((m_force_sync_idx >= m_trc_curr_idx) && (m_force_sync_idx < (m_trc_curr_idx + m_in_block_size)))
365             {
366                 unsynced_bytes = m_force_sync_idx - m_trc_curr_idx;
367                 m_frame_synced = true;
368             }
369             else
370             {
371                 unsynced_bytes = m_in_block_size;
372             }
373         }
374         else if( m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS)   // memory aligned data
375         {
376              unsynced_bytes = findfirstFSync();
377 
378         }
379         else
380         {
381             // OCSD_DFRMTR_FRAME_MEM_ALIGN - this has guaranteed 16 byte frame size and alignment.
382             m_frame_synced = true;
383         }
384 
385         if(unsynced_bytes)
386         {
387             outputUnsyncedBytes(unsynced_bytes);
388             m_in_block_processed = unsynced_bytes;
389             m_trc_curr_idx += unsynced_bytes;
390         }
391     }
392     return m_frame_synced;
393 }
394 
findfirstFSync()395 uint32_t TraceFmtDcdImpl::findfirstFSync()
396 {
397     uint32_t processed = 0;
398     const uint32_t FSYNC_PATTERN = 0x7FFFFFFF;    // LE host pattern for FSYNC
399     const uint8_t *dataPtr = m_in_block_base;
400 
401     while (processed < (m_in_block_size - 3))
402     {
403         if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
404         {
405             m_frame_synced = true;
406             break;
407         }
408         processed++;
409         dataPtr++;
410     }
411     return processed;
412 }
413 
outputUnsyncedBytes(uint32_t)414 void TraceFmtDcdImpl::outputUnsyncedBytes(uint32_t /*num_bytes*/)
415 {
416     //**TBD:
417 }
418 
checkForResetFSyncPatterns()419 int TraceFmtDcdImpl::checkForResetFSyncPatterns()
420 {
421 	const uint32_t FSYNC_PATTERN = 0x7FFFFFFF;    // LE host pattern for FSYNC
422 	bool check_for_fsync = true;
423 	int num_fsyncs = 0;
424 	const uint8_t *dataPtr = m_in_block_base + m_in_block_processed;
425 
426 	while (check_for_fsync && (m_in_block_processed < m_in_block_size))
427 	{
428 		// look for consecutive fsyncs as padding or for reset downstream - both cases will reset downstream....
429 		if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
430 		{
431 			dataPtr += sizeof(uint32_t);
432 			num_fsyncs++;
433 		}
434 		else
435 			check_for_fsync = false;
436 	}
437 
438 	if (num_fsyncs)
439 	{
440 		if ((num_fsyncs % 4) == 0)
441         {
442             // reset the upstream decoders
443 			executeNoneDataOpAllIDs(OCSD_OP_RESET,m_trc_curr_idx);
444 
445             // reset the intra frame parameters
446             m_curr_src_ID = OCSD_BAD_CS_SRC_ID;
447             m_ex_frm_n_bytes = 0;
448             m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX;
449         }
450 		else
451 		{
452 			// TBD: throw processing error, none frame size block of fsyncs
453 		}
454 	}
455     return num_fsyncs * 4;
456 }
457 
458 
extractFrame()459 bool TraceFmtDcdImpl::extractFrame()
460 {
461 	const uint32_t FSYNC_PATTERN = 0x7FFFFFFF;    // LE host pattern for FSYNC
462 	const uint16_t HSYNC_PATTERN = 0x7FFF;        // LE host pattern for HSYNC
463 
464 
465 	bool cont_process = true;   // continue processing after extraction.
466     uint32_t f_sync_bytes = 0; // skipped f sync bytes
467     uint32_t h_sync_bytes = 0; // skipped h sync bytes
468     uint32_t ex_bytes = 0;  // extracted this pass (may be filling out part frame)
469 
470     // memory aligned sources are always multiples of frames, aligned to start.
471     if( m_cfgFlags & OCSD_DFRMTR_FRAME_MEM_ALIGN)
472     {
473 		// some linux drivers (e.g. for perf) will insert FSYNCS to pad or differentiate
474         // between blocks of aligned data, always in frame aligned complete 16 byte frames.
475         if (m_cfgFlags & OCSD_DFRMTR_RESET_ON_4X_FSYNC)
476         {
477             f_sync_bytes = checkForResetFSyncPatterns();
478 
479             /* in this case the FSYNC pattern is output on both packed and unpacked cases */
480             if (f_sync_bytes && (m_b_output_packed_raw || m_b_output_unpacked_raw))
481             {
482                 outputRawMonBytes(OCSD_OP_DATA,
483                     m_trc_curr_idx,
484                     OCSD_FRM_FSYNC,
485                     f_sync_bytes,
486                     m_in_block_base + m_in_block_processed,
487                     0);
488             }
489         }
490 
491         if((m_in_block_processed+f_sync_bytes) == m_in_block_size)
492         {
493             m_ex_frm_n_bytes = 0;
494             cont_process = false;   // end of input data.
495         }
496 		else
497 		{
498 			// always a complete frame.
499 			m_ex_frm_n_bytes = OCSD_DFRMTR_FRAME_SIZE;
500 			memcpy(m_ex_frm_data, m_in_block_base + m_in_block_processed + f_sync_bytes, m_ex_frm_n_bytes);
501 			m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;
502 			ex_bytes = OCSD_DFRMTR_FRAME_SIZE;
503         }
504     }
505     else
506     {
507         // extract data accounting for frame syncs and hsyncs if present.
508         // we know we are aligned at this point - could be FSYNC or HSYNCs here.
509 
510         // check what we a looking for
511         bool hasFSyncs =  ((m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) == OCSD_DFRMTR_HAS_FSYNCS);
512         bool hasHSyncs =  ((m_cfgFlags & OCSD_DFRMTR_HAS_HSYNCS) == OCSD_DFRMTR_HAS_HSYNCS);
513 
514         const uint8_t *dataPtr = m_in_block_base+m_in_block_processed;
515         const uint8_t *eodPtr = m_in_block_base+m_in_block_size;
516 
517         cont_process = (bool)(dataPtr < eodPtr);
518 
519         // can have FSYNCS at start of frame (in middle is an error).
520         if(hasFSyncs && cont_process && (m_ex_frm_n_bytes == 0))
521         {
522             while((*((uint32_t *)(dataPtr)) == FSYNC_PATTERN) && cont_process)
523             {
524                 f_sync_bytes += 4;
525                 dataPtr += 4;
526                 cont_process = (bool)(dataPtr < eodPtr);
527             }
528         }
529 
530         // not an FSYNC
531         while((m_ex_frm_n_bytes < OCSD_DFRMTR_FRAME_SIZE) && cont_process)
532         {
533             // check for illegal out of sequence FSYNC
534             if((m_ex_frm_n_bytes % 4) == 0)
535             {
536                 if(*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
537                 {
538                     // throw an illegal FSYNC error
539                     throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad FSYNC in frame.");
540                 }
541             }
542 
543             // mark start of frame after FSyncs
544             if(m_ex_frm_n_bytes == 0)
545                 m_trc_curr_idx_sof = m_trc_curr_idx + f_sync_bytes;
546 
547             m_ex_frm_data[m_ex_frm_n_bytes] = dataPtr[0];
548             m_ex_frm_data[m_ex_frm_n_bytes+1] = dataPtr[1];
549             m_ex_frm_n_bytes+=2;
550             ex_bytes +=2;
551 
552             // check pair is not HSYNC
553             if(*((uint16_t *)(dataPtr)) == HSYNC_PATTERN)
554             {
555                 if(hasHSyncs)
556                 {
557                     m_ex_frm_n_bytes-=2;
558                     ex_bytes -= 2;
559                     h_sync_bytes+=2;
560                 }
561                 else
562                 {
563                     // throw illegal HSYNC error.
564                     throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_DFMTR_BAD_FHSYNC, m_trc_curr_idx, "Bad HSYNC in frame.");
565                 }
566             }
567 
568             dataPtr += 2;
569             cont_process = (bool)(dataPtr < eodPtr);
570         }
571 
572         // if we hit the end of data but still have a complete frame waiting,
573         // need to continue processing to allow it to be used.
574         if(!cont_process && (m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE))
575             cont_process = true;
576     }
577 
578     // total bytes processed this pass
579     uint32_t total_processed = ex_bytes + f_sync_bytes + h_sync_bytes;
580 
581     // output raw data on raw frame channel - packed raw.
582     if (((m_ex_frm_n_bytes == OCSD_DFRMTR_FRAME_SIZE) || !cont_process) && m_b_output_packed_raw)
583     {
584         outputRawMonBytes(  OCSD_OP_DATA,
585                             m_trc_curr_idx,
586                             OCSD_FRM_PACKED,
587                             total_processed,
588                             m_in_block_base+m_in_block_processed,
589                             0);
590     }
591 
592     // update the processed count for the buffer
593     m_in_block_processed += total_processed;
594 
595     // update index past the processed data
596     m_trc_curr_idx += total_processed;
597 
598     // update any none trace data byte stats
599     addToFrameStats((uint64_t)(f_sync_bytes + h_sync_bytes));
600 
601     return cont_process;
602 }
603 
unpackFrame()604 bool TraceFmtDcdImpl::unpackFrame()
605 {
606     // unpack cannot fail as never called on incomplete frame.
607     uint8_t frameFlagBit = 0x1;
608     uint8_t newSrcID = OCSD_BAD_CS_SRC_ID;
609     bool PrevIDandIDChange = false;
610     uint64_t noneDataBytes = 0;
611 
612     // init output processing
613     m_out_data_idx = 0;
614     m_out_processed = 0;
615 
616     // set up first out data packet...
617     m_out_data[m_out_data_idx].id = m_curr_src_ID;
618     m_out_data[m_out_data_idx].valid = 0;
619     m_out_data[m_out_data_idx].index =  m_trc_curr_idx_sof;
620     m_out_data[m_out_data_idx].used = 0;
621 
622     // work on byte pairs - bytes 0 - 13.
623     for(int i = 0; i < 14; i+=2)
624     {
625         PrevIDandIDChange = false;
626 
627         // it's an ID + data
628         if(m_ex_frm_data[i] & 0x1)
629         {
630             newSrcID = (m_ex_frm_data[i] >> 1) & 0x7f;
631             if(newSrcID != m_curr_src_ID)   // ID change
632             {
633                 PrevIDandIDChange = ((frameFlagBit & m_ex_frm_data[15]) != 0);
634 
635                 // following byte for old id?
636                 if(PrevIDandIDChange)
637                     // 2nd byte always data
638                     m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i+1];
639 
640                 // change ID
641                 m_curr_src_ID = newSrcID;
642 
643                 // if we already have data in this buffer
644                 if(m_out_data[m_out_data_idx].valid > 0)
645                 {
646                     m_out_data_idx++; // move to next buffer
647                     m_out_data[m_out_data_idx].valid = 0;
648                     m_out_data[m_out_data_idx].used = 0;
649                     m_out_data[m_out_data_idx].index = m_trc_curr_idx_sof + i;
650                 }
651 
652                 // set new ID on buffer
653                 m_out_data[m_out_data_idx].id = m_curr_src_ID;
654 
655                 /// TBD - ID indexing in here.
656             }
657             noneDataBytes++;
658         }
659         else
660         // it's just data
661         {
662             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);
663         }
664 
665         // 2nd byte always data
666         if(!PrevIDandIDChange) // output only if we didn't for an ID change + prev ID.
667             m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i+1];
668 
669         frameFlagBit <<= 1;
670     }
671 
672     // unpack byte 14;
673 
674     // it's an ID
675     if(m_ex_frm_data[14] & 0x1)
676     {
677         // no matter if change or not, no associated data in byte 15 anyway so just set.
678         m_curr_src_ID = (m_ex_frm_data[14] >> 1) & 0x7f;
679         noneDataBytes++;
680     }
681     // it's data
682     else
683     {
684         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);
685     }
686     m_ex_frm_n_bytes = 0;   // mark frame as empty;
687 
688     noneDataBytes++;    // byte 15 is always non-data.
689     addToFrameStats(noneDataBytes); // update the non data byte stats.
690     return true;
691 }
692 
693 // output data to channels.
outputFrame()694 bool TraceFmtDcdImpl::outputFrame()
695 {
696     bool cont_processing = true;
697     ITrcDataIn *pDataIn = 0;
698     uint32_t bytes_used;
699 
700     // output each valid ID within the frame - stopping if we get a wait or error
701     while((m_out_processed < (m_out_data_idx + 1)) && cont_processing)
702     {
703 
704         // may have data prior to a valid ID appearing
705         if(m_out_data[m_out_processed].id != OCSD_BAD_CS_SRC_ID)
706         {
707             if((pDataIn = m_IDStreams[m_out_data[m_out_processed].id].first()) != 0)
708             {
709                 // log the stuff we are about to put out early so as to make it visible before interpretation
710                 // however, don't re-output if only part used first time round.
711                 if(m_b_output_unpacked_raw && (m_out_data[m_out_processed].used == 0) && rawChanEnabled( m_out_data[m_out_processed].id))
712                 {
713                     outputRawMonBytes( OCSD_OP_DATA,
714                             m_out_data[m_out_processed].index,
715                             OCSD_FRM_ID_DATA,
716                             m_out_data[m_out_processed].valid,
717                             m_out_data[m_out_processed].data,
718                             m_out_data[m_out_processed].id);
719                 }
720 
721                 // output to the connected packet process
722                 CollateDataPathResp(pDataIn->TraceDataIn(OCSD_OP_DATA,
723                     m_out_data[m_out_processed].index + m_out_data[m_out_processed].used,
724                     m_out_data[m_out_processed].valid - m_out_data[m_out_processed].used,
725                     m_out_data[m_out_processed].data + m_out_data[m_out_processed].used,
726                     &bytes_used));
727 
728                 addToIDStats((uint64_t)bytes_used);
729 
730                 if(!dataPathCont())
731                 {
732                     cont_processing = false;
733                     m_out_data[m_out_processed].used += bytes_used;
734                     if(m_out_data[m_out_processed].used == m_out_data[m_out_processed].valid)
735                         m_out_processed++; // we have used up all this data.
736                 }
737                 else
738                 {
739                     m_out_processed++; // we have sent this data;
740                 }
741             }
742             else
743             {
744                 // optional raw output for debugging / monitor tools
745                 if(m_b_output_unpacked_raw && rawChanEnabled( m_out_data[m_out_processed].id))
746                 {
747                     outputRawMonBytes(  OCSD_OP_DATA,
748                         m_out_data[m_out_processed].index,
749                         OCSD_FRM_ID_DATA,
750                         m_out_data[m_out_processed].valid,
751                         m_out_data[m_out_processed].data,
752                         m_out_data[m_out_processed].id);
753                 }
754 
755                 if (isReservedID(m_out_data[m_out_processed].id))
756                     addToReservedIDStats((uint64_t)m_out_data[m_out_processed].valid);
757                 else
758                     addToNoIDStats((uint64_t)m_out_data[m_out_processed].valid);
759                 m_out_processed++; // skip past this data.
760             }
761         }
762         else
763         {
764             // optional raw output for debugging / monitor tools of unknown src ID data
765             if(m_b_output_unpacked_raw)
766             {
767                 outputRawMonBytes(  OCSD_OP_DATA,
768                     m_out_data[m_out_processed].index,
769                     OCSD_FRM_ID_DATA,
770                     m_out_data[m_out_processed].valid,
771                     m_out_data[m_out_processed].data,
772                     m_out_data[m_out_processed].id);
773             }
774             addToUnknownIDStats((uint64_t)m_out_data[m_out_processed].valid);
775             m_out_processed++; // skip past this data.
776         }
777     }
778     return cont_processing;
779 }
780 
addToIDStats(uint64_t val)781 void TraceFmtDcdImpl::addToIDStats(uint64_t val)
782 {
783     if (m_pStatsBlock)
784         m_pStatsBlock->valid_id_bytes += val;
785 }
786 
addToNoIDStats(uint64_t val)787 void TraceFmtDcdImpl::addToNoIDStats(uint64_t val)
788 {
789     if (m_pStatsBlock)
790         m_pStatsBlock->no_id_bytes += val;
791 }
792 
addToFrameStats(uint64_t val)793 void TraceFmtDcdImpl::addToFrameStats(uint64_t val)
794 {
795     if (m_pStatsBlock)
796         m_pStatsBlock->frame_bytes += val;
797 }
798 
addToUnknownIDStats(uint64_t val)799 void TraceFmtDcdImpl::addToUnknownIDStats(uint64_t val)
800 {
801     if (m_pStatsBlock)
802         m_pStatsBlock->unknown_id_bytes += val;
803 }
804 
addToReservedIDStats(uint64_t val)805 void TraceFmtDcdImpl::addToReservedIDStats(uint64_t val)
806 {
807     if (m_pStatsBlock)
808         m_pStatsBlock->reserved_id_bytes += val;
809 }
810 
811 /***************************************************************/
812 /* interface */
813 /***************************************************************/
TraceFormatterFrameDecoder()814 TraceFormatterFrameDecoder::TraceFormatterFrameDecoder() : m_pDecoder(0)
815 {
816     m_instNum = -1;
817 }
818 
TraceFormatterFrameDecoder(int instNum)819 TraceFormatterFrameDecoder::TraceFormatterFrameDecoder(int instNum) : m_pDecoder(0)
820 {
821     m_instNum = instNum;
822 }
823 
~TraceFormatterFrameDecoder()824 TraceFormatterFrameDecoder::~TraceFormatterFrameDecoder()
825 {
826     if(m_pDecoder)
827     {
828         delete m_pDecoder;
829         m_pDecoder = 0;
830     }
831 }
832 
833     /* 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)834 ocsd_datapath_resp_t TraceFormatterFrameDecoder::TraceDataIn(  const ocsd_datapath_op_t op,
835                                                                 const ocsd_trc_index_t index,
836                                                                 const uint32_t dataBlockSize,
837                                                                 const uint8_t *pDataBlock,
838                                                                 uint32_t *numBytesProcessed)
839 {
840     return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed);
841 }
842 
843 /* attach a data processor to a stream ID output */
getIDStreamAttachPt(uint8_t ID)844 componentAttachPt<ITrcDataIn> *TraceFormatterFrameDecoder::getIDStreamAttachPt(uint8_t ID)
845 {
846     componentAttachPt<ITrcDataIn> *pAttachPt = 0;
847     if((ID < 128) && (m_pDecoder != 0))
848         pAttachPt = &(m_pDecoder->m_IDStreams[ID]);
849     return pAttachPt;
850 }
851 
852 /* attach a data processor to the raw frame output */
getTrcRawFrameAttachPt()853 componentAttachPt<ITrcRawFrameIn> *TraceFormatterFrameDecoder::getTrcRawFrameAttachPt()
854 {
855     return (m_pDecoder != 0) ? &m_pDecoder->m_RawTraceFrame : 0;
856 }
857 
858 
getTrcSrcIndexAttachPt()859 componentAttachPt<ITrcSrcIndexCreator> *TraceFormatterFrameDecoder::getTrcSrcIndexAttachPt()
860 {
861     return (m_pDecoder != 0) ? &m_pDecoder->m_SrcIndexer : 0;
862 }
863 
getErrLogAttachPt()864 componentAttachPt<ITraceErrorLog> *TraceFormatterFrameDecoder::getErrLogAttachPt()
865 {
866     return (m_pDecoder != 0) ? m_pDecoder->getErrorLogAttachPt() : 0;
867 }
868 
869 /* configuration - set operational mode for incoming stream (has FSYNCS etc) */
Configure(uint32_t cfg_flags)870 ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags)
871 {
872     if(!m_pDecoder)
873     {
874         if(m_instNum >= 0)
875             m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(m_instNum);
876         else
877             m_pDecoder = new (std::nothrow) TraceFmtDcdImpl();
878         if(!m_pDecoder) return OCSD_ERR_MEM;
879     }
880     m_pDecoder->DecodeConfigure(cfg_flags);
881     return OCSD_OK;
882 }
883 
getConfigFlags() const884 const uint32_t TraceFormatterFrameDecoder::getConfigFlags() const
885 {
886     uint32_t flags = 0;
887     if(m_pDecoder)
888         flags = m_pDecoder->m_cfgFlags;
889     return flags;
890 }
891 
892 
893 /* enable / disable ID streams - default as all enabled */
OutputFilterIDs(std::vector<uint8_t> & id_list,bool bEnable)894 ocsd_err_t TraceFormatterFrameDecoder::OutputFilterIDs(std::vector<uint8_t> &id_list, bool bEnable)
895 {
896     return (m_pDecoder == 0) ? OCSD_ERR_NOT_INIT : m_pDecoder->OutputFilterIDs(id_list,bEnable);
897 }
898 
OutputFilterAllIDs(bool bEnable)899 ocsd_err_t TraceFormatterFrameDecoder::OutputFilterAllIDs(bool bEnable)
900 {
901     return (m_pDecoder == 0) ? OCSD_ERR_NOT_INIT : m_pDecoder->OutputFilterAllIDs(bEnable);
902 }
903 
904 /* decode control */
Reset()905 ocsd_datapath_resp_t TraceFormatterFrameDecoder::Reset()
906 {
907     return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Reset();
908 }
909 
Flush()910 ocsd_datapath_resp_t TraceFormatterFrameDecoder::Flush()
911 {
912     return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Flush();
913 }
914 
SetDemuxStatsBlock(ocsd_demux_stats_t * pStatsBlock)915 void TraceFormatterFrameDecoder::SetDemuxStatsBlock(ocsd_demux_stats_t *pStatsBlock)
916 {
917     if (m_pDecoder)
918         m_pDecoder->SetDemuxStatsBlock(pStatsBlock);
919 }
920 
921 /* End of File trc_frame_deformatter.cpp */
922