1 /* 2 * \file trc_pkt_decode_stm.cpp 3 * \brief OpenCSD : STM packet decoder - output generic SW trace packets. 4 * 5 * \copyright Copyright (c) 2016, 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 35 #include "opencsd/stm/trc_pkt_decode_stm.h" 36 #define DCD_NAME "DCD_STM" 37 38 TrcPktDecodeStm::TrcPktDecodeStm() 39 : TrcPktDecodeBase(DCD_NAME) 40 { 41 initDecoder(); 42 } 43 44 TrcPktDecodeStm::TrcPktDecodeStm(int instIDNum) 45 : TrcPktDecodeBase(DCD_NAME, instIDNum) 46 { 47 initDecoder(); 48 } 49 50 TrcPktDecodeStm::~TrcPktDecodeStm() 51 { 52 if(m_payload_buffer) 53 delete [] m_payload_buffer; 54 m_payload_buffer = 0; 55 } 56 57 /* implementation packet decoding interface */ 58 ocsd_datapath_resp_t TrcPktDecodeStm::processPacket() 59 { 60 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 61 bool bPktDone = false; 62 63 m_decode_pass1 = true; 64 65 while(!bPktDone) 66 { 67 switch(m_curr_state) 68 { 69 case NO_SYNC: 70 m_output_elem.setType(OCSD_GEN_TRC_ELEM_NO_SYNC); 71 m_output_elem.setUnSyncEOTReason(m_unsync_info); 72 resp = outputTraceElement(m_output_elem); 73 m_curr_state = WAIT_SYNC; 74 break; 75 76 case WAIT_SYNC: 77 if(m_curr_packet_in->getPktType() == STM_PKT_ASYNC) 78 m_curr_state = DECODE_PKTS; 79 bPktDone = true; 80 break; 81 82 case DECODE_PKTS: 83 resp = decodePacket(bPktDone); 84 break; 85 } 86 } 87 return resp; 88 } 89 90 ocsd_datapath_resp_t TrcPktDecodeStm::onEOT() 91 { 92 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 93 m_output_elem.setType(OCSD_GEN_TRC_ELEM_EO_TRACE); 94 m_output_elem.setUnSyncEOTReason(UNSYNC_EOT); 95 resp = outputTraceElement(m_output_elem); 96 return resp; 97 } 98 99 ocsd_datapath_resp_t TrcPktDecodeStm::onReset() 100 { 101 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 102 m_unsync_info = UNSYNC_RESET_DECODER; 103 resetDecoder(); 104 return resp; 105 } 106 107 ocsd_datapath_resp_t TrcPktDecodeStm::onFlush() 108 { 109 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 110 // don't currently save unsent packets so nothing to flush 111 return resp; 112 } 113 114 ocsd_err_t TrcPktDecodeStm::onProtocolConfig() 115 { 116 if(m_config == 0) 117 return OCSD_ERR_NOT_INIT; 118 119 // static config - copy of CSID for easy reference 120 m_CSID = m_config->getTraceID(); 121 return OCSD_OK; 122 } 123 124 void TrcPktDecodeStm::initDecoder() 125 { 126 m_payload_buffer = 0; 127 m_num_pkt_correlation = 1; // fixed at single packet payload correlation - add feature later 128 m_CSID = 0; 129 130 // base decoder state - STM requires no memory and instruction decode. 131 setUsesMemAccess(false); 132 setUsesIDecode(false); 133 m_unsync_info = UNSYNC_INIT_DECODER; 134 resetDecoder(); 135 } 136 137 void TrcPktDecodeStm::resetDecoder() 138 { 139 m_curr_state = NO_SYNC; 140 m_payload_size = 0; 141 m_payload_used = 0; 142 m_payload_odd_nibble = false; 143 m_output_elem.init(); 144 m_swt_packet_info.swt_flag_bits = 0; // zero out everything 145 initPayloadBuffer(); 146 } 147 148 void TrcPktDecodeStm::initPayloadBuffer() 149 { 150 // set up the payload buffer. If we are correlating indentical packets then 151 // need a buffer that is a multiple of 64bit packets. 152 // otherwise a single packet length will do. 153 if(m_payload_buffer) 154 delete [] m_payload_buffer; 155 m_payload_buffer = new (std::nothrow) uint8_t[m_num_pkt_correlation * sizeof(uint64_t)]; 156 } 157 158 ocsd_datapath_resp_t TrcPktDecodeStm::decodePacket(bool &bPktDone) 159 { 160 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 161 bool bSendPacket = false; // flag to indicate output required. 162 163 bPktDone = true; // assume complete unless 2nd pass required. 164 m_output_elem.setType(OCSD_GEN_TRC_ELEM_SWTRACE); 165 clearSWTPerPcktInfo(); 166 167 switch (m_curr_packet_in->getPktType()) 168 { 169 case STM_PKT_BAD_SEQUENCE: /**< Incorrect protocol sequence */ 170 case STM_PKT_RESERVED: 171 resp = OCSD_RESP_FATAL_INVALID_DATA; 172 m_unsync_info = UNSYNC_BAD_PACKET; 173 case STM_PKT_NOTSYNC: 174 resetDecoder(); 175 break; 176 177 case STM_PKT_VERSION: /**< Version packet - not relevant to generic (versionless) o/p */ 178 case STM_PKT_ASYNC: /**< Alignment synchronisation packet */ 179 case STM_PKT_INCOMPLETE_EOT: /**< Incomplete packet flushed at end of trace. */ 180 // no action required. 181 break; 182 183 /* markers for valid packets*/ 184 case STM_PKT_NULL: /**< Null packet */ 185 if(m_curr_packet_in->isTSPkt()) 186 bSendPacket = true; // forward NULL packet if associated timestamp. 187 break; 188 189 case STM_PKT_FREQ: /**< Frequency packet */ 190 m_swt_packet_info.swt_frequency = 1; 191 updatePayload(bSendPacket); 192 break; 193 194 case STM_PKT_TRIG: /**< Trigger event packet. */ 195 m_swt_packet_info.swt_trigger_event = 1; 196 updatePayload(bSendPacket); 197 break; 198 199 case STM_PKT_GERR: /**< Global error packet - protocol error but unknown which master had error */ 200 m_swt_packet_info.swt_master_id = m_curr_packet_in->getMaster(); 201 m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel(); 202 m_swt_packet_info.swt_global_err = 1; 203 m_swt_packet_info.swt_id_valid = 0; 204 updatePayload(bSendPacket); 205 break; 206 207 case STM_PKT_MERR: /**< Master error packet - current master detected an error (e.g. dropped trace) */ 208 m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel(); 209 m_swt_packet_info.swt_master_err = 1; 210 updatePayload(bSendPacket); 211 break; 212 213 case STM_PKT_M8: /**< Set current master */ 214 m_swt_packet_info.swt_master_id = m_curr_packet_in->getMaster(); 215 m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel(); // forced to 0 216 m_swt_packet_info.swt_id_valid = 1; 217 break; 218 219 case STM_PKT_C8: /**< Set lower 8 bits of current channel - packet proc hadnles this */ 220 case STM_PKT_C16: /**< Set current channel */ 221 m_swt_packet_info.swt_channel_id = m_curr_packet_in->getChannel(); 222 break; 223 224 case STM_PKT_FLAG: /**< Flag packet */ 225 m_swt_packet_info.swt_marker_packet = 1; 226 bSendPacket = true; // send 0 payload marker packet./ 227 break; 228 229 230 case STM_PKT_D4: /**< 4 bit data payload packet */ 231 case STM_PKT_D8: /**< 8 bit data payload packet */ 232 case STM_PKT_D16: /**< 16 bit data payload packet */ 233 case STM_PKT_D32: /**< 32 bit data payload packet */ 234 case STM_PKT_D64: /**< 64 bit data payload packet */ 235 updatePayload(bSendPacket); 236 break; 237 238 } 239 240 if(bSendPacket) 241 { 242 if(m_curr_packet_in->isTSPkt()) 243 { 244 m_output_elem.setTS(m_curr_packet_in->getTSVal()); 245 m_swt_packet_info.swt_has_timestamp = 1; 246 } 247 m_output_elem.setSWTInfo(m_swt_packet_info); 248 resp = outputTraceElement(m_output_elem); 249 } 250 251 return resp; 252 } 253 254 void TrcPktDecodeStm::clearSWTPerPcktInfo() 255 { 256 m_swt_packet_info.swt_flag_bits &= (uint32_t)(0x0 | SWT_ID_VALID_MASK); // clear flags and current payload size (save id valid flag). 257 } 258 259 void TrcPktDecodeStm::updatePayload(bool &bSendPacket) 260 { 261 // without buffering similar packets - this function is quite simple 262 bSendPacket = true; 263 m_swt_packet_info.swt_payload_num_packets = 1; 264 265 switch(m_curr_packet_in->getPktType()) 266 { 267 case STM_PKT_D4: /**< 4 bit data payload packet */ 268 m_swt_packet_info.swt_payload_pkt_bitsize = 4; 269 *(uint8_t *)m_payload_buffer = m_curr_packet_in->getD4Val(); 270 break; 271 272 case STM_PKT_D8: /**< 8 bit data payload packet */ 273 case STM_PKT_TRIG: /**< Trigger event packet - 8 bits. */ 274 case STM_PKT_GERR: /**< error packet - 8 bits. */ 275 case STM_PKT_MERR: /**< error packet - 8 bits. */ 276 m_swt_packet_info.swt_payload_pkt_bitsize = 8; 277 *(uint8_t *)m_payload_buffer = m_curr_packet_in->getD8Val(); 278 break; 279 280 case STM_PKT_D16: /**< 16 bit data payload packet */ 281 m_swt_packet_info.swt_payload_pkt_bitsize = 16; 282 *(uint16_t *)m_payload_buffer = m_curr_packet_in->getD16Val(); 283 break; 284 285 case STM_PKT_D32: /**< 32 bit data payload packet */ 286 case STM_PKT_FREQ: /**< Frequency packet */ 287 m_swt_packet_info.swt_payload_pkt_bitsize = 32; 288 *(uint32_t *)m_payload_buffer = m_curr_packet_in->getD32Val(); 289 break; 290 291 292 case STM_PKT_D64: /**< 64 bit data payload packet */ 293 m_swt_packet_info.swt_payload_pkt_bitsize = 64; 294 *(uint64_t *)m_payload_buffer = m_curr_packet_in->getD64Val(); 295 break; 296 } 297 m_output_elem.setExtendedDataPtr(m_payload_buffer); 298 if (m_curr_packet_in->isMarkerPkt()) 299 m_swt_packet_info.swt_marker_packet = 1; 300 301 } 302 303 /* End of File trc_pkt_decode_stm.cpp */ 304