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 #include "opencsd/trc_gen_elem_types.h"
38
39 #include <deque>
40 #include <vector>
41
42 /* ETMv4 I trace stack elements
43 Speculation requires that we stack certain elements till they are committed or
44 cancelled. (P0 elements + other associated parts.)
45 */
46
47 typedef enum _p0_elem_t
48 {
49 P0_UNKNOWN,
50 P0_ATOM,
51 P0_ADDR,
52 P0_CTXT,
53 P0_TRC_ON,
54 P0_EXCEP,
55 P0_EXCEP_RET,
56 P0_EVENT,
57 P0_TS,
58 P0_CC,
59 P0_TS_CC,
60 P0_MARKER,
61 P0_Q,
62 P0_OVERFLOW,
63 P0_FUNC_RET,
64 P0_SRC_ADDR,
65 P0_TRANS_TRACE_INIT,
66 P0_TRANS_START,
67 P0_TRANS_COMMIT,
68 P0_TRANS_FAIL
69 } p0_elem_t;
70
71
72 /************************************************************/
73 /***Trace stack element base class -
74 record originating packet type and index in buffer*/
75
76 class TrcStackElem {
77 public:
78 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()79 virtual ~TrcStackElem() {};
80
getP0Type()81 const p0_elem_t getP0Type() const { return m_P0_type; };
getRootPkt()82 const ocsd_etmv4_i_pkt_type getRootPkt() const { return m_root_pkt; };
getRootIndex()83 const ocsd_trc_index_t getRootIndex() const { return m_root_idx; };
isP0()84 const bool isP0() const { return m_is_P0; };
85
86 private:
87 ocsd_etmv4_i_pkt_type m_root_pkt;
88 ocsd_trc_index_t m_root_idx;
89 p0_elem_t m_P0_type;
90
91 protected:
92 bool m_is_P0; // true if genuine P0 - commit / cancellable, false otherwise
93
94 };
95
TrcStackElem(p0_elem_t p0_type,const bool isP0,ocsd_etmv4_i_pkt_type root_pkt,ocsd_trc_index_t root_index)96 inline TrcStackElem::TrcStackElem(p0_elem_t p0_type, const bool isP0, ocsd_etmv4_i_pkt_type root_pkt, ocsd_trc_index_t root_index) :
97 m_root_pkt(root_pkt),
98 m_root_idx(root_index),
99 m_P0_type(p0_type),
100 m_is_P0(isP0)
101 {
102 }
103
104 /************************************************************/
105 /** Address element */
106
107 class TrcStackElemAddr : public TrcStackElem
108 {
109 protected:
110 TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
111 TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool src_addr);
~TrcStackElemAddr()112 virtual ~TrcStackElemAddr() {};
113
114 friend class EtmV4P0Stack;
115
116 public:
setAddr(const etmv4_addr_val_t & addr_val)117 void setAddr(const etmv4_addr_val_t &addr_val) { m_addr_val = addr_val; };
getAddr()118 const etmv4_addr_val_t &getAddr() const { return m_addr_val; };
119
120 private:
121 etmv4_addr_val_t m_addr_val;
122 };
123
TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)124 inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
125 TrcStackElem(P0_ADDR, false, root_pkt,root_index)
126 {
127 m_addr_val.val = 0;
128 m_addr_val.isa = 0;
129 }
130
TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index,const bool src_addr)131 inline TrcStackElemAddr::TrcStackElemAddr(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool src_addr) :
132 TrcStackElem(src_addr ? P0_SRC_ADDR : P0_ADDR, false, root_pkt, root_index)
133 {
134 m_addr_val.val = 0;
135 m_addr_val.isa = 0;
136 }
137
138
139 /************************************************************/
140 /** Q element */
141 class TrcStackQElem : public TrcStackElem
142 {
143 protected:
144 TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackQElem()145 virtual ~TrcStackQElem() {};
146
147 friend class EtmV4P0Stack;
148
149 public:
setInstrCount(const int instr_count)150 void setInstrCount(const int instr_count) { m_instr_count = instr_count; };
getInstrCount()151 const int getInstrCount() const { return m_instr_count; }
152
setAddr(const etmv4_addr_val_t & addr_val)153 void setAddr(const etmv4_addr_val_t &addr_val)
154 {
155 m_addr_val = addr_val;
156 m_has_addr = true;
157 };
getAddr()158 const etmv4_addr_val_t &getAddr() const { return m_addr_val; };
hasAddr()159 const bool hasAddr() const { return m_has_addr; };
160
161 private:
162 bool m_has_addr;
163 etmv4_addr_val_t m_addr_val;
164 int m_instr_count;
165
166 };
167
TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)168 inline TrcStackQElem::TrcStackQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
169 TrcStackElem(P0_Q , true, root_pkt, root_index)
170 {
171 m_addr_val.val = 0;
172 m_addr_val.isa = 0;
173 m_has_addr = false;
174 m_instr_count = 0;
175 }
176
177 /************************************************************/
178 /** Context element */
179
180 class TrcStackElemCtxt : public TrcStackElem
181 {
182 protected:
183 TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemCtxt()184 virtual ~TrcStackElemCtxt() {};
185
186 friend class EtmV4P0Stack;
187
188 public:
setContext(const etmv4_context_t & ctxt)189 void setContext(const etmv4_context_t &ctxt) { m_context = ctxt; };
getContext()190 const etmv4_context_t &getContext() const { return m_context; };
setIS(const uint8_t IS)191 void setIS(const uint8_t IS) { m_IS = IS; };
getIS()192 const uint8_t getIS() const { return m_IS; };
193
194 private:
195 etmv4_context_t m_context;
196 uint8_t m_IS; //!< IS value at time of generation of packet.
197 };
198
TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)199 inline TrcStackElemCtxt::TrcStackElemCtxt(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
200 TrcStackElem(P0_CTXT, false, root_pkt,root_index)
201 {
202 }
203
204 /************************************************************/
205 /** Exception element */
206
207 class TrcStackElemExcept : public TrcStackElem
208 {
209 protected:
210 TrcStackElemExcept(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemExcept()211 virtual ~TrcStackElemExcept() {};
212
213 friend class EtmV4P0Stack;
214
215 public:
setPrevSame(bool bSame)216 void setPrevSame(bool bSame) { m_prev_addr_same = bSame; };
getPrevSame()217 const bool getPrevSame() const { return m_prev_addr_same; };
218
setExcepNum(const uint16_t num)219 void setExcepNum(const uint16_t num) { m_excep_num = num; };
getExcepNum()220 const uint16_t getExcepNum() const { return m_excep_num; };
221
222 private:
223 bool m_prev_addr_same;
224 uint16_t m_excep_num;
225 };
226
TrcStackElemExcept(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)227 inline TrcStackElemExcept::TrcStackElemExcept(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
228 TrcStackElem(P0_EXCEP, true, root_pkt,root_index),
229 m_prev_addr_same(false)
230 {
231 }
232
233 /************************************************************/
234 /** Atom element */
235
236 class TrcStackElemAtom : public TrcStackElem
237 {
238 protected:
239 TrcStackElemAtom(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemAtom()240 virtual ~TrcStackElemAtom() {};
241
242 friend class EtmV4P0Stack;
243
244 public:
setAtom(const ocsd_pkt_atom & atom)245 void setAtom(const ocsd_pkt_atom &atom) { m_atom = atom; };
246
247 const ocsd_atm_val commitOldest();
248 int cancelNewest(const int nCancel);
249 void mispredictNewest();
isEmpty()250 const bool isEmpty() const { return (m_atom.num == 0); };
251
252 private:
253 ocsd_pkt_atom m_atom;
254 };
255
TrcStackElemAtom(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)256 inline TrcStackElemAtom::TrcStackElemAtom(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
257 TrcStackElem(P0_ATOM, true, root_pkt,root_index)
258 {
259 m_atom.num = 0;
260 }
261
262 // commit oldest - get value and remove it from pattern
commitOldest()263 inline const ocsd_atm_val TrcStackElemAtom::commitOldest()
264 {
265 ocsd_atm_val val = (m_atom.En_bits & 0x1) ? ATOM_E : ATOM_N;
266 m_atom.num--;
267 m_atom.En_bits >>= 1;
268 return val;
269 }
270
271 // cancel newest - just reduce the atom count.
cancelNewest(const int nCancel)272 inline int TrcStackElemAtom::cancelNewest(const int nCancel)
273 {
274 int nRemove = (nCancel <= m_atom.num) ? nCancel : m_atom.num;
275 m_atom.num -= nRemove;
276 return nRemove;
277 }
278
279 // mispredict newest - flip the bit of the newest atom
mispredictNewest()280 inline void TrcStackElemAtom::mispredictNewest()
281 {
282 uint32_t mask = 0x1 << (m_atom.num - 1);
283 if (m_atom.En_bits & mask)
284 m_atom.En_bits &= ~mask;
285 else
286 m_atom.En_bits |= mask;
287 }
288
289 /************************************************************/
290 /** Generic param element */
291
292 class TrcStackElemParam : public TrcStackElem
293 {
294 protected:
295 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()296 virtual ~TrcStackElemParam() {};
297
298 friend class EtmV4P0Stack;
299
300 public:
setParam(const uint32_t param,const int nParamNum)301 void setParam(const uint32_t param, const int nParamNum) { m_param[(nParamNum & 0x3)] = param; };
getParam(const int nParamNum)302 const uint32_t &getParam(const int nParamNum) const { return m_param[(nParamNum & 0x3)]; };
303
304 private:
305 uint32_t m_param[4];
306 };
307
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)308 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) :
309 TrcStackElem(p0_type, isP0, root_pkt,root_index)
310 {
311 }
312
313 /************************************************************/
314 /** Marker element */
315
316 class TrcStackElemMarker : public TrcStackElem
317 {
318 protected:
319 TrcStackElemMarker(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index);
~TrcStackElemMarker()320 virtual ~TrcStackElemMarker() {};
321
322 friend class EtmV4P0Stack;
323
324 public:
setMarker(const trace_marker_payload_t & marker)325 void setMarker(const trace_marker_payload_t &marker) { m_marker = marker; };
getMarker()326 const trace_marker_payload_t &getMarker() const { return m_marker; };
327
328 private:
329 trace_marker_payload_t m_marker;
330 };
331
TrcStackElemMarker(const ocsd_etmv4_i_pkt_type root_pkt,const ocsd_trc_index_t root_index)332 inline TrcStackElemMarker::TrcStackElemMarker(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index) :
333 TrcStackElem(P0_MARKER, false, root_pkt, root_index)
334 {
335 }
336
337
338 /************************************************************/
339 /* P0 element stack that allows push of elements, and deletion of elements when done.
340 */
341 class EtmV4P0Stack
342 {
343 public:
EtmV4P0Stack()344 EtmV4P0Stack() {};
345 ~EtmV4P0Stack();
346
347 void push_front(TrcStackElem *pElem);
348 void push_back(TrcStackElem *pElem); // insert element when processing
349 void pop_back(bool pend_delete = true);
350 void pop_front(bool pend_delete = true);
351 TrcStackElem *back();
352 TrcStackElem *front();
353 size_t size();
354
355 // iterate through stack from front
356 void from_front_init();
357 TrcStackElem *from_front_next();
358 void erase_curr_from_front(); // erase the element last returned
359
360 void delete_all();
361 void delete_back();
362 void delete_front();
363 void delete_popped();
364
365 // creation functions - create and push if successful.
366 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);
367 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);
368 TrcStackElemAtom *createAtomElem (const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const ocsd_pkt_atom &atom);
369 TrcStackElemExcept *createExceptElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const bool bSame, const uint16_t excepNum);
370 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);
371 TrcStackElemAddr *createAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val);
372 TrcStackQElem *createQElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const int count);
373 TrcStackElemMarker *createMarkerElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const trace_marker_payload_t &marker);
374 TrcStackElemAddr *createSrcAddrElem(const ocsd_etmv4_i_pkt_type root_pkt, const ocsd_trc_index_t root_index, const etmv4_addr_val_t &addr_val);
375
376 private:
377 std::deque<TrcStackElem *> m_P0_stack; //!< P0 decode element stack
378 std::vector<TrcStackElem *> m_popped_elem; //!< save list of popped but not deleted elements.
379 std::deque<TrcStackElem *>::iterator m_iter; //!< iterate across the list w/o removing stuff
380 };
381
~EtmV4P0Stack()382 inline EtmV4P0Stack::~EtmV4P0Stack()
383 {
384 delete_all();
385 delete_popped();
386 }
387
388 // put an element on the front of the stack
push_front(TrcStackElem * pElem)389 inline void EtmV4P0Stack::push_front(TrcStackElem *pElem)
390 {
391 m_P0_stack.push_front(pElem);
392 }
393
394 // put an element on the back of the stack
push_back(TrcStackElem * pElem)395 inline void EtmV4P0Stack::push_back(TrcStackElem *pElem)
396 {
397 m_P0_stack.push_back(pElem);
398 }
399
400 // pop last element pointer off the stack and stash it for later deletion
pop_back(bool pend_delete)401 inline void EtmV4P0Stack::pop_back(bool pend_delete /* = true */)
402 {
403 if (pend_delete)
404 m_popped_elem.push_back(m_P0_stack.back());
405 m_P0_stack.pop_back();
406 }
407
pop_front(bool pend_delete)408 inline void EtmV4P0Stack::pop_front(bool pend_delete /* = true */)
409 {
410 if (pend_delete)
411 m_popped_elem.push_back(m_P0_stack.front());
412 m_P0_stack.pop_front();
413 }
414
415 // pop last element pointer off the stack and delete immediately
delete_back()416 inline void EtmV4P0Stack::delete_back()
417 {
418 if (m_P0_stack.size() > 0)
419 {
420 TrcStackElem* pElem = m_P0_stack.back();
421 delete pElem;
422 m_P0_stack.pop_back();
423 }
424 }
425
426 // pop first element pointer off the stack and delete immediately
delete_front()427 inline void EtmV4P0Stack::delete_front()
428 {
429 if (m_P0_stack.size() > 0)
430 {
431 TrcStackElem* pElem = m_P0_stack.front();
432 delete pElem;
433 m_P0_stack.pop_front();
434 }
435 }
436
437
438
439 // get a pointer to the last element on the stack
back()440 inline TrcStackElem *EtmV4P0Stack::back()
441 {
442 return m_P0_stack.back();
443 }
444
front()445 inline TrcStackElem *EtmV4P0Stack::front()
446 {
447 return m_P0_stack.front();
448 }
449
450 // remove and delete all the elements left on the stack
delete_all()451 inline void EtmV4P0Stack::delete_all()
452 {
453 while (m_P0_stack.size() > 0)
454 delete_back();
455 m_P0_stack.clear();
456 }
457
458 // delete list of popped elements.
delete_popped()459 inline void EtmV4P0Stack::delete_popped()
460 {
461 while (m_popped_elem.size() > 0)
462 {
463 delete m_popped_elem.back();
464 m_popped_elem.pop_back();
465 }
466 m_popped_elem.clear();
467 }
468
469 // get current number of elements on the stack
size()470 inline size_t EtmV4P0Stack::size()
471 {
472 return m_P0_stack.size();
473 }
474
475 #endif // ARM_TRC_ETMV4_STACK_ELEM_H_INCLUDED
476
477 /* End of File trc_etmv4_stack_elem.h */
478