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
59 {
60 resetStateParams();
61 setRawChanFilterAll(true);
62 }
63
TraceFmtDcdImpl(int instNum)64 TraceFmtDcdImpl::TraceFmtDcdImpl(int instNum) : TraceComponent(DEFORMATTER_NAME, instNum),
65 m_cfgFlags(0),
66 m_force_sync_idx(0),
67 m_use_force_sync(false),
68 m_alignment(16)
69 {
70 resetStateParams();
71 setRawChanFilterAll(true);
72 }
73
~TraceFmtDcdImpl()74 TraceFmtDcdImpl::~TraceFmtDcdImpl()
75 {
76 }
77
TraceDataIn(const ocsd_datapath_op_t op,const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)78 ocsd_datapath_resp_t TraceFmtDcdImpl::TraceDataIn(
79 const ocsd_datapath_op_t op,
80 const ocsd_trc_index_t index,
81 const uint32_t dataBlockSize,
82 const uint8_t *pDataBlock,
83 uint32_t *numBytesProcessed)
84 {
85 ocsd_datapath_resp_t resp = OCSD_RESP_FATAL_INVALID_OP;
86 InitCollateDataPathResp();
87
88 m_b_output_packed_raw = m_RawTraceFrame.num_attached() && ((m_cfgFlags & OCSD_DFRMTR_PACKED_RAW_OUT) != 0);
89 m_b_output_unpacked_raw = m_RawTraceFrame.num_attached() && ((m_cfgFlags & OCSD_DFRMTR_UNPACKED_RAW_OUT) != 0);
90
91 switch(op)
92 {
93 case OCSD_OP_RESET:
94 resp = Reset();
95 break;
96
97 case OCSD_OP_FLUSH:
98 resp = Flush();
99 break;
100
101 case OCSD_OP_EOT:
102 // local 'flush' here?
103 // pass on EOT to connected ID streams
104 resp = executeNoneDataOpAllIDs(OCSD_OP_EOT);
105 break;
106
107 case OCSD_OP_DATA:
108 if((dataBlockSize <= 0) || ( pDataBlock == 0) || (numBytesProcessed == 0))
109 resp = OCSD_RESP_FATAL_INVALID_PARAM;
110 else
111 resp = processTraceData(index,dataBlockSize, pDataBlock, numBytesProcessed);
112 break;
113
114 default:
115 break;
116 }
117
118 return resp;
119 }
120
121 /* enable / disable ID streams - default as all enabled */
OutputFilterIDs(std::vector<uint8_t> & id_list,bool bEnable)122 ocsd_err_t TraceFmtDcdImpl::OutputFilterIDs(std::vector<uint8_t> &id_list, bool bEnable)
123 {
124 ocsd_err_t err = OCSD_OK;
125 std::vector<uint8_t>::iterator iter = id_list.begin();
126 uint8_t id = 0;
127
128 while((iter < id_list.end()) && (err == OCSD_OK))
129 {
130 id = *iter;
131 if(id > 128)
132 err = OCSD_ERR_INVALID_ID;
133 else
134 {
135 m_IDStreams[id].set_enabled(bEnable);
136 m_raw_chan_enable[id] = bEnable;
137 }
138 iter++;
139 }
140 return err;
141 }
142
OutputFilterAllIDs(bool bEnable)143 ocsd_err_t TraceFmtDcdImpl::OutputFilterAllIDs(bool bEnable)
144 {
145 for(uint8_t id = 0; id < 128; id++)
146 {
147 m_IDStreams[id].set_enabled(bEnable);
148 }
149 setRawChanFilterAll(bEnable);
150 return OCSD_OK;
151 }
152
setRawChanFilterAll(bool bEnable)153 void TraceFmtDcdImpl::setRawChanFilterAll(bool bEnable)
154 {
155 for(int i=0; i<128; i++)
156 {
157 m_raw_chan_enable[i] = bEnable;
158 }
159 }
160
rawChanEnabled(const uint8_t id) const161 const bool TraceFmtDcdImpl::rawChanEnabled(const uint8_t id) const
162 {
163 if(id < 128)
164 return m_raw_chan_enable[id];
165 return false;
166 }
167
168 /* decode control */
Reset()169 ocsd_datapath_resp_t TraceFmtDcdImpl::Reset()
170 {
171 resetStateParams();
172 InitCollateDataPathResp();
173 return executeNoneDataOpAllIDs(OCSD_OP_RESET);
174 }
175
Flush()176 ocsd_datapath_resp_t TraceFmtDcdImpl::Flush()
177 {
178 executeNoneDataOpAllIDs(OCSD_OP_FLUSH); // flush any upstream data.
179 if(dataPathCont())
180 outputFrame(); // try to flush any partial frame data remaining
181 return highestDataPathResp();
182 }
183
executeNoneDataOpAllIDs(ocsd_datapath_op_t op,const ocsd_trc_index_t index)184 ocsd_datapath_resp_t TraceFmtDcdImpl::executeNoneDataOpAllIDs(ocsd_datapath_op_t op,
185 const ocsd_trc_index_t index /* = 0*/)
186 {
187 ITrcDataIn *pTrcComp = 0;
188 for(uint8_t id = 0; id < 128; id++)
189 {
190 if(m_IDStreams[id].num_attached())
191 {
192 pTrcComp = m_IDStreams[id].first();
193 while(pTrcComp)
194 {
195 CollateDataPathResp(pTrcComp->TraceDataIn(op,index,0,0,0));
196 pTrcComp = m_IDStreams[id].next();
197 }
198 }
199 }
200
201 if( m_RawTraceFrame.num_attached())
202 {
203 if(m_RawTraceFrame.first())
204 m_RawTraceFrame.first()->TraceRawFrameIn(op,0,OCSD_FRM_NONE,0,0,0);
205 }
206 return highestDataPathResp();
207 }
208
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)209 void TraceFmtDcdImpl::outputRawMonBytes(const ocsd_datapath_op_t op,
210 const ocsd_trc_index_t index,
211 const ocsd_rawframe_elem_t frame_element,
212 const int dataBlockSize,
213 const uint8_t *pDataBlock,
214 const uint8_t traceID)
215 {
216 if( m_RawTraceFrame.num_attached())
217 {
218 if(m_RawTraceFrame.first())
219 m_RawTraceFrame.first()->TraceRawFrameIn(op,index,frame_element,dataBlockSize, pDataBlock,traceID);
220 }
221 }
222
CollateDataPathResp(const ocsd_datapath_resp_t resp)223 void TraceFmtDcdImpl::CollateDataPathResp(const ocsd_datapath_resp_t resp)
224 {
225 // simple most severe error across multiple IDs.
226 if(resp > m_highestResp) m_highestResp = resp;
227 }
228
processTraceData(const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)229 ocsd_datapath_resp_t TraceFmtDcdImpl::processTraceData(
230 const ocsd_trc_index_t index,
231 const uint32_t dataBlockSize,
232 const uint8_t *pDataBlock,
233 uint32_t *numBytesProcessed
234 )
235 {
236 try {
237
238 if(!m_first_data) // is this the initial data block?
239 {
240 m_trc_curr_idx = index;
241 }
242 else
243 {
244 if(m_trc_curr_idx != index) // none continuous trace data - throw an error.
245 throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_DFMTR_NOTCONTTRACE,index);
246 }
247
248 if(dataBlockSize % m_alignment) // must be correctly aligned data
249 {
250 ocsdError err(OCSD_ERR_SEV_ERROR, OCSD_ERR_INVALID_PARAM_VAL);
251 char msg_buffer[64];
252 sprintf(msg_buffer,"Input block incorrect size, must be %d byte multiple", m_alignment);
253 err.setMessage(msg_buffer);
254 throw ocsdError(&err);
255 }
256
257 // record the incoming block for extraction routines to use.
258 m_in_block_base = pDataBlock;
259 m_in_block_size = dataBlockSize;
260 m_in_block_processed = 0;
261
262 // processing loop...
263 if(checkForSync())
264 {
265 bool bProcessing = true;
266 while(bProcessing)
267 {
268 bProcessing = extractFrame(); // will stop on end of input data.
269 if(bProcessing)
270 bProcessing = unpackFrame();
271 if(bProcessing)
272 bProcessing = outputFrame(); // will stop on data path halt.
273 }
274 }
275 }
276 catch(const ocsdError &err) {
277 LogError(err);
278 CollateDataPathResp(OCSD_RESP_FATAL_INVALID_DATA);
279 }
280 catch(...) {
281 LogError(ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_FAIL));
282 CollateDataPathResp(OCSD_RESP_FATAL_SYS_ERR);
283 }
284
285 if(!m_first_data)
286 m_first_data = true;
287
288 // update the outputs.
289 *numBytesProcessed = m_in_block_processed;
290
291 return highestDataPathResp();
292 }
293
DecodeConfigure(uint32_t flags)294 ocsd_err_t TraceFmtDcdImpl::DecodeConfigure(uint32_t flags)
295 {
296 const char *pszErrMsg = "";
297 ocsd_err_t err = OCSD_OK;
298
299 if((flags & ~OCSD_DFRMTR_VALID_MASK) != 0)
300 {
301 err = OCSD_ERR_INVALID_PARAM_VAL;
302 pszErrMsg = "Unknown Config Flags";
303 }
304
305 if((flags & OCSD_DFRMTR_VALID_MASK) == 0)
306 {
307 err = OCSD_ERR_INVALID_PARAM_VAL;
308 pszErrMsg = "No Config Flags Set";
309 }
310
311 if((flags & (OCSD_DFRMTR_HAS_FSYNCS | OCSD_DFRMTR_HAS_HSYNCS)) &&
312 (flags & OCSD_DFRMTR_FRAME_MEM_ALIGN)
313 )
314 {
315 err = OCSD_ERR_INVALID_PARAM_VAL;
316 pszErrMsg = "Invalid Config Flag Combination Set";
317 }
318
319 if(err != OCSD_OK)
320 {
321 ocsdError errObj(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL);
322 errObj.setMessage(pszErrMsg);
323 LogError(errObj);
324 }
325 else
326 {
327 m_cfgFlags = flags;
328 m_alignment = 16;
329 if(flags & OCSD_DFRMTR_HAS_FSYNCS)
330 m_alignment = 4;
331 else if(flags & OCSD_DFRMTR_HAS_HSYNCS)
332 m_alignment = 2;
333 }
334 return err;
335 }
336
resetStateParams()337 void TraceFmtDcdImpl::resetStateParams()
338 {
339 // overall dynamic state - intra frame
340 m_trc_curr_idx = OCSD_BAD_TRC_INDEX; /* source index of current trace data */
341 m_frame_synced = false;
342 m_first_data = false;
343 m_curr_src_ID = OCSD_BAD_CS_SRC_ID;
344
345 // current frame processing
346 m_ex_frm_n_bytes = 0;
347 m_trc_curr_idx_sof = OCSD_BAD_TRC_INDEX;
348 }
349
checkForSync()350 bool TraceFmtDcdImpl::checkForSync()
351 {
352 // we can sync on:-
353 // 16 byte alignment - standard input buffers such as ETB
354 // FSYNC packets in the stream
355 // forced index programmed into the object.
356 uint32_t unsynced_bytes = 0;
357
358 if(!m_frame_synced)
359 {
360 if(m_use_force_sync)
361 {
362 // is the force sync point in this block?
363 if((m_force_sync_idx >= m_trc_curr_idx) && (m_force_sync_idx < (m_trc_curr_idx + m_in_block_size)))
364 {
365 unsynced_bytes = m_force_sync_idx - m_trc_curr_idx;
366 m_frame_synced = true;
367 }
368 else
369 {
370 unsynced_bytes = m_in_block_size;
371 }
372 }
373 else if( m_cfgFlags & OCSD_DFRMTR_HAS_FSYNCS) // memory aligned data
374 {
375 unsynced_bytes = findfirstFSync();
376
377 }
378 else
379 {
380 // OCSD_DFRMTR_FRAME_MEM_ALIGN - this has guaranteed 16 byte frame size and alignment.
381 m_frame_synced = true;
382 }
383
384 if(unsynced_bytes)
385 {
386 outputUnsyncedBytes(unsynced_bytes);
387 m_in_block_processed = unsynced_bytes;
388 m_trc_curr_idx += unsynced_bytes;
389 }
390 }
391 return m_frame_synced;
392 }
393
findfirstFSync()394 uint32_t TraceFmtDcdImpl::findfirstFSync()
395 {
396 uint32_t processed = 0;
397 const uint32_t FSYNC_PATTERN = 0x7FFFFFFF; // LE host pattern for FSYNC
398 const uint8_t *dataPtr = m_in_block_base;
399
400 while (processed < (m_in_block_size - 3))
401 {
402 if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
403 {
404 m_frame_synced = true;
405 break;
406 }
407 processed++;
408 dataPtr++;
409 }
410 return processed;
411 }
412
outputUnsyncedBytes(uint32_t)413 void TraceFmtDcdImpl::outputUnsyncedBytes(uint32_t /*num_bytes*/)
414 {
415 //**TBD:
416 }
417
checkForResetFSyncPatterns()418 int TraceFmtDcdImpl::checkForResetFSyncPatterns()
419 {
420 const uint32_t FSYNC_PATTERN = 0x7FFFFFFF; // LE host pattern for FSYNC
421 bool check_for_fsync = true;
422 int num_fsyncs = 0;
423 const uint8_t *dataPtr = m_in_block_base + m_in_block_processed;
424
425 while (check_for_fsync && (m_in_block_processed < m_in_block_size))
426 {
427 // look for consecutive fsyncs as padding or for reset downstream - both cases will reset downstream....
428 if (*((uint32_t *)(dataPtr)) == FSYNC_PATTERN)
429 {
430 dataPtr += sizeof(uint32_t);
431 num_fsyncs++;
432 }
433 else
434 check_for_fsync = false;
435 }
436
437 if (num_fsyncs)
438 {
439 printf("Frame deformatter: Found %d FSYNCS\n",num_fsyncs);
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 return cont_process;
599 }
600
unpackFrame()601 bool TraceFmtDcdImpl::unpackFrame()
602 {
603 // unpack cannot fail as never called on incomplete frame.
604 uint8_t frameFlagBit = 0x1;
605 uint8_t newSrcID = OCSD_BAD_CS_SRC_ID;
606 bool PrevIDandIDChange = false;
607
608 // init output processing
609 m_out_data_idx = 0;
610 m_out_processed = 0;
611
612 // set up first out data packet...
613 m_out_data[m_out_data_idx].id = m_curr_src_ID;
614 m_out_data[m_out_data_idx].valid = 0;
615 m_out_data[m_out_data_idx].index = m_trc_curr_idx_sof;
616 m_out_data[m_out_data_idx].used = 0;
617
618 // work on byte pairs - bytes 0 - 13.
619 for(int i = 0; i < 14; i+=2)
620 {
621 PrevIDandIDChange = false;
622
623 // it's an ID + data
624 if(m_ex_frm_data[i] & 0x1)
625 {
626 newSrcID = (m_ex_frm_data[i] >> 1) & 0x7f;
627 if(newSrcID != m_curr_src_ID) // ID change
628 {
629 PrevIDandIDChange = ((frameFlagBit & m_ex_frm_data[15]) != 0);
630
631 // following byte for old id?
632 if(PrevIDandIDChange)
633 // 2nd byte always data
634 m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i+1];
635
636 // change ID
637 m_curr_src_ID = newSrcID;
638
639 // if we already have data in this buffer
640 if(m_out_data[m_out_data_idx].valid > 0)
641 {
642 m_out_data_idx++; // move to next buffer
643 m_out_data[m_out_data_idx].valid = 0;
644 m_out_data[m_out_data_idx].used = 0;
645 m_out_data[m_out_data_idx].index = m_trc_curr_idx_sof + i;
646 }
647
648 // set new ID on buffer
649 m_out_data[m_out_data_idx].id = m_curr_src_ID;
650
651 /// TBD - ID indexing in here.
652 }
653 }
654 else
655 // it's just data
656 {
657 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);
658 }
659
660 // 2nd byte always data
661 if(!PrevIDandIDChange) // output only if we didn't for an ID change + prev ID.
662 m_out_data[m_out_data_idx].data[m_out_data[m_out_data_idx].valid++] = m_ex_frm_data[i+1];
663
664 frameFlagBit <<= 1;
665 }
666
667 // unpack byte 14;
668
669 // it's an ID
670 if(m_ex_frm_data[14] & 0x1)
671 {
672 // no matter if change or not, no associated data in byte 15 anyway so just set.
673 m_curr_src_ID = (m_ex_frm_data[14] >> 1) & 0x7f;
674 }
675 // it's data
676 else
677 {
678 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);
679 }
680 m_ex_frm_n_bytes = 0; // mark frame as empty;
681 return true;
682 }
683
684 // output data to channels.
outputFrame()685 bool TraceFmtDcdImpl::outputFrame()
686 {
687 bool cont_processing = true;
688 ITrcDataIn *pDataIn = 0;
689 uint32_t bytes_used;
690
691 // output each valid ID within the frame - stopping if we get a wait or error
692 while((m_out_processed < (m_out_data_idx + 1)) && cont_processing)
693 {
694
695 // may have data prior to a valid ID appearing
696 if(m_out_data[m_out_processed].id != OCSD_BAD_CS_SRC_ID)
697 {
698 if((pDataIn = m_IDStreams[m_out_data[m_out_processed].id].first()) != 0)
699 {
700 // log the stuff we are about to put out early so as to make it visible before interpretation
701 // however, don't re-output if only part used first time round.
702 if(m_b_output_unpacked_raw && (m_out_data[m_out_processed].used == 0) && rawChanEnabled( m_out_data[m_out_processed].id))
703 {
704 outputRawMonBytes( OCSD_OP_DATA,
705 m_out_data[m_out_processed].index,
706 OCSD_FRM_ID_DATA,
707 m_out_data[m_out_processed].valid,
708 m_out_data[m_out_processed].data,
709 m_out_data[m_out_processed].id);
710 }
711
712 // output to the connected packet process
713 CollateDataPathResp(pDataIn->TraceDataIn(OCSD_OP_DATA,
714 m_out_data[m_out_processed].index + m_out_data[m_out_processed].used,
715 m_out_data[m_out_processed].valid - m_out_data[m_out_processed].used,
716 m_out_data[m_out_processed].data + m_out_data[m_out_processed].used,
717 &bytes_used));
718
719 if(!dataPathCont())
720 {
721 cont_processing = false;
722 m_out_data[m_out_processed].used += bytes_used;
723 if(m_out_data[m_out_processed].used == m_out_data[m_out_processed].valid)
724 m_out_processed++; // we have used up all this data.
725 }
726 else
727 {
728 m_out_processed++; // we have sent this data;
729 }
730 }
731 else
732 {
733 // optional raw output for debugging / monitor tools
734 if(m_b_output_unpacked_raw && rawChanEnabled( m_out_data[m_out_processed].id))
735 {
736 outputRawMonBytes( OCSD_OP_DATA,
737 m_out_data[m_out_processed].index,
738 OCSD_FRM_ID_DATA,
739 m_out_data[m_out_processed].valid,
740 m_out_data[m_out_processed].data,
741 m_out_data[m_out_processed].id);
742 }
743 m_out_processed++; // skip past this data.
744 }
745 }
746 else
747 {
748 // optional raw output for debugging / monitor tools of unknown src ID data
749 if(m_b_output_unpacked_raw)
750 {
751 outputRawMonBytes( OCSD_OP_DATA,
752 m_out_data[m_out_processed].index,
753 OCSD_FRM_ID_DATA,
754 m_out_data[m_out_processed].valid,
755 m_out_data[m_out_processed].data,
756 m_out_data[m_out_processed].id);
757 }
758 m_out_processed++; // skip past this data.
759 }
760 }
761 return cont_processing;
762 }
763
764 /***************************************************************/
765 /* interface */
766 /***************************************************************/
TraceFormatterFrameDecoder()767 TraceFormatterFrameDecoder::TraceFormatterFrameDecoder() : m_pDecoder(0)
768 {
769 m_instNum = -1;
770 }
771
TraceFormatterFrameDecoder(int instNum)772 TraceFormatterFrameDecoder::TraceFormatterFrameDecoder(int instNum) : m_pDecoder(0)
773 {
774 m_instNum = instNum;
775 }
776
~TraceFormatterFrameDecoder()777 TraceFormatterFrameDecoder::~TraceFormatterFrameDecoder()
778 {
779 if(m_pDecoder)
780 {
781 delete m_pDecoder;
782 m_pDecoder = 0;
783 }
784 }
785
786 /* 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)787 ocsd_datapath_resp_t TraceFormatterFrameDecoder::TraceDataIn( const ocsd_datapath_op_t op,
788 const ocsd_trc_index_t index,
789 const uint32_t dataBlockSize,
790 const uint8_t *pDataBlock,
791 uint32_t *numBytesProcessed)
792 {
793 return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->TraceDataIn(op,index,dataBlockSize,pDataBlock,numBytesProcessed);
794 }
795
796 /* attach a data processor to a stream ID output */
getIDStreamAttachPt(uint8_t ID)797 componentAttachPt<ITrcDataIn> *TraceFormatterFrameDecoder::getIDStreamAttachPt(uint8_t ID)
798 {
799 componentAttachPt<ITrcDataIn> *pAttachPt = 0;
800 if((ID < 128) && (m_pDecoder != 0))
801 pAttachPt = &(m_pDecoder->m_IDStreams[ID]);
802 return pAttachPt;
803 }
804
805 /* attach a data processor to the raw frame output */
getTrcRawFrameAttachPt()806 componentAttachPt<ITrcRawFrameIn> *TraceFormatterFrameDecoder::getTrcRawFrameAttachPt()
807 {
808 return (m_pDecoder != 0) ? &m_pDecoder->m_RawTraceFrame : 0;
809 }
810
811
getTrcSrcIndexAttachPt()812 componentAttachPt<ITrcSrcIndexCreator> *TraceFormatterFrameDecoder::getTrcSrcIndexAttachPt()
813 {
814 return (m_pDecoder != 0) ? &m_pDecoder->m_SrcIndexer : 0;
815 }
816
getErrLogAttachPt()817 componentAttachPt<ITraceErrorLog> *TraceFormatterFrameDecoder::getErrLogAttachPt()
818 {
819 return (m_pDecoder != 0) ? m_pDecoder->getErrorLogAttachPt() : 0;
820 }
821
822 /* configuration - set operational mode for incoming stream (has FSYNCS etc) */
Configure(uint32_t cfg_flags)823 ocsd_err_t TraceFormatterFrameDecoder::Configure(uint32_t cfg_flags)
824 {
825 if(!m_pDecoder)
826 {
827 if(m_instNum >= 0)
828 m_pDecoder = new (std::nothrow) TraceFmtDcdImpl(m_instNum);
829 else
830 m_pDecoder = new (std::nothrow) TraceFmtDcdImpl();
831 if(!m_pDecoder) return OCSD_ERR_MEM;
832 }
833 m_pDecoder->DecodeConfigure(cfg_flags);
834 return OCSD_OK;
835 }
836
getConfigFlags() const837 const uint32_t TraceFormatterFrameDecoder::getConfigFlags() const
838 {
839 uint32_t flags = 0;
840 if(m_pDecoder)
841 flags = m_pDecoder->m_cfgFlags;
842 return flags;
843 }
844
845
846 /* enable / disable ID streams - default as all enabled */
OutputFilterIDs(std::vector<uint8_t> & id_list,bool bEnable)847 ocsd_err_t TraceFormatterFrameDecoder::OutputFilterIDs(std::vector<uint8_t> &id_list, bool bEnable)
848 {
849 return (m_pDecoder == 0) ? OCSD_ERR_NOT_INIT : m_pDecoder->OutputFilterIDs(id_list,bEnable);
850 }
851
OutputFilterAllIDs(bool bEnable)852 ocsd_err_t TraceFormatterFrameDecoder::OutputFilterAllIDs(bool bEnable)
853 {
854 return (m_pDecoder == 0) ? OCSD_ERR_NOT_INIT : m_pDecoder->OutputFilterAllIDs(bEnable);
855 }
856
857 /* decode control */
Reset()858 ocsd_datapath_resp_t TraceFormatterFrameDecoder::Reset()
859 {
860 return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Reset();
861 }
862
Flush()863 ocsd_datapath_resp_t TraceFormatterFrameDecoder::Flush()
864 {
865 return (m_pDecoder == 0) ? OCSD_RESP_FATAL_NOT_INIT : m_pDecoder->Flush();
866 }
867
868
869 /* End of File trc_frame_deformatter.cpp */
870