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
61class TrcPktDecodeI : public TraceComponent
62{
63public:
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
78protected:
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
120inline 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
130inline 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
140inline 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
160inline 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
165inline 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
170inline 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
177inline 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
184inline 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/**********************************************************************/
193template <class P, class Pc>
194class TrcPktDecodeBase : public TrcPktDecodeI, public IPktDataIn<P>
195{
196public:
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
210protected:
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
221template <class P, class Pc> TrcPktDecodeBase<P, Pc>::TrcPktDecodeBase(const char *component_name) :
222    TrcPktDecodeI(component_name),
223    m_config(0)
224{
225}
226
227template <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
233template <class P, class Pc> TrcPktDecodeBase<P, Pc>::~TrcPktDecodeBase()
234{
235    ClearConfigObj();
236}
237
238template <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 */
286template <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
305template <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