1 /*!
2  * \file       trc_pkt_decode_etmv3.h
3  * \brief      OpenCSD : ETMv3 decode
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_ETMV3_H_INCLUDED
36 #define ARM_TRC_PKT_DECODE_ETMV3_H_INCLUDED
37 
38 #include "common/trc_pkt_decode_base.h"
39 #include "common/trc_gen_elem.h"
40 #include "common/ocsd_pe_context.h"
41 #include "common/ocsd_code_follower.h"
42 #include "common/ocsd_gen_elem_list.h"
43 
44 #include "opencsd/etmv3/trc_pkt_elem_etmv3.h"
45 #include "opencsd/etmv3/trc_cmp_cfg_etmv3.h"
46 
47 /**************** Atom handling class **************************************/
48 class Etmv3Atoms
49 {
50 public:
51     Etmv3Atoms(const bool isCycleAcc);
52     ~Etmv3Atoms() {};
53 
54     //! initialise the atom and index values
55     void initAtomPkt(const EtmV3TrcPacket *in_pkt, const ocsd_trc_index_t &root_index);
56 
57     const ocsd_atm_val getCurrAtomVal() const;
58     const int numAtoms() const; //!< number of atoms
59     const ocsd_trc_index_t pktIndex() const; //!< originating packet index
60 
61     const bool hasAtomCC() const;   //!< cycle count for current atom?
62     const uint32_t getAtomCC() const;   //!< cycle count for current atom
63     const uint32_t getRemainCC() const; //!< get residual cycle count for remaining atoms
64 
65     void clearAtom();   //!< clear the current atom, set the next.
66     void clearAll();    //!< clear all
67 
68 private:
69 
70     // Atom PHDR packet formats from ETMv3 spec - defines content of header.
71     enum {
72         ATOM_PHDR_FMT_1 = 1,
73         ATOM_PHDR_FMT_2,
74         ATOM_PHDR_FMT_3,
75         ATOM_PHDR_FMT_4,
76     };
77 
78 
79 
80     ocsd_pkt_atom m_atom;         /**< atom elements - non zero number indicates valid atom count */
81     uint8_t m_p_hdr_fmt;          /**< if atom elements, associated phdr format */
82     uint32_t m_cycle_count;
83     ocsd_trc_index_t m_root_index; //!< root index for the atom packet
84     bool m_isCCPacket;
85 };
86 
87 
88 inline Etmv3Atoms::Etmv3Atoms(const bool isCycleAcc)
89 {
90     m_isCCPacket = isCycleAcc;
91 }
92 
93 //! initialise the atom and index values
94 inline void Etmv3Atoms::initAtomPkt(const EtmV3TrcPacket *in_pkt, const ocsd_trc_index_t &root_index)
95 {
96     m_atom = in_pkt->getAtom();
97     m_p_hdr_fmt = in_pkt->getPHdrFmt();
98     m_cycle_count = in_pkt->getCycleCount();
99 }
100 
101 inline const ocsd_atm_val Etmv3Atoms::getCurrAtomVal() const
102 {
103     return (m_atom.En_bits & 0x1) ? ATOM_E : ATOM_N;
104 }
105 
106 inline const int Etmv3Atoms::numAtoms() const
107 {
108     return m_atom.num;
109 }
110 
111 inline const ocsd_trc_index_t Etmv3Atoms::pktIndex() const
112 {
113     return  m_root_index;
114 }
115 
116 inline const bool Etmv3Atoms::hasAtomCC() const
117 {
118     bool hasCC = false;
119     if(!m_isCCPacket)
120         return hasCC;
121 
122     switch(m_p_hdr_fmt)
123     {
124     case ATOM_PHDR_FMT_4:
125     default:
126         break;
127 
128     case ATOM_PHDR_FMT_3:
129     case ATOM_PHDR_FMT_1:
130         hasCC = true;
131         break;
132 
133     case ATOM_PHDR_FMT_2:
134         hasCC = (m_atom.num > 1);   // first of 2 has W state
135         break;
136     }
137     return hasCC;
138 }
139 
140 inline const uint32_t Etmv3Atoms::getAtomCC() const
141 {
142     uint32_t CC = 0;
143     if(!m_isCCPacket)
144         return CC;
145 
146     switch(m_p_hdr_fmt)
147     {
148     case ATOM_PHDR_FMT_4: // no CC in format 4
149     default:
150         break;
151 
152     case ATOM_PHDR_FMT_3: // single CC with optional E atom
153         CC = m_cycle_count;
154         break;
155 
156     case ATOM_PHDR_FMT_2: // single W on first of 2 atoms
157         CC = (m_atom.num > 1) ? 1: 0;
158         break;
159 
160     case ATOM_PHDR_FMT_1: // each atom has 1 CC.
161         CC = 1;
162         break;
163     }
164     return CC;
165 }
166 
167 inline const uint32_t Etmv3Atoms::getRemainCC() const
168 {
169     uint32_t CC = 0;
170     if(!m_isCCPacket)
171         return CC;
172 
173     switch(m_p_hdr_fmt)
174     {
175     case ATOM_PHDR_FMT_4: // no CC in format 4
176     default:
177         break;
178 
179     case ATOM_PHDR_FMT_3:
180         CC = m_cycle_count;
181         break;
182 
183     case ATOM_PHDR_FMT_2:
184         CC = (m_atom.num > 1) ? 1: 0;
185         break;
186 
187     case ATOM_PHDR_FMT_1:
188         CC = m_atom.num;
189         break;
190     }
191     return CC;
192 }
193 
194 inline void Etmv3Atoms::clearAtom()
195 {
196     m_atom.En_bits >>=1;
197     if(m_atom.num)
198         m_atom.num--;
199 }
200 
201 inline void Etmv3Atoms::clearAll()
202 {
203     m_atom.num = 0;
204 }
205 
206 /********** Main decode class ****************************************************/
207 class TrcPktDecodeEtmV3 :  public TrcPktDecodeBase<EtmV3TrcPacket, EtmV3Config>
208 {
209 public:
210     TrcPktDecodeEtmV3();
211     TrcPktDecodeEtmV3(int instIDNum);
212     virtual ~TrcPktDecodeEtmV3();
213 
214 protected:
215     /* implementation packet decoding interface */
216     virtual ocsd_datapath_resp_t processPacket();
217     virtual ocsd_datapath_resp_t onEOT();
218     virtual ocsd_datapath_resp_t onReset();
219     virtual ocsd_datapath_resp_t onFlush();
220     virtual ocsd_err_t onProtocolConfig();
221     virtual const uint8_t getCoreSightTraceID() { return m_CSID; };
222 
223     /* local decode methods */
224     void initDecoder();      //!< initial state on creation (zeros all config)
225     void resetDecoder();     //!< reset state to start of decode. (moves state, retains config)
226 
227     ocsd_datapath_resp_t decodePacket(bool &pktDone); //!< decode a packet
228 
229     ocsd_datapath_resp_t processISync(const bool withCC, const bool firstSync = false);
230     ocsd_datapath_resp_t processBranchAddr();
231     ocsd_datapath_resp_t processPHdr();
232 
233     ocsd_datapath_resp_t sendUnsyncPacket();    //!< send an initial unsync packet when decoder starts
234 
235     OcsdTraceElement *GetNextOpElem(ocsd_datapath_resp_t &resp);    //!< get the next element from the element list.
236 
237 private:
238     void setNeedAddr(bool bNeedAddr);
239     void pendExceptionReturn();
240     bool preISyncValid(ocsd_etmv3_pkt_type pkt_type);
241 //** intra packet state;
242 
243     OcsdCodeFollower m_code_follower;   //!< code follower for instruction trace
244 
245     ocsd_vaddr_t m_IAddr;           //!< next instruction address
246     bool m_bNeedAddr;               //!< true if an address is needed (current out of date / invalid)
247     bool m_bSentUnknown;            //!< true if we have sent an unknown address packet for this phase of needing an address.
248     bool m_bWaitISync;              //!< true if waiting for first ISync packet
249 
250     OcsdPeContext m_PeContext;      //!< save context data before sending in output packet
251 
252     OcsdGenElemList m_outputElemList;   //!< list of output elements
253 
254 
255 //** Other packet decoder state;
256 
257     // trace decode FSM
258     typedef enum {
259         NO_SYNC,        //!< pre start trace - init state or after reset or overflow, loss of sync.
260         WAIT_ASYNC,     //!< waiting for a-sync packet.
261         WAIT_ISYNC,     //!< waiting for i-sync packet.
262         DECODE_PKTS,    //!< processing a packet
263         SEND_PKTS,      //!< sending packets.
264     } processor_state_t;
265 
266     processor_state_t m_curr_state;
267     unsync_info_t m_unsync_info;    //!< additional state for unsync
268 
269     uint8_t m_CSID; //!< Coresight trace ID for this decoder.
270 };
271 
272 
273 #endif // ARM_TRC_PKT_DECODE_ETMV3_H_INCLUDED
274 
275 /* End of File trc_pkt_decode_etmv3.h */
276