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