1 /*! 2 * \file trc_pkt_decode_base.h 3 * \brief OpenCSD : Trace Packet decoder base class. 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 35 #ifndef ARM_TRC_PKT_DECODE_BASE_H_INCLUDED 36 #define ARM_TRC_PKT_DECODE_BASE_H_INCLUDED 37 38 #include "trc_component.h" 39 #include "comp_attach_pt_t.h" 40 41 #include "interfaces/trc_pkt_in_i.h" 42 #include "interfaces/trc_gen_elem_in_i.h" 43 #include "interfaces/trc_tgt_mem_access_i.h" 44 #include "interfaces/trc_instr_decode_i.h" 45 46 /** @defgroup ocsd_pkt_decode OpenCSD Library : Packet Decoders. 47 48 @brief Classes providing Protocol Packet Decoding capability. 49 50 Packet decoders convert incoming protocol packets from a packet processor, 51 into generic trace elements to be output to an analysis program. 52 53 Packet decoders can be:- 54 - PE decoders - converting ETM or PTM packets into instruction and data trace elements 55 - SW stimulus decoder - converting STM or ITM packets into software generated trace elements. 56 - Bus decoders - converting HTM packets into bus transaction elements. 57 58 @{*/ 59 60 61 class TrcPktDecodeI : public TraceComponent 62 { 63 public: 64 TrcPktDecodeI(const char *component_name); 65 TrcPktDecodeI(const char *component_name, int instIDNum); 66 virtual ~TrcPktDecodeI() {}; 67 68 componentAttachPt<ITrcGenElemIn> *getTraceElemOutAttachPt() { return &m_trace_elem_out; }; 69 componentAttachPt<ITargetMemAccess> *getMemoryAccessAttachPt() { return &m_mem_access; }; 70 componentAttachPt<IInstrDecode> *getInstrDecodeAttachPt() { return &m_instr_decode; }; 71 72 void setUsesMemAccess(bool bUsesMemaccess) { m_uses_memaccess = bUsesMemaccess; }; 73 const bool getUsesMemAccess() const { return m_uses_memaccess; }; 74 75 void setUsesIDecode(bool bUsesIDecode) { m_uses_idecode = bUsesIDecode; }; 76 const bool getUsesIDecode() const { return m_uses_idecode; }; 77 78 protected: 79 80 /* implementation packet decoding interface */ 81 virtual ocsd_datapath_resp_t processPacket() = 0; 82 virtual ocsd_datapath_resp_t onEOT() = 0; 83 virtual ocsd_datapath_resp_t onReset() = 0; 84 virtual ocsd_datapath_resp_t onFlush() = 0; 85 virtual ocsd_err_t onProtocolConfig() = 0; 86 virtual const uint8_t getCoreSightTraceID() = 0; 87 88 /* init handling */ 89 const bool checkInit(); 90 /* Called on first init confirmation */ 91 virtual void onFirstInitOK() {}; 92 93 /* data output */ 94 ocsd_datapath_resp_t outputTraceElement(const OcsdTraceElement &elem); // use current index 95 ocsd_datapath_resp_t outputTraceElementIdx(ocsd_trc_index_t idx, const OcsdTraceElement &elem); // use supplied index (where decoder caches elements) 96 97 /* target access */ 98 ocsd_err_t accessMemory(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer); 99 100 /* instruction decode */ 101 ocsd_err_t instrDecode(ocsd_instr_info *instr_info); 102 103 componentAttachPt<ITrcGenElemIn> m_trace_elem_out; 104 componentAttachPt<ITargetMemAccess> m_mem_access; 105 componentAttachPt<IInstrDecode> m_instr_decode; 106 107 ocsd_trc_index_t m_index_curr_pkt; 108 109 bool m_decode_init_ok; //!< set true if all attachments in place for decode. (remove checks in main throughput paths) 110 bool m_config_init_ok; //!< set true if config set. 111 112 std::string init_err_msg; //!< error message for init error 113 114 bool m_uses_memaccess; 115 bool m_uses_idecode; 116 117 }; 118 119 inline TrcPktDecodeI::TrcPktDecodeI(const char *component_name) : 120 TraceComponent(component_name), 121 m_index_curr_pkt(0), 122 m_decode_init_ok(false), 123 m_config_init_ok(false), 124 m_uses_memaccess(true), 125 m_uses_idecode(true) 126 { 127 } 128 129 inline TrcPktDecodeI::TrcPktDecodeI(const char *component_name, int instIDNum) : 130 TraceComponent(component_name, instIDNum), 131 m_index_curr_pkt(0), 132 m_decode_init_ok(false), 133 m_config_init_ok(false), 134 m_uses_memaccess(true), 135 m_uses_idecode(true) 136 { 137 } 138 139 inline const bool TrcPktDecodeI::checkInit() 140 { 141 if(!m_decode_init_ok) 142 { 143 if(!m_config_init_ok) 144 init_err_msg = "No decoder configuration information"; 145 else if(!m_trace_elem_out.hasAttachedAndEnabled()) 146 init_err_msg = "No element output interface attached and enabled"; 147 else if(m_uses_memaccess && !m_mem_access.hasAttachedAndEnabled()) 148 init_err_msg = "No memory access interface attached and enabled"; 149 else if(m_uses_idecode && !m_instr_decode.hasAttachedAndEnabled()) 150 init_err_msg = "No instruction decoder interface attached and enabled"; 151 else 152 m_decode_init_ok = true; 153 if (m_decode_init_ok) 154 onFirstInitOK(); 155 } 156 return m_decode_init_ok; 157 } 158 159 inline ocsd_datapath_resp_t TrcPktDecodeI::outputTraceElement(const OcsdTraceElement &elem) 160 { 161 return m_trace_elem_out.first()->TraceElemIn(m_index_curr_pkt,getCoreSightTraceID(), elem); 162 } 163 164 inline ocsd_datapath_resp_t TrcPktDecodeI::outputTraceElementIdx(ocsd_trc_index_t idx, const OcsdTraceElement &elem) 165 { 166 return m_trace_elem_out.first()->TraceElemIn(idx, getCoreSightTraceID(), elem); 167 } 168 169 inline ocsd_err_t TrcPktDecodeI::instrDecode(ocsd_instr_info *instr_info) 170 { 171 if(m_uses_idecode) 172 return m_instr_decode.first()->DecodeInstruction(instr_info); 173 return OCSD_ERR_DCD_INTERFACE_UNUSED; 174 } 175 176 inline ocsd_err_t TrcPktDecodeI::accessMemory(const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, uint32_t *num_bytes, uint8_t *p_buffer) 177 { 178 if(m_uses_memaccess) 179 return m_mem_access.first()->ReadTargetMemory(address,getCoreSightTraceID(),mem_space, num_bytes,p_buffer); 180 return OCSD_ERR_DCD_INTERFACE_UNUSED; 181 } 182 183 /**********************************************************************/ 184 template <class P, class Pc> 185 class TrcPktDecodeBase : public TrcPktDecodeI, public IPktDataIn<P> 186 { 187 public: 188 TrcPktDecodeBase(const char *component_name); 189 TrcPktDecodeBase(const char *component_name, int instIDNum); 190 virtual ~TrcPktDecodeBase(); 191 192 virtual ocsd_datapath_resp_t PacketDataIn( const ocsd_datapath_op_t op, 193 const ocsd_trc_index_t index_sop, 194 const P *p_packet_in); 195 196 197 /* protocol configuration */ 198 ocsd_err_t setProtocolConfig(const Pc *config); 199 const Pc * getProtocolConfig() const { return m_config; }; 200 201 protected: 202 void ClearConfigObj(); 203 204 /* the protocol configuration */ 205 Pc * m_config; 206 /* the current input packet */ 207 const P * m_curr_packet_in; 208 209 }; 210 211 212 template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name) : 213 TrcPktDecodeI(component_name), 214 m_config(0) 215 { 216 } 217 218 template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name, int instIDNum) : 219 TrcPktDecodeI(component_name,instIDNum), 220 m_config(0) 221 { 222 } 223 224 template <class P, class Pc> TrcPktDecodeBase<P, Pc>::~TrcPktDecodeBase() 225 { 226 ClearConfigObj(); 227 } 228 229 template <class P, class Pc> ocsd_datapath_resp_t TrcPktDecodeBase<P, Pc>::PacketDataIn( const ocsd_datapath_op_t op, 230 const ocsd_trc_index_t index_sop, 231 const P *p_packet_in) 232 { 233 ocsd_datapath_resp_t resp = OCSD_RESP_CONT; 234 if(!checkInit()) 235 { 236 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_NOT_INIT,init_err_msg)); 237 return OCSD_RESP_FATAL_NOT_INIT; 238 } 239 240 switch(op) 241 { 242 case OCSD_OP_DATA: 243 if(p_packet_in == 0) 244 { 245 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL)); 246 resp = OCSD_RESP_FATAL_INVALID_PARAM; 247 } 248 else 249 { 250 m_curr_packet_in = p_packet_in; 251 m_index_curr_pkt = index_sop; 252 resp = processPacket(); 253 } 254 break; 255 256 case OCSD_OP_EOT: 257 resp = onEOT(); 258 break; 259 260 case OCSD_OP_FLUSH: 261 resp = onFlush(); 262 break; 263 264 case OCSD_OP_RESET: 265 resp = onReset(); 266 break; 267 268 default: 269 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL)); 270 resp = OCSD_RESP_FATAL_INVALID_OP; 271 break; 272 } 273 return resp; 274 } 275 276 /* protocol configuration */ 277 template <class P, class Pc> ocsd_err_t TrcPktDecodeBase<P, Pc>::setProtocolConfig(const Pc *config) 278 { 279 ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL; 280 if(config != 0) 281 { 282 ClearConfigObj(); // remove any current config 283 m_config = new (std::nothrow) Pc(*config); // make a copy of the config - don't rely on the object passed in being valid outside the context of the call. 284 if(m_config != 0) 285 { 286 err = onProtocolConfig(); 287 if(err == OCSD_OK) 288 m_config_init_ok = true; 289 } 290 else 291 err = OCSD_ERR_MEM; 292 } 293 return err; 294 } 295 296 template <class P, class Pc> void TrcPktDecodeBase<P, Pc>::ClearConfigObj() 297 { 298 if(m_config) 299 { 300 delete m_config; 301 m_config = 0; 302 } 303 } 304 305 /** @}*/ 306 #endif // ARM_TRC_PKT_DECODE_BASE_H_INCLUDED 307 308 /* End of File trc_pkt_decode_base.h */ 309