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