xref: /freebsd-src/contrib/opencsd/decoder/include/common/trc_pkt_decode_base.h (revision 46e6e290975f19ea62d03f90ac3e523af4dae557)
1c120c564SAndrew Turner /*!
2c120c564SAndrew Turner  * \file       trc_pkt_decode_base.h
3c120c564SAndrew Turner  * \brief      OpenCSD : Trace Packet decoder base class.
4c120c564SAndrew Turner  *
5c120c564SAndrew Turner  * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
6c120c564SAndrew Turner  */
7c120c564SAndrew Turner 
8c120c564SAndrew Turner /*
9c120c564SAndrew Turner  * Redistribution and use in source and binary forms, with or without modification,
10c120c564SAndrew Turner  * are permitted provided that the following conditions are met:
11c120c564SAndrew Turner  *
12c120c564SAndrew Turner  * 1. Redistributions of source code must retain the above copyright notice,
13c120c564SAndrew Turner  * this list of conditions and the following disclaimer.
14c120c564SAndrew Turner  *
15c120c564SAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright notice,
16c120c564SAndrew Turner  * this list of conditions and the following disclaimer in the documentation
17c120c564SAndrew Turner  * and/or other materials provided with the distribution.
18c120c564SAndrew Turner  *
19c120c564SAndrew Turner  * 3. Neither the name of the copyright holder nor the names of its contributors
20c120c564SAndrew Turner  * may be used to endorse or promote products derived from this software without
21c120c564SAndrew Turner  * specific prior written permission.
22c120c564SAndrew Turner  *
23c120c564SAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24c120c564SAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25c120c564SAndrew Turner  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26c120c564SAndrew Turner  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27c120c564SAndrew Turner  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28c120c564SAndrew Turner  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29c120c564SAndrew Turner  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30c120c564SAndrew Turner  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31c120c564SAndrew Turner  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32c120c564SAndrew Turner  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33c120c564SAndrew Turner  */
34c120c564SAndrew Turner 
35c120c564SAndrew Turner #ifndef ARM_TRC_PKT_DECODE_BASE_H_INCLUDED
36c120c564SAndrew Turner #define ARM_TRC_PKT_DECODE_BASE_H_INCLUDED
37c120c564SAndrew Turner 
38c120c564SAndrew Turner #include "trc_component.h"
39c120c564SAndrew Turner #include "comp_attach_pt_t.h"
40c120c564SAndrew Turner 
41c120c564SAndrew Turner #include "interfaces/trc_pkt_in_i.h"
42c120c564SAndrew Turner #include "interfaces/trc_gen_elem_in_i.h"
43c120c564SAndrew Turner #include "interfaces/trc_tgt_mem_access_i.h"
44c120c564SAndrew Turner #include "interfaces/trc_instr_decode_i.h"
45c120c564SAndrew Turner 
46c120c564SAndrew Turner /** @defgroup ocsd_pkt_decode OpenCSD Library : Packet Decoders.
47c120c564SAndrew Turner 
48c120c564SAndrew Turner     @brief Classes providing Protocol Packet Decoding capability.
49c120c564SAndrew Turner 
50c120c564SAndrew Turner     Packet decoders convert incoming protocol packets from a packet processor,
51c120c564SAndrew Turner     into generic trace elements to be output to an analysis program.
52c120c564SAndrew Turner 
53c120c564SAndrew Turner     Packet decoders can be:-
54c120c564SAndrew Turner     - PE decoders - converting ETM or PTM packets into instruction and data trace elements
55c120c564SAndrew Turner     - SW stimulus decoder - converting STM or ITM packets into software generated trace elements.
56c120c564SAndrew Turner     - Bus decoders - converting HTM packets into bus transaction elements.
57c120c564SAndrew Turner 
58c120c564SAndrew Turner @{*/
59c120c564SAndrew Turner 
60c120c564SAndrew Turner 
61c120c564SAndrew Turner class TrcPktDecodeI : public TraceComponent
62c120c564SAndrew Turner {
63c120c564SAndrew Turner public:
64c120c564SAndrew Turner     TrcPktDecodeI(const char *component_name);
65c120c564SAndrew Turner     TrcPktDecodeI(const char *component_name, int instIDNum);
~TrcPktDecodeI()66c120c564SAndrew Turner     virtual ~TrcPktDecodeI() {};
67c120c564SAndrew Turner 
getTraceElemOutAttachPt()68c120c564SAndrew Turner     componentAttachPt<ITrcGenElemIn> *getTraceElemOutAttachPt() { return &m_trace_elem_out; };
getMemoryAccessAttachPt()69c120c564SAndrew Turner     componentAttachPt<ITargetMemAccess> *getMemoryAccessAttachPt() { return &m_mem_access; };
getInstrDecodeAttachPt()70c120c564SAndrew Turner     componentAttachPt<IInstrDecode> *getInstrDecodeAttachPt() { return &m_instr_decode; };
71c120c564SAndrew Turner 
setUsesMemAccess(bool bUsesMemaccess)72c120c564SAndrew Turner     void setUsesMemAccess(bool bUsesMemaccess) { m_uses_memaccess = bUsesMemaccess; };
getUsesMemAccess()73c120c564SAndrew Turner     const bool getUsesMemAccess() const { return m_uses_memaccess; };
74c120c564SAndrew Turner 
setUsesIDecode(bool bUsesIDecode)75c120c564SAndrew Turner     void setUsesIDecode(bool bUsesIDecode) { m_uses_idecode = bUsesIDecode; };
getUsesIDecode()76c120c564SAndrew Turner     const bool getUsesIDecode() const { return m_uses_idecode; };
77c120c564SAndrew Turner 
78c120c564SAndrew Turner protected:
79c120c564SAndrew Turner 
80c120c564SAndrew Turner     /* implementation packet decoding interface */
81c120c564SAndrew Turner     virtual ocsd_datapath_resp_t processPacket() = 0;
82c120c564SAndrew Turner     virtual ocsd_datapath_resp_t onEOT() = 0;
83c120c564SAndrew Turner     virtual ocsd_datapath_resp_t onReset() = 0;
84c120c564SAndrew Turner     virtual ocsd_datapath_resp_t onFlush() = 0;
85c120c564SAndrew Turner     virtual ocsd_err_t onProtocolConfig() = 0;
86c120c564SAndrew Turner     virtual const uint8_t getCoreSightTraceID() = 0;
87c120c564SAndrew Turner 
88b6aadd18SAndrew Turner     /* init handling */
89c120c564SAndrew Turner     const bool checkInit();
90b6aadd18SAndrew Turner     /* Called on first init confirmation */
onFirstInitOK()91b6aadd18SAndrew Turner     virtual void onFirstInitOK() {};
92c120c564SAndrew Turner 
93c120c564SAndrew Turner     /* data output */
94c120c564SAndrew Turner     ocsd_datapath_resp_t outputTraceElement(const OcsdTraceElement &elem);    // use current index
95c120c564SAndrew Turner     ocsd_datapath_resp_t outputTraceElementIdx(ocsd_trc_index_t idx, const OcsdTraceElement &elem); // use supplied index (where decoder caches elements)
96c120c564SAndrew Turner 
97c120c564SAndrew Turner     /* target access */
98c120c564SAndrew Turner     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*46e6e290SRuslan Bukin     ocsd_err_t invalidateMemAccCache();
100c120c564SAndrew Turner 
101c120c564SAndrew Turner     /* instruction decode */
102c120c564SAndrew Turner     ocsd_err_t instrDecode(ocsd_instr_info *instr_info);
103c120c564SAndrew Turner 
104c120c564SAndrew Turner     componentAttachPt<ITrcGenElemIn> m_trace_elem_out;
105c120c564SAndrew Turner     componentAttachPt<ITargetMemAccess> m_mem_access;
106c120c564SAndrew Turner     componentAttachPt<IInstrDecode> m_instr_decode;
107c120c564SAndrew Turner 
108c120c564SAndrew Turner     ocsd_trc_index_t   m_index_curr_pkt;
109c120c564SAndrew Turner 
110c120c564SAndrew Turner     bool m_decode_init_ok;  //!< set true if all attachments in place for decode. (remove checks in main throughput paths)
111c120c564SAndrew Turner     bool m_config_init_ok;  //!< set true if config set.
112c120c564SAndrew Turner 
113c120c564SAndrew Turner     std::string init_err_msg;    //!< error message for init error
114c120c564SAndrew Turner 
115c120c564SAndrew Turner     bool m_uses_memaccess;
116c120c564SAndrew Turner     bool m_uses_idecode;
117c120c564SAndrew Turner 
118c120c564SAndrew Turner };
119c120c564SAndrew Turner 
TrcPktDecodeI(const char * component_name)120c120c564SAndrew Turner inline TrcPktDecodeI::TrcPktDecodeI(const char *component_name) :
121c120c564SAndrew Turner     TraceComponent(component_name),
122c120c564SAndrew Turner     m_index_curr_pkt(0),
123c120c564SAndrew Turner     m_decode_init_ok(false),
124c120c564SAndrew Turner     m_config_init_ok(false),
125c120c564SAndrew Turner     m_uses_memaccess(true),
126c120c564SAndrew Turner     m_uses_idecode(true)
127c120c564SAndrew Turner {
128c120c564SAndrew Turner }
129c120c564SAndrew Turner 
TrcPktDecodeI(const char * component_name,int instIDNum)130c120c564SAndrew Turner inline TrcPktDecodeI::TrcPktDecodeI(const char *component_name, int instIDNum) :
131c120c564SAndrew Turner     TraceComponent(component_name, instIDNum),
132c120c564SAndrew Turner     m_index_curr_pkt(0),
133c120c564SAndrew Turner     m_decode_init_ok(false),
134c120c564SAndrew Turner     m_config_init_ok(false),
135c120c564SAndrew Turner     m_uses_memaccess(true),
136c120c564SAndrew Turner     m_uses_idecode(true)
137c120c564SAndrew Turner {
138c120c564SAndrew Turner }
139c120c564SAndrew Turner 
checkInit()140c120c564SAndrew Turner inline const bool TrcPktDecodeI::checkInit()
141c120c564SAndrew Turner {
142c120c564SAndrew Turner     if(!m_decode_init_ok)
143c120c564SAndrew Turner     {
144c120c564SAndrew Turner         if(!m_config_init_ok)
145c120c564SAndrew Turner             init_err_msg = "No decoder configuration information";
146c120c564SAndrew Turner         else if(!m_trace_elem_out.hasAttachedAndEnabled())
147c120c564SAndrew Turner             init_err_msg = "No element output interface attached and enabled";
148c120c564SAndrew Turner         else if(m_uses_memaccess && !m_mem_access.hasAttachedAndEnabled())
149c120c564SAndrew Turner             init_err_msg = "No memory access interface attached and enabled";
150c120c564SAndrew Turner         else if(m_uses_idecode && !m_instr_decode.hasAttachedAndEnabled())
151c120c564SAndrew Turner             init_err_msg = "No instruction decoder interface attached and enabled";
152c120c564SAndrew Turner         else
153c120c564SAndrew Turner             m_decode_init_ok = true;
154b6aadd18SAndrew Turner         if (m_decode_init_ok)
155b6aadd18SAndrew Turner             onFirstInitOK();
156c120c564SAndrew Turner     }
157c120c564SAndrew Turner     return m_decode_init_ok;
158c120c564SAndrew Turner }
159c120c564SAndrew Turner 
outputTraceElement(const OcsdTraceElement & elem)160c120c564SAndrew Turner inline ocsd_datapath_resp_t TrcPktDecodeI::outputTraceElement(const OcsdTraceElement &elem)
161c120c564SAndrew Turner {
162c120c564SAndrew Turner     return m_trace_elem_out.first()->TraceElemIn(m_index_curr_pkt,getCoreSightTraceID(), elem);
163c120c564SAndrew Turner }
164c120c564SAndrew Turner 
outputTraceElementIdx(ocsd_trc_index_t idx,const OcsdTraceElement & elem)165c120c564SAndrew Turner inline ocsd_datapath_resp_t TrcPktDecodeI::outputTraceElementIdx(ocsd_trc_index_t idx, const OcsdTraceElement &elem)
166c120c564SAndrew Turner {
167c120c564SAndrew Turner     return m_trace_elem_out.first()->TraceElemIn(idx, getCoreSightTraceID(), elem);
168c120c564SAndrew Turner }
169c120c564SAndrew Turner 
instrDecode(ocsd_instr_info * instr_info)170c120c564SAndrew Turner inline ocsd_err_t TrcPktDecodeI::instrDecode(ocsd_instr_info *instr_info)
171c120c564SAndrew Turner {
172c120c564SAndrew Turner     if(m_uses_idecode)
173c120c564SAndrew Turner         return m_instr_decode.first()->DecodeInstruction(instr_info);
174c120c564SAndrew Turner     return OCSD_ERR_DCD_INTERFACE_UNUSED;
175c120c564SAndrew Turner }
176c120c564SAndrew Turner 
accessMemory(const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,uint32_t * num_bytes,uint8_t * p_buffer)177c120c564SAndrew Turner 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)
178c120c564SAndrew Turner {
179c120c564SAndrew Turner     if(m_uses_memaccess)
180c120c564SAndrew Turner         return m_mem_access.first()->ReadTargetMemory(address,getCoreSightTraceID(),mem_space, num_bytes,p_buffer);
181c120c564SAndrew Turner     return OCSD_ERR_DCD_INTERFACE_UNUSED;
182c120c564SAndrew Turner }
183c120c564SAndrew Turner 
invalidateMemAccCache()184*46e6e290SRuslan Bukin inline ocsd_err_t TrcPktDecodeI::invalidateMemAccCache()
185*46e6e290SRuslan Bukin {
186*46e6e290SRuslan Bukin     if (!m_uses_memaccess)
187*46e6e290SRuslan Bukin         return OCSD_ERR_DCD_INTERFACE_UNUSED;
188*46e6e290SRuslan Bukin     m_mem_access.first()->InvalidateMemAccCache(getCoreSightTraceID());
189*46e6e290SRuslan Bukin     return OCSD_OK;
190*46e6e290SRuslan Bukin }
191*46e6e290SRuslan Bukin 
192c120c564SAndrew Turner /**********************************************************************/
193c120c564SAndrew Turner template <class P, class Pc>
194c120c564SAndrew Turner class TrcPktDecodeBase : public TrcPktDecodeI, public IPktDataIn<P>
195c120c564SAndrew Turner {
196c120c564SAndrew Turner public:
197c120c564SAndrew Turner     TrcPktDecodeBase(const char *component_name);
198c120c564SAndrew Turner     TrcPktDecodeBase(const char *component_name, int instIDNum);
199c120c564SAndrew Turner     virtual ~TrcPktDecodeBase();
200c120c564SAndrew Turner 
201c120c564SAndrew Turner     virtual ocsd_datapath_resp_t PacketDataIn( const ocsd_datapath_op_t op,
202c120c564SAndrew Turner                                                 const ocsd_trc_index_t index_sop,
203c120c564SAndrew Turner                                                 const P *p_packet_in);
204c120c564SAndrew Turner 
205c120c564SAndrew Turner 
206c120c564SAndrew Turner     /* protocol configuration */
207c120c564SAndrew Turner     ocsd_err_t setProtocolConfig(const Pc *config);
getProtocolConfig()208c120c564SAndrew Turner     const Pc *  getProtocolConfig() const { return  m_config; };
209c120c564SAndrew Turner 
210c120c564SAndrew Turner protected:
211c120c564SAndrew Turner     void ClearConfigObj();
212c120c564SAndrew Turner 
213c120c564SAndrew Turner     /* the protocol configuration */
214c120c564SAndrew Turner     Pc *          m_config;
215c120c564SAndrew Turner     /* the current input packet */
216c120c564SAndrew Turner     const P *     m_curr_packet_in;
217c120c564SAndrew Turner 
218c120c564SAndrew Turner };
219c120c564SAndrew Turner 
220c120c564SAndrew Turner 
TrcPktDecodeBase(const char * component_name)221c120c564SAndrew Turner template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name) :
222c120c564SAndrew Turner     TrcPktDecodeI(component_name),
223c120c564SAndrew Turner     m_config(0)
224c120c564SAndrew Turner {
225c120c564SAndrew Turner }
226c120c564SAndrew Turner 
TrcPktDecodeBase(const char * component_name,int instIDNum)227c120c564SAndrew Turner template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name, int instIDNum) :
228c120c564SAndrew Turner     TrcPktDecodeI(component_name,instIDNum),
229c120c564SAndrew Turner     m_config(0)
230c120c564SAndrew Turner {
231c120c564SAndrew Turner }
232c120c564SAndrew Turner 
~TrcPktDecodeBase()233c120c564SAndrew Turner template <class P, class Pc> TrcPktDecodeBase<P, Pc>::~TrcPktDecodeBase()
234c120c564SAndrew Turner {
235c120c564SAndrew Turner     ClearConfigObj();
236c120c564SAndrew Turner }
237c120c564SAndrew Turner 
PacketDataIn(const ocsd_datapath_op_t op,const ocsd_trc_index_t index_sop,const P * p_packet_in)238c120c564SAndrew Turner template <class P, class Pc> ocsd_datapath_resp_t TrcPktDecodeBase<P, Pc>::PacketDataIn( const ocsd_datapath_op_t op,
239c120c564SAndrew Turner                                                 const ocsd_trc_index_t index_sop,
240c120c564SAndrew Turner                                                 const P *p_packet_in)
241c120c564SAndrew Turner {
242c120c564SAndrew Turner     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
243c120c564SAndrew Turner     if(!checkInit())
244c120c564SAndrew Turner     {
245c120c564SAndrew Turner         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_NOT_INIT,init_err_msg));
246c120c564SAndrew Turner         return OCSD_RESP_FATAL_NOT_INIT;
247c120c564SAndrew Turner     }
248c120c564SAndrew Turner 
249c120c564SAndrew Turner     switch(op)
250c120c564SAndrew Turner     {
251c120c564SAndrew Turner     case OCSD_OP_DATA:
252c120c564SAndrew Turner         if(p_packet_in == 0)
253c120c564SAndrew Turner         {
254c120c564SAndrew Turner             LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL));
255c120c564SAndrew Turner             resp = OCSD_RESP_FATAL_INVALID_PARAM;
256c120c564SAndrew Turner         }
257c120c564SAndrew Turner         else
258c120c564SAndrew Turner         {
259c120c564SAndrew Turner             m_curr_packet_in = p_packet_in;
260c120c564SAndrew Turner             m_index_curr_pkt = index_sop;
261c120c564SAndrew Turner             resp = processPacket();
262c120c564SAndrew Turner         }
263c120c564SAndrew Turner         break;
264c120c564SAndrew Turner 
265c120c564SAndrew Turner     case OCSD_OP_EOT:
266c120c564SAndrew Turner         resp = onEOT();
267c120c564SAndrew Turner         break;
268c120c564SAndrew Turner 
269c120c564SAndrew Turner     case OCSD_OP_FLUSH:
270c120c564SAndrew Turner         resp = onFlush();
271c120c564SAndrew Turner         break;
272c120c564SAndrew Turner 
273c120c564SAndrew Turner     case OCSD_OP_RESET:
274c120c564SAndrew Turner         resp = onReset();
275c120c564SAndrew Turner         break;
276c120c564SAndrew Turner 
277c120c564SAndrew Turner     default:
278c120c564SAndrew Turner         LogError(ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PARAM_VAL));
279c120c564SAndrew Turner         resp = OCSD_RESP_FATAL_INVALID_OP;
280c120c564SAndrew Turner         break;
281c120c564SAndrew Turner     }
282c120c564SAndrew Turner     return resp;
283c120c564SAndrew Turner }
284c120c564SAndrew Turner 
285c120c564SAndrew Turner     /* protocol configuration */
setProtocolConfig(const Pc * config)286c120c564SAndrew Turner template <class P, class Pc>  ocsd_err_t TrcPktDecodeBase<P, Pc>::setProtocolConfig(const Pc *config)
287c120c564SAndrew Turner {
288c120c564SAndrew Turner     ocsd_err_t err = OCSD_ERR_INVALID_PARAM_VAL;
289c120c564SAndrew Turner     if(config != 0)
290c120c564SAndrew Turner     {
291c120c564SAndrew Turner         ClearConfigObj(); // remove any current config
292c120c564SAndrew Turner         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.
293c120c564SAndrew Turner         if(m_config != 0)
294c120c564SAndrew Turner         {
295c120c564SAndrew Turner             err = onProtocolConfig();
296c120c564SAndrew Turner             if(err == OCSD_OK)
297c120c564SAndrew Turner                 m_config_init_ok = true;
298c120c564SAndrew Turner         }
299c120c564SAndrew Turner         else
300c120c564SAndrew Turner             err = OCSD_ERR_MEM;
301c120c564SAndrew Turner     }
302c120c564SAndrew Turner     return err;
303c120c564SAndrew Turner }
304c120c564SAndrew Turner 
ClearConfigObj()305c120c564SAndrew Turner template <class P, class Pc> void TrcPktDecodeBase<P, Pc>::ClearConfigObj()
306c120c564SAndrew Turner {
307c120c564SAndrew Turner     if(m_config)
308c120c564SAndrew Turner     {
309c120c564SAndrew Turner         delete m_config;
310c120c564SAndrew Turner         m_config = 0;
311c120c564SAndrew Turner     }
312c120c564SAndrew Turner }
313c120c564SAndrew Turner 
314c120c564SAndrew Turner /** @}*/
315c120c564SAndrew Turner #endif // ARM_TRC_PKT_DECODE_BASE_H_INCLUDED
316c120c564SAndrew Turner 
317c120c564SAndrew Turner /* End of File trc_pkt_decode_base.h */
318