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