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); 72 virtual ~TrcStackElem() {}; 73 74 const p0_elem_t getP0Type() const { return m_P0_type; }; 75 const ocsd_etmv4_i_pkt_type getRootPkt() const { return m_root_pkt; }; 76 const ocsd_trc_index_t getRootIndex() const { return m_root_idx; }; 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 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); 104 virtual ~TrcStackElemAddr() {}; 105 106 friend class EtmV4P0Stack; 107 108 public: 109 void setAddr(const etmv4_addr_val_t &addr_val) { m_addr_val = addr_val; }; 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 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); 129 virtual ~TrcStackQElem() {}; 130 131 friend class EtmV4P0Stack; 132 133 public: 134 void setInstrCount(const int instr_count) { m_instr_count = instr_count; }; 135 const int getInstrCount() const { return m_instr_count; } 136 137 void setAddr(const etmv4_addr_val_t &addr_val) 138 { 139 m_addr_val = addr_val; 140 m_has_addr = true; 141 }; 142 const etmv4_addr_val_t &getAddr() const { return m_addr_val; }; 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 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); 168 virtual ~TrcStackElemCtxt() {}; 169 170 friend class EtmV4P0Stack; 171 172 public: 173 void setContext(const etmv4_context_t &ctxt) { m_context = ctxt; }; 174 const etmv4_context_t &getContext() const { return m_context; }; 175 void setIS(const uint8_t IS) { m_IS = IS; }; 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 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); 195 virtual ~TrcStackElemExcept() {}; 196 197 friend class EtmV4P0Stack; 198 199 public: 200 void setPrevSame(bool bSame) { m_prev_addr_same = bSame; }; 201 const bool getPrevSame() const { return m_prev_addr_same; }; 202 203 void setExcepNum(const uint16_t num) { m_excep_num = num; }; 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 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); 224 virtual ~TrcStackElemAtom() {}; 225 226 friend class EtmV4P0Stack; 227 228 public: 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(); 234 const bool isEmpty() const { return (m_atom.num == 0); }; 235 236 private: 237 ocsd_pkt_atom m_atom; 238 }; 239 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 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. 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 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); 280 virtual ~TrcStackElemParam() {}; 281 282 friend class EtmV4P0Stack; 283 284 public: 285 void setParam(const uint32_t param, const int nParamNum) { m_param[(nParamNum & 0x3)] = param; }; 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 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: 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 338 inline EtmV4P0Stack::~EtmV4P0Stack() 339 { 340 delete_all(); 341 delete_popped(); 342 } 343 344 // put an element on the front of the stack 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 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 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 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 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 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 396 inline TrcStackElem *EtmV4P0Stack::back() 397 { 398 return m_P0_stack.back(); 399 } 400 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 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. 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 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