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