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