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);
~TrcPktDecodeI()66 virtual ~TrcPktDecodeI() {};
67
getTraceElemOutAttachPt()68 componentAttachPt<ITrcGenElemIn> *getTraceElemOutAttachPt() { return &m_trace_elem_out; };
getMemoryAccessAttachPt()69 componentAttachPt<ITargetMemAccess> *getMemoryAccessAttachPt() { return &m_mem_access; };
getInstrDecodeAttachPt()70 componentAttachPt<IInstrDecode> *getInstrDecodeAttachPt() { return &m_instr_decode; };
71
setUsesMemAccess(bool bUsesMemaccess)72 void setUsesMemAccess(bool bUsesMemaccess) { m_uses_memaccess = bUsesMemaccess; };
getUsesMemAccess()73 const bool getUsesMemAccess() const { return m_uses_memaccess; };
74
setUsesIDecode(bool bUsesIDecode)75 void setUsesIDecode(bool bUsesIDecode) { m_uses_idecode = bUsesIDecode; };
getUsesIDecode()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 const bool checkInit();
89
90 /* data output */
91 ocsd_datapath_resp_t outputTraceElement(const OcsdTraceElement &elem); // use current index
92 ocsd_datapath_resp_t outputTraceElementIdx(ocsd_trc_index_t idx, const OcsdTraceElement &elem); // use supplied index (where decoder caches elements)
93
94 /* target access */
95 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);
96
97 /* instruction decode */
98 ocsd_err_t instrDecode(ocsd_instr_info *instr_info);
99
100 componentAttachPt<ITrcGenElemIn> m_trace_elem_out;
101 componentAttachPt<ITargetMemAccess> m_mem_access;
102 componentAttachPt<IInstrDecode> m_instr_decode;
103
104 ocsd_trc_index_t m_index_curr_pkt;
105
106 bool m_decode_init_ok; //!< set true if all attachments in place for decode. (remove checks in main throughput paths)
107 bool m_config_init_ok; //!< set true if config set.
108
109 std::string init_err_msg; //!< error message for init error
110
111 bool m_uses_memaccess;
112 bool m_uses_idecode;
113
114 };
115
TrcPktDecodeI(const char * component_name)116 inline TrcPktDecodeI::TrcPktDecodeI(const char *component_name) :
117 TraceComponent(component_name),
118 m_index_curr_pkt(0),
119 m_decode_init_ok(false),
120 m_config_init_ok(false),
121 m_uses_memaccess(true),
122 m_uses_idecode(true)
123 {
124 }
125
TrcPktDecodeI(const char * component_name,int instIDNum)126 inline TrcPktDecodeI::TrcPktDecodeI(const char *component_name, int instIDNum) :
127 TraceComponent(component_name, instIDNum),
128 m_index_curr_pkt(0),
129 m_decode_init_ok(false),
130 m_config_init_ok(false),
131 m_uses_memaccess(true),
132 m_uses_idecode(true)
133 {
134 }
135
checkInit()136 inline const bool TrcPktDecodeI::checkInit()
137 {
138 if(!m_decode_init_ok)
139 {
140 if(!m_config_init_ok)
141 init_err_msg = "No decoder configuration information";
142 else if(!m_trace_elem_out.hasAttachedAndEnabled())
143 init_err_msg = "No element output interface attached and enabled";
144 else if(m_uses_memaccess && !m_mem_access.hasAttachedAndEnabled())
145 init_err_msg = "No memory access interface attached and enabled";
146 else if(m_uses_idecode && !m_instr_decode.hasAttachedAndEnabled())
147 init_err_msg = "No instruction decoder interface attached and enabled";
148 else
149 m_decode_init_ok = true;
150 }
151 return m_decode_init_ok;
152 }
153
outputTraceElement(const OcsdTraceElement & elem)154 inline ocsd_datapath_resp_t TrcPktDecodeI::outputTraceElement(const OcsdTraceElement &elem)
155 {
156 return m_trace_elem_out.first()->TraceElemIn(m_index_curr_pkt,getCoreSightTraceID(), elem);
157 }
158
outputTraceElementIdx(ocsd_trc_index_t idx,const OcsdTraceElement & elem)159 inline ocsd_datapath_resp_t TrcPktDecodeI::outputTraceElementIdx(ocsd_trc_index_t idx, const OcsdTraceElement &elem)
160 {
161 return m_trace_elem_out.first()->TraceElemIn(idx, getCoreSightTraceID(), elem);
162 }
163
instrDecode(ocsd_instr_info * instr_info)164 inline ocsd_err_t TrcPktDecodeI::instrDecode(ocsd_instr_info *instr_info)
165 {
166 if(m_uses_idecode)
167 return m_instr_decode.first()->DecodeInstruction(instr_info);
168 return OCSD_ERR_DCD_INTERFACE_UNUSED;
169 }
170
accessMemory(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,uint32_t * num_bytes,uint8_t * p_buffer)171 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)
172 {
173 if(m_uses_memaccess)
174 return m_mem_access.first()->ReadTargetMemory(address,getCoreSightTraceID(),mem_space, num_bytes,p_buffer);
175 return OCSD_ERR_DCD_INTERFACE_UNUSED;
176 }
177
178 /**********************************************************************/
179 template <class P, class Pc>
180 class TrcPktDecodeBase : public TrcPktDecodeI, public IPktDataIn<P>
181 {
182 public:
183 TrcPktDecodeBase(const char *component_name);
184 TrcPktDecodeBase(const char *component_name, int instIDNum);
185 virtual ~TrcPktDecodeBase();
186
187 virtual ocsd_datapath_resp_t PacketDataIn( const ocsd_datapath_op_t op,
188 const ocsd_trc_index_t index_sop,
189 const P *p_packet_in);
190
191
192 /* protocol configuration */
193 ocsd_err_t setProtocolConfig(const Pc *config);
getProtocolConfig()194 const Pc * getProtocolConfig() const { return m_config; };
195
196 protected:
197 void ClearConfigObj();
198
199 /* the protocol configuration */
200 Pc * m_config;
201 /* the current input packet */
202 const P * m_curr_packet_in;
203
204 };
205
206
TrcPktDecodeBase(const char * component_name)207 template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name) :
208 TrcPktDecodeI(component_name),
209 m_config(0)
210 {
211 }
212
TrcPktDecodeBase(const char * component_name,int instIDNum)213 template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name, int instIDNum) :
214 TrcPktDecodeI(component_name,instIDNum),
215 m_config(0)
216 {
217 }
218
~TrcPktDecodeBase()219 template <class P, class Pc> TrcPktDecodeBase<P, Pc>::~TrcPktDecodeBase()
220 {
221 ClearConfigObj();
222 }
223
PacketDataIn(const ocsd_datapath_op_t op,const ocsd_trc_index_t index_sop,const P * p_packet_in)224 template <class P, class Pc> ocsd_datapath_resp_t TrcPktDecodeBase<P, Pc>::PacketDataIn( const ocsd_datapath_op_t op,
225 const ocsd_trc_index_t index_sop,
226 const P *p_packet_in)
227 {
228 ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
229 if(!checkInit())
230 {
231 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_NOT_INIT,init_err_msg));
232 return OCSD_RESP_FATAL_NOT_INIT;
233 }
234
235 switch(op)
236 {
237 case OCSD_OP_DATA:
238 if(p_packet_in == 0)
239 {
240 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL));
241 resp = OCSD_RESP_FATAL_INVALID_PARAM;
242 }
243 else
244 {
245 m_curr_packet_in = p_packet_in;
246 m_index_curr_pkt = index_sop;
247 resp = processPacket();
248 }
249 break;
250
251 case OCSD_OP_EOT:
252 resp = onEOT();
253 break;
254
255 case OCSD_OP_FLUSH:
256 resp = onFlush();
257 break;
258
259 case OCSD_OP_RESET:
260 resp = onReset();
261 break;
262
263 default:
264 LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL));
265 resp = OCSD_RESP_FATAL_INVALID_OP;
266 break;
267 }
268 return resp;
269 }
270
271 /* protocol configuration */
setProtocolConfig(const Pc * config)272 template <class P, class Pc> ocsd_err_t TrcPktDecodeBase<P, Pc>::setProtocolConfig(const Pc *config)
273 {
274 ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL;
275 if(config != 0)
276 {
277 ClearConfigObj(); // remove any current config
278 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.
279 if(m_config != 0)
280 {
281 err = onProtocolConfig();
282 if(err == OCSD_OK)
283 m_config_init_ok = true;
284 }
285 else
286 err = OCSD_ERR_MEM;
287 }
288 return err;
289 }
290
ClearConfigObj()291 template <class P, class Pc> void TrcPktDecodeBase<P, Pc>::ClearConfigObj()
292 {
293 if(m_config)
294 {
295 delete m_config;
296 m_config = 0;
297 }
298 }
299
300 /** @}*/
301 #endif // ARM_TRC_PKT_DECODE_BASE_H_INCLUDED
302
303 /* End of File trc_pkt_decode_base.h */
304