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> ¶ms); 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