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