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