1 /*
2 * \file trc_etmv4_stack_elem.h
3 * \brief OpenCSD :
4 *
5 * \copyright Copyright (c) 2015, ARM Limited. All Rights Reserved.
6 */
7 /*
8 * Redistribution and use in source and binary forms, with or without modification,
9 * are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 *
18 * 3. Neither the name of the copyright holder nor the names of its contributors
19 * may be used to endorse or promote products derived from this software without
20 * specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 #ifndef ARM_TRC_ETMV4_STACK_ELEM_H_INCLUDED
34 #define ARM_TRC_ETMV4_STACK_ELEM_H_INCLUDED
35
36 #include "opencsd/etmv4/trc_pkt_types_etmv4.h"
37
38 #include <deque>
39 #include <vector>
40
41 /* ETMv4 I trace stack elements
42 Speculation requires that we stack certain elements till they are committed or
43 cancelled. (P0 elements + other associated parts.)
44 */
45
46 typedef enum _p0_elem_t
47 {
48 P0_UNKNOWN,
49 P0_ATOM,
50 P0_ADDR,
51 P0_CTXT,
52 P0_TRC_ON,
53 P0_EXCEP,
54 P0_EXCEP_RET,
55 P0_EVENT,
56 P0_TS,
57 P0_CC,
58 P0_TS_CC,
59 P0_Q,
60 P0_OVERFLOW,
61 P0_FUNC_RET,
62 } p0_elem_t;
63
64
65 /************************************************************/
66 /***Trace stack element base class -
67 record originating packet type and index in buffer*/
68
69 class TrcStackElem {
70 public:
71 TrcStackElem(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElem()72 virtual ~TrcStackElem() {};
73
getP0Type()74 const p0_elem_t getP0Type() const { return m_P0_type; };
getRootPkt()75 const ocsd_etmv4_i_pkt_type getRootPkt() const { return m_root_pkt; };
getRootIndex()76 const ocsd_trc_index_t getRootIndex() const { return m_root_idx; };
isP0()77 const bool isP0() const { return m_is_P0; };
78
79 private:
80 ocsd_etmv4_i_pkt_type m_root_pkt;
81 ocsd_trc_index_t m_root_idx;
82 p0_elem_t m_P0_type;
83
84 protected:
85 bool m_is_P0; // true if genuine P0 - commit / cancellable, false otherwise
86
87 };
88
TrcStackElem(p0_elem_t p0_type,const bool isP0,ocsd_etmv4_i_pkt_type root_pkt,ocsd_trc_index_t root_index)89 inline TrcStackElem::TrcStackElem(p0_elem_t p0_type, const bool isP0, ocsd_etmv4_i_pkt_type root_pkt, ocsd_trc_index_t root_index) :
90 m_root_pkt(root_pkt),
91 m_root_idx(root_index),
92 m_P0_type(p0_type),
93 m_is_P0(isP0)
94 {
95 }
96
97 /************************************************************/
98 /** Address element */
99
100 class TrcStackElemAddr : public TrcStackElem
101 {
102 protected:
103 TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemAddr()104 virtual ~TrcStackElemAddr() {};
105
106 friend class EtmV4P0Stack;
107
108 public:
setAddr(const etmv4_addr_val_t & addr_val)109 void setAddr(const etmv4_addr_val_t &addr_val) { m_addr_val = addr_val; };
getAddr()110 const etmv4_addr_val_t &getAddr() const { return m_addr_val; };
111
112 private:
113 etmv4_addr_val_t m_addr_val;
114 };
115
TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)116 inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
117 TrcStackElem(P0_ADDR, false, root_pkt,root_index)
118 {
119 m_addr_val.val = 0;
120 m_addr_val.isa = 0;
121 }
122
123 /************************************************************/
124 /** Q element */
125 class TrcStackQElem : public TrcStackElem
126 {
127 protected:
128 TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackQElem()129 virtual ~TrcStackQElem() {};
130
131 friend class EtmV4P0Stack;
132
133 public:
setInstrCount(const int instr_count)134 void setInstrCount(const int instr_count) { m_instr_count = instr_count; };
getInstrCount()135 const int getInstrCount() const { return m_instr_count; }
136
setAddr(const etmv4_addr_val_t & addr_val)137 void setAddr(const etmv4_addr_val_t &addr_val)
138 {
139 m_addr_val = addr_val;
140 m_has_addr = true;
141 };
getAddr()142 const etmv4_addr_val_t &getAddr() const { return m_addr_val; };
hasAddr()143 const bool hasAddr() const { return m_has_addr; };
144
145 private:
146 bool m_has_addr;
147 etmv4_addr_val_t m_addr_val;
148 int m_instr_count;
149
150 };
151
TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)152 inline TrcStackQElem::TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
153 TrcStackElem(P0_Q , true, root_pkt, root_index)
154 {
155 m_addr_val.val = 0;
156 m_addr_val.isa = 0;
157 m_has_addr = false;
158 m_instr_count = 0;
159 }
160
161 /************************************************************/
162 /** Context element */
163
164 class TrcStackElemCtxt : public TrcStackElem
165 {
166 protected:
167 TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemCtxt()168 virtual ~TrcStackElemCtxt() {};
169
170 friend class EtmV4P0Stack;
171
172 public:
setContext(const etmv4_context_t & ctxt)173 void setContext(const etmv4_context_t &ctxt) { m_context = ctxt; };
getContext()174 const etmv4_context_t &getContext() const { return m_context; };
setIS(const uint8_t IS)175 void setIS(const uint8_t IS) { m_IS = IS; };
getIS()176 const uint8_t getIS() const { return m_IS; };
177
178 private:
179 etmv4_context_t m_context;
180 uint8_t m_IS; //!< IS value at time of generation of packet.
181 };
182
TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)183 inline TrcStackElemCtxt::TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
184 TrcStackElem(P0_CTXT, false, root_pkt,root_index)
185 {
186 }
187
188 /************************************************************/
189 /** Exception element */
190
191 class TrcStackElemExcept : public TrcStackElem
192 {
193 protected:
194 TrcStackElemExcept(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemExcept()195 virtual ~TrcStackElemExcept() {};
196
197 friend class EtmV4P0Stack;
198
199 public:
setPrevSame(bool bSame)200 void setPrevSame(bool bSame) { m_prev_addr_same = bSame; };
getPrevSame()201 const bool getPrevSame() const { return m_prev_addr_same; };
202
setExcepNum(const uint16_t num)203 void setExcepNum(const uint16_t num) { m_excep_num = num; };
getExcepNum()204 const uint16_t getExcepNum() const { return m_excep_num; };
205
206 private:
207 bool m_prev_addr_same;
208 uint16_t m_excep_num;
209 };
210
TrcStackElemExcept(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)211 inline TrcStackElemExcept::TrcStackElemExcept(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
212 TrcStackElem(P0_EXCEP, true, root_pkt,root_index),
213 m_prev_addr_same(false)
214 {
215 }
216
217 /************************************************************/
218 /** Atom element */
219
220 class TrcStackElemAtom : public TrcStackElem
221 {
222 protected:
223 TrcStackElemAtom(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemAtom()224 virtual ~TrcStackElemAtom() {};
225
226 friend class EtmV4P0Stack;
227
228 public:
setAtom(const ocsd_pkt_atom & atom)229 void setAtom(const ocsd_pkt_atom &atom) { m_atom = atom; };
230
231 const ocsd_atm_val commitOldest();
232 int cancelNewest(const int nCancel);
233 void mispredictNewest();
isEmpty()234 const bool isEmpty() const { return (m_atom.num == 0); };
235
236 private:
237 ocsd_pkt_atom m_atom;
238 };
239
TrcStackElemAtom(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)240 inline TrcStackElemAtom::TrcStackElemAtom(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
241 TrcStackElem(P0_ATOM, true, root_pkt,root_index)
242 {
243 m_atom.num = 0;
244 }
245
246 // commit oldest - get value and remove it from pattern
commitOldest()247 inline const ocsd_atm_val TrcStackElemAtom::commitOldest()
248 {
249 ocsd_atm_val val = (m_atom.En_bits & 0x1) ? ATOM_E : ATOM_N;
250 m_atom.num--;
251 m_atom.En_bits >>= 1;
252 return val;
253 }
254
255 // cancel newest - just reduce the atom count.
cancelNewest(const int nCancel)256 inline int TrcStackElemAtom::cancelNewest(const int nCancel)
257 {
258 int nRemove = (nCancel <= m_atom.num) ? nCancel : m_atom.num;
259 m_atom.num -= nRemove;
260 return nRemove;
261 }
262
263 // mispredict newest - flip the bit of the newest atom
mispredictNewest()264 inline void TrcStackElemAtom::mispredictNewest()
265 {
266 uint32_t mask = 0x1 << (m_atom.num - 1);
267 if (m_atom.En_bits & mask)
268 m_atom.En_bits &= ~mask;
269 else
270 m_atom.En_bits |= mask;
271 }
272
273 /************************************************************/
274 /** Generic param element */
275
276 class TrcStackElemParam : public TrcStackElem
277 {
278 protected:
279 TrcStackElemParam(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemParam()280 virtual ~TrcStackElemParam() {};
281
282 friend class EtmV4P0Stack;
283
284 public:
setParam(const uint32_t param,const int nParamNum)285 void setParam(const uint32_t param, const int nParamNum) { m_param[(nParamNum & 0x3)] = param; };
getParam(const int nParamNum)286 const uint32_t &getParam(const int nParamNum) const { return m_param[(nParamNum & 0x3)]; };
287
288 private:
289 uint32_t m_param[4];
290 };
291
TrcStackElemParam(const p0_elem_t p0_type,const bool isP0,const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)292 inline TrcStackElemParam::TrcStackElemParam(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
293 TrcStackElem(p0_type, isP0, root_pkt,root_index)
294 {
295 }
296
297 /************************************************************/
298 /* P0 element stack that allows push of elements, and deletion of elements when done.
299 */
300 class EtmV4P0Stack
301 {
302 public:
EtmV4P0Stack()303 EtmV4P0Stack() {};
304 ~EtmV4P0Stack();
305
306 void push_front(TrcStackElem *pElem);
307 void push_back(TrcStackElem *pElem); // insert element when processing
308 void pop_back(bool pend_delete = true);
309 void pop_front(bool pend_delete = true);
310 TrcStackElem *back();
311 TrcStackElem *front();
312 size_t size();
313
314 // iterate through stack from front
315 void from_front_init();
316 TrcStackElem *from_front_next();
317 void erase_curr_from_front(); // erase the element last returned
318
319 void delete_all();
320 void delete_back();
321 void delete_front();
322 void delete_popped();
323
324 // creation functions - create and push if successful.
325 TrcStackElemParam *createParamElem(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const std::vector<uint32_t> ¶ms);
326 TrcStackElem *createParamElemNoParam(const p0_elem_t p0_type, const bool isP0, const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, bool back = false);
327 TrcStackElemAtom *createAtomElem (const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const ocsd_pkt_atom &atom);
328 TrcStackElemExcept *createExceptElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool bSame, const uint16_t excepNum);
329 TrcStackElemCtxt *createContextElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_context_t &context, const uint8_t IS, const bool back = false);
330 TrcStackElemAddr *createAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val);
331 TrcStackQElem *createQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const int count);
332 private:
333 std::deque<TrcStackElem *> m_P0_stack; //!< P0 decode element stack
334 std::vector<TrcStackElem *> m_popped_elem; //!< save list of popped but not deleted elements.
335 std::deque<TrcStackElem *>::iterator m_iter; //!< iterate across the list w/o removing stuff
336 };
337
~EtmV4P0Stack()338 inline EtmV4P0Stack::~EtmV4P0Stack()
339 {
340 delete_all();
341 delete_popped();
342 }
343
344 // put an element on the front of the stack
push_front(TrcStackElem * pElem)345 inline void EtmV4P0Stack::push_front(TrcStackElem *pElem)
346 {
347 m_P0_stack.push_front(pElem);
348 }
349
350 // put an element on the back of the stack
push_back(TrcStackElem * pElem)351 inline void EtmV4P0Stack::push_back(TrcStackElem *pElem)
352 {
353 m_P0_stack.push_back(pElem);
354 }
355
356 // pop last element pointer off the stack and stash it for later deletion
pop_back(bool pend_delete)357 inline void EtmV4P0Stack::pop_back(bool pend_delete /* = true */)
358 {
359 if (pend_delete)
360 m_popped_elem.push_back(m_P0_stack.back());
361 m_P0_stack.pop_back();
362 }
363
pop_front(bool pend_delete)364 inline void EtmV4P0Stack::pop_front(bool pend_delete /* = true */)
365 {
366 if (pend_delete)
367 m_popped_elem.push_back(m_P0_stack.front());
368 m_P0_stack.pop_front();
369 }
370
371 // pop last element pointer off the stack and delete immediately
delete_back()372 inline void EtmV4P0Stack::delete_back()
373 {
374 if (m_P0_stack.size() > 0)
375 {
376 TrcStackElem* pElem = m_P0_stack.back();
377 delete pElem;
378 m_P0_stack.pop_back();
379 }
380 }
381
382 // pop first element pointer off the stack and delete immediately
delete_front()383 inline void EtmV4P0Stack::delete_front()
384 {
385 if (m_P0_stack.size() > 0)
386 {
387 TrcStackElem* pElem = m_P0_stack.front();
388 delete pElem;
389 m_P0_stack.pop_front();
390 }
391 }
392
393
394
395 // get a pointer to the last element on the stack
back()396 inline TrcStackElem *EtmV4P0Stack::back()
397 {
398 return m_P0_stack.back();
399 }
400
front()401 inline TrcStackElem *EtmV4P0Stack::front()
402 {
403 return m_P0_stack.front();
404 }
405
406 // remove and delete all the elements left on the stack
delete_all()407 inline void EtmV4P0Stack::delete_all()
408 {
409 while (m_P0_stack.size() > 0)
410 delete_back();
411 m_P0_stack.clear();
412 }
413
414 // delete list of popped elements.
delete_popped()415 inline void EtmV4P0Stack::delete_popped()
416 {
417 while (m_popped_elem.size() > 0)
418 {
419 delete m_popped_elem.back();
420 m_popped_elem.pop_back();
421 }
422 m_popped_elem.clear();
423 }
424
425 // get current number of elements on the stack
size()426 inline size_t EtmV4P0Stack::size()
427 {
428 return m_P0_stack.size();
429 }
430
431 #endif // ARM_TRC_ETMV4_STACK_ELEM_H_INCLUDED
432
433 /* End of File trc_etmv4_stack_elem.h */
434