47#if CP_ANNOTATE 48#include "params/CPA.hh" 49#endif 50 51class System; 52class ThreadContext; 53 54 55#if !CP_ANNOTATE 56class CPA 57{ 58 public: 59 enum flags { 60 FL_NONE = 0x00, 61 FL_HW = 0x01, 62 FL_BAD = 0x02, 63 FL_QOPP = 0x04, 64 FL_WAIT = 0x08, 65 FL_LINK = 0x10, 66 FL_RESET = 0x20 67 }; 68 69 static CPA *cpa() { return NULL; } 70 static bool available() { return false; } 71 bool enabled() { return false; } 72 void swSmBegin(ThreadContext *tc) { return; } 73 void swSmEnd(ThreadContext *tc) { return; } 74 void swExplictBegin(ThreadContext *tc) { return; } 75 void swAutoBegin(ThreadContext *tc, Addr next_pc) { return; } 76 void swEnd(ThreadContext *tc) { return; } 77 void swQ(ThreadContext *tc) { return; } 78 void swDq(ThreadContext *tc) { return; } 79 void swPq(ThreadContext *tc) { return; } 80 void swRq(ThreadContext *tc) { return; } 81 void swWf(ThreadContext *tc) { return; } 82 void swWe(ThreadContext *tc) { return; } 83 void swSq(ThreadContext *tc) { return; } 84 void swAq(ThreadContext *tc) { return; } 85 void swLink(ThreadContext *tc) { return; } 86 void swIdentify(ThreadContext *tc) { return; } 87 uint64_t swGetId(ThreadContext *tc) { return 0; } 88 void swSyscallLink(ThreadContext *tc) { return; } 89 void hwBegin(flags f, System *sys, uint64_t frame, std::string sm, 90 std::string st) { return; } 91 void hwQ(flags f, System *sys, uint64_t frame, std::string sm, 92 std::string q, uint64_t qid, System *q_sys = NULL, 93 int32_t count = 1) { return; } 94 void hwDq(flags f, System *sys, uint64_t frame, std::string sm, 95 std::string q, uint64_t qid, System *q_sys = NULL, 96 int32_t count = 1) { return; } 97 void hwPq(flags f, System *sys, uint64_t frame, std::string sm, 98 std::string q, uint64_t qid, System *q_sys = NULL, 99 int32_t count = 1) { return; } 100 void hwRq(flags f, System *sys, uint64_t frame, std::string sm, 101 std::string q, uint64_t qid, System *q_sys = NULL, 102 int32_t count = 1) { return; } 103 void hwWf(flags f, System *sys, uint64_t frame, std::string sm, 104 std::string q, uint64_t qid, System *q_sys = NULL, 105 int32_t count = 1) { return; } 106 void hwWe(flags f, System *sys, uint64_t frame, std::string sm, 107 std::string q, uint64_t qid, System *q_sys = NULL, 108 int32_t count = 1) { return; } 109}; 110#else 111class CPA : SimObject 112{ 113 public: 114 typedef CPAParams Params; 115 116 /** The known operations that are written to the annotation output file. */ 117 enum ops { 118 OP_BEGIN = 0x01, 119 OP_WAIT_EMPTY = 0x02, 120 OP_WAIT_FULL = 0x03, 121 OP_QUEUE = 0x04, 122 OP_DEQUEUE = 0x05, 123 OP_SIZE_QUEUE = 0x08, 124 OP_PEEK = 0x09, 125 OP_LINK = 0x0A, 126 OP_IDENT = 0x0B, 127 OP_RESERVE = 0x0C 128 }; 129 130 /** Flags for the various options.*/ 131 enum flags { 132 /* no flags */ 133 FL_NONE = 0x00, 134 /* operation was done on hardware */ 135 FL_HW = 0x01, 136 /* operation should cause a warning when encountered */ 137 FL_BAD = 0x02, 138 /* Queue like a stack, not a queue */ 139 FL_QOPP = 0x04, 140 /* Mark HW state as waiting for some non-resource constraint 141 * (e.g. wait because SM only starts after 10 items are queued) */ 142 FL_WAIT = 0x08, 143 /* operation is linking to another state machine */ 144 FL_LINK = 0x10, 145 /* queue should be completely cleared/reset before executing this 146 * operation */ 147 FL_RESET = 0x20 148 }; 149 150 151 152 protected: 153 const Params * 154 params() const 155 { 156 return dynamic_cast<const Params *>(_params); 157 } 158 159 /* struct that is written to the annotation output file */ 160 struct AnnotateData : public RefCounted { 161 162 Tick time; 163 uint32_t data; 164 uint32_t orig_data; 165 uint16_t sm; 166 uint16_t stq; 167 uint8_t op; 168 uint8_t flag; 169 uint8_t cpu; 170 bool dump; 171 172 void serialize(std::ostream &os); 173 void unserialize(Checkpoint *cp, const std::string §ion); 174 175 }; 176 177 typedef RefCountingPtr<AnnotateData> AnnDataPtr; 178 179 /* header for the annotation file */ 180 struct AnnotateHeader { 181 uint64_t version; 182 uint64_t num_recs; 183 uint64_t key_off; 184 uint64_t idx_off; 185 uint32_t key_len; 186 uint32_t idx_len; 187 }; 188 189 AnnotateHeader ah; 190 191 std::vector<uint64_t> annotateIdx; 192 193 // number of state machines encountered in the simulation 194 int numSm; 195 // number of states encountered in the simulation 196 int numSmt; 197 // number of states/queues for a given state machine/system respectively 198 std::vector<int> numSt, numQ; 199 // number of systems in the simulation 200 int numSys; 201 // number of queues in the state machine 202 int numQs; 203 // maximum connection id assigned so far 204 uint64_t conId; 205 206 // Convert state strings into state ids 207 typedef m5::hash_map<std::string, int> SCache; 208 typedef std::vector<SCache> StCache; 209 210 // Convert sm and queue name,id into queue id 211 typedef std::pair<std::string, uint64_t> Id; 212 typedef m5::hash_map<Id, int> IdHCache; 213 typedef std::vector<IdHCache> IdCache; 214 215 // Hold mapping of sm and queues to output python 216 typedef std::vector<std::pair<int, Id> > IdMap; 217 218 // System pointer to name,id 219 typedef std::map<System*, std::pair<std::string, int> > NameCache; 220 221 // array of systems each of which is a stack of running sm 222 typedef std::pair<int, uint64_t> StackId; 223 typedef std::map<StackId, std::vector<int> > SmStack; 224 225 // map of each context and if it's currently in explict state mode 226 // states are not automatically updated until it leaves 227 typedef std::map<StackId, bool> SwExpl; 228 229 typedef std::map<int,int> IMap; 230 // List of annotate records have not been written/completed yet 231 typedef std::list<AnnDataPtr> AnnotateList; 232 233 // Maintain link state information 234 typedef std::map<int, int> LinkMap; 235 236 // SC Links 237 typedef m5::hash_map<Id, AnnDataPtr> ScHCache; 238 typedef std::vector<ScHCache> ScCache; 239 240 241 AnnotateList data; 242 243 // vector indexed by queueid to find current number of elements and bytes 244 std::vector<int> qSize; 245 std::vector<int32_t> qBytes; 246 247 248 // Turn state machine string into state machine id (small int) 249 // Used for outputting key to convert id back into string 250 SCache smtCache; 251 // Turn state machine id, state name into state id (small int) 252 StCache stCache; 253 // turn system, queue, and queue identify into qid (small int) 254 // turn system, state, and context into state machine id (small int) 255 IdCache qCache, smCache; 256 //Link state machines accross system calls 257 ScCache scLinks; 258 // System pointer to name,id 259 NameCache nameCache; 260 // Stack of state machines currently nested (should unwind correctly) 261 SmStack smStack; 262 // Map of currently outstanding links 263 LinkMap lnMap; 264 // If the state machine is currently exculding automatic changes 265 SwExpl swExpl; 266 // Last state that a given state machine was in 267 IMap lastState; 268 // Hold mapping of sm and queues to output python 269 IdMap smMap, qMap; 270 // Items still in queue, used for sanity checking 271 std::vector<AnnotateList> qData; 272 273 void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi, 274 int count); 275 void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi, 276 int count); 277 278 void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame); 279 280 // Turn a system id, state machine string, state machine id into a small int 281 // for annotation output 282 int 283 getSm(int sysi, std::string si, uint64_t id) 284 { 285 int smi; 286 Id smid = Id(si, id); 287 288 smi = smCache[sysi-1][smid]; 289 if (smi == 0) { 290 smCache[sysi-1][smid] = smi = ++numSm; 291 assert(smi < 65535); 292 smMap.push_back(std::make_pair<int, Id>(sysi, smid)); 293 } 294 return smi; 295 } 296 297 // Turn a state machine string, state string into a small int 298 // for annotation output 299 int 300 getSt(std::string sm, std::string s) 301 { 302 int sti, smi; 303 304 smi = smtCache[sm]; 305 if (smi == 0) 306 smi = smtCache[sm] = ++numSmt; 307 308 while (stCache.size() < smi) { 309 //stCache.resize(sm); 310 stCache.push_back(SCache()); 311 numSt.push_back(0); 312 } 313 //assert(stCache.size() == sm); 314 //assert(numSt.size() == sm); 315 sti = stCache[smi-1][s]; 316 if (sti == 0) 317 stCache[smi-1][s] = sti = ++numSt[smi-1]; 318 return sti; 319 } 320 321 // Turn state machine pointer into a smal int for annotation output 322 int 323 getSys(System *s) 324 { 325 NameCache::iterator i = nameCache.find(s); 326 if (i == nameCache.end()) { 327 nameCache[s] = std::make_pair<std::string,int>(s->name(), ++numSys); 328 i = nameCache.find(s); 329 // might need to put smstackid into map here, but perhaps not 330 //smStack.push_back(std::vector<int>()); 331 //swExpl.push_back(false); 332 numQ.push_back(0); 333 qCache.push_back(IdHCache()); 334 smCache.push_back(IdHCache()); 335 scLinks.push_back(ScHCache()); 336 } 337 return i->second.second; 338 } 339 340 // Turn queue name, and queue context into small int for 341 // annotation output 342 int 343 getQ(int sys, std::string q, uint64_t id) 344 { 345 int qi; 346 Id qid = Id(q, id); 347 348 qi = qCache[sys-1][qid]; 349 if (qi == 0) { 350 qi = qCache[sys-1][qid] = ++numQs; 351 assert(qi < 65535); 352 qSize.push_back(0); 353 qBytes.push_back(0); 354 qData.push_back(AnnotateList()); 355 numQ[sys-1]++; 356 qMap.push_back(std::make_pair<int, Id>(sys, qid)); 357 } 358 return qi; 359 } 360 361 void swBegin(System *sys, int cpuid, std::string st, uint64_t frame, 362 bool expl = false, int flags = FL_NONE); 363 364 AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0); 365 366 std::ostream *osbin; 367 368 bool _enabled; 369 370 /** Only allow one CPA object in a system. It doesn't make sense to have 371 * more that one per simulation because if a part of the system was 372 * important it would have annotations and queues, and with more than one 373 * object none of the sanity checking for queues will work. */ 374 static bool exists; 375 static CPA *_cpa; 376 377 378 std::map<std::string, SymbolTable*> userApp; 379 380 public: 381 static CPA *cpa() { return _cpa; } 382 void swSmBegin(ThreadContext *tc); 383 void swSmEnd(ThreadContext *tc); 384 void swExplictBegin(ThreadContext *tc); 385 void swAutoBegin(ThreadContext *tc, Addr next_pc); 386 void swEnd(ThreadContext *tc); 387 void swQ(ThreadContext *tc); 388 void swDq(ThreadContext *tc); 389 void swPq(ThreadContext *tc); 390 void swRq(ThreadContext *tc); 391 void swWf(ThreadContext *tc); 392 void swWe(ThreadContext *tc); 393 void swSq(ThreadContext *tc); 394 void swAq(ThreadContext *tc); 395 void swLink(ThreadContext *tc); 396 void swIdentify(ThreadContext *tc); 397 uint64_t swGetId(ThreadContext *tc); 398 void swSyscallLink(ThreadContext *tc); 399 400 inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm, 401 std::string st) 402 { 403 if (!enabled()) 404 return; 405 406 int sysi = getSys(sys); 407 int smi = getSm(sysi, sm, frame); 408 add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st)); 409 if (f & FL_BAD) 410 warn("BAD state encountered: at cycle %d: %s\n", curTick, st); 411 } 412 413 inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm, 414 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 415 { 416 if (!enabled()) 417 return; 418 419 int sysi = getSys(sys); 420 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 421 DPRINTFS(AnnotateQ, sys, 422 "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n", 423 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); 424 doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count); 425 426 } 427 428 inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm, 429 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 430 { 431 if (!enabled()) 432 return; 433 434 int sysi = getSys(sys); 435 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 436 DPRINTFS(AnnotateQ, sys, 437 "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n", 438 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); 439 doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count); 440 } 441 442 inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm, 443 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 444 { 445 if (!enabled()) 446 return; 447 448 int sysi = getSys(sys); 449 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 450 DPRINTFS(AnnotateQ, sys, 451 "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n", 452 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); 453 add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); 454 } 455 456 inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm, 457 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 458 { 459 if (!enabled()) 460 return; 461 462 int sysi = getSys(sys); 463 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 464 DPRINTFS(AnnotateQ, sys, 465 "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n", 466 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); 467 add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); 468 } 469 470 inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm, 471 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 472 { 473 if (!enabled()) 474 return; 475 476 int sysi = getSys(sys); 477 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 478 add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); 479 } 480 481 inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm, 482 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 483 { 484 if (!enabled()) 485 return; 486 487 int sysi = getSys(sys); 488 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 489 add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); 490 } 491 492 public: 493 CPA(Params *p); 494 void startup(); 495 496 // This code is ISA specific and will need to be changed 497 // if the annotation code is used for something other than Alpha 498 inline uint64_t getFrame(ThreadContext *tc) 499 { return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) & 500 ~ULL(0x3FFF)); } 501 502 static bool available() { return true; } 503 504 bool 505 enabled() 506 { 507 if (!this) 508 return false; 509 return _enabled; 510 } 511 512 void dump(bool all); 513 void dumpKey(); 514 515 void serialize(std::ostream &os); 516 void unserialize(Checkpoint *cp, const std::string §ion); 517 518}; 519#endif // !CP_ANNOTATE 520 521#endif //__BASE__CP_ANNOTATE_HH__ 522
| 48#if CP_ANNOTATE 49#include "params/CPA.hh" 50#endif 51 52class System; 53class ThreadContext; 54 55 56#if !CP_ANNOTATE 57class CPA 58{ 59 public: 60 enum flags { 61 FL_NONE = 0x00, 62 FL_HW = 0x01, 63 FL_BAD = 0x02, 64 FL_QOPP = 0x04, 65 FL_WAIT = 0x08, 66 FL_LINK = 0x10, 67 FL_RESET = 0x20 68 }; 69 70 static CPA *cpa() { return NULL; } 71 static bool available() { return false; } 72 bool enabled() { return false; } 73 void swSmBegin(ThreadContext *tc) { return; } 74 void swSmEnd(ThreadContext *tc) { return; } 75 void swExplictBegin(ThreadContext *tc) { return; } 76 void swAutoBegin(ThreadContext *tc, Addr next_pc) { return; } 77 void swEnd(ThreadContext *tc) { return; } 78 void swQ(ThreadContext *tc) { return; } 79 void swDq(ThreadContext *tc) { return; } 80 void swPq(ThreadContext *tc) { return; } 81 void swRq(ThreadContext *tc) { return; } 82 void swWf(ThreadContext *tc) { return; } 83 void swWe(ThreadContext *tc) { return; } 84 void swSq(ThreadContext *tc) { return; } 85 void swAq(ThreadContext *tc) { return; } 86 void swLink(ThreadContext *tc) { return; } 87 void swIdentify(ThreadContext *tc) { return; } 88 uint64_t swGetId(ThreadContext *tc) { return 0; } 89 void swSyscallLink(ThreadContext *tc) { return; } 90 void hwBegin(flags f, System *sys, uint64_t frame, std::string sm, 91 std::string st) { return; } 92 void hwQ(flags f, System *sys, uint64_t frame, std::string sm, 93 std::string q, uint64_t qid, System *q_sys = NULL, 94 int32_t count = 1) { return; } 95 void hwDq(flags f, System *sys, uint64_t frame, std::string sm, 96 std::string q, uint64_t qid, System *q_sys = NULL, 97 int32_t count = 1) { return; } 98 void hwPq(flags f, System *sys, uint64_t frame, std::string sm, 99 std::string q, uint64_t qid, System *q_sys = NULL, 100 int32_t count = 1) { return; } 101 void hwRq(flags f, System *sys, uint64_t frame, std::string sm, 102 std::string q, uint64_t qid, System *q_sys = NULL, 103 int32_t count = 1) { return; } 104 void hwWf(flags f, System *sys, uint64_t frame, std::string sm, 105 std::string q, uint64_t qid, System *q_sys = NULL, 106 int32_t count = 1) { return; } 107 void hwWe(flags f, System *sys, uint64_t frame, std::string sm, 108 std::string q, uint64_t qid, System *q_sys = NULL, 109 int32_t count = 1) { return; } 110}; 111#else 112class CPA : SimObject 113{ 114 public: 115 typedef CPAParams Params; 116 117 /** The known operations that are written to the annotation output file. */ 118 enum ops { 119 OP_BEGIN = 0x01, 120 OP_WAIT_EMPTY = 0x02, 121 OP_WAIT_FULL = 0x03, 122 OP_QUEUE = 0x04, 123 OP_DEQUEUE = 0x05, 124 OP_SIZE_QUEUE = 0x08, 125 OP_PEEK = 0x09, 126 OP_LINK = 0x0A, 127 OP_IDENT = 0x0B, 128 OP_RESERVE = 0x0C 129 }; 130 131 /** Flags for the various options.*/ 132 enum flags { 133 /* no flags */ 134 FL_NONE = 0x00, 135 /* operation was done on hardware */ 136 FL_HW = 0x01, 137 /* operation should cause a warning when encountered */ 138 FL_BAD = 0x02, 139 /* Queue like a stack, not a queue */ 140 FL_QOPP = 0x04, 141 /* Mark HW state as waiting for some non-resource constraint 142 * (e.g. wait because SM only starts after 10 items are queued) */ 143 FL_WAIT = 0x08, 144 /* operation is linking to another state machine */ 145 FL_LINK = 0x10, 146 /* queue should be completely cleared/reset before executing this 147 * operation */ 148 FL_RESET = 0x20 149 }; 150 151 152 153 protected: 154 const Params * 155 params() const 156 { 157 return dynamic_cast<const Params *>(_params); 158 } 159 160 /* struct that is written to the annotation output file */ 161 struct AnnotateData : public RefCounted { 162 163 Tick time; 164 uint32_t data; 165 uint32_t orig_data; 166 uint16_t sm; 167 uint16_t stq; 168 uint8_t op; 169 uint8_t flag; 170 uint8_t cpu; 171 bool dump; 172 173 void serialize(std::ostream &os); 174 void unserialize(Checkpoint *cp, const std::string §ion); 175 176 }; 177 178 typedef RefCountingPtr<AnnotateData> AnnDataPtr; 179 180 /* header for the annotation file */ 181 struct AnnotateHeader { 182 uint64_t version; 183 uint64_t num_recs; 184 uint64_t key_off; 185 uint64_t idx_off; 186 uint32_t key_len; 187 uint32_t idx_len; 188 }; 189 190 AnnotateHeader ah; 191 192 std::vector<uint64_t> annotateIdx; 193 194 // number of state machines encountered in the simulation 195 int numSm; 196 // number of states encountered in the simulation 197 int numSmt; 198 // number of states/queues for a given state machine/system respectively 199 std::vector<int> numSt, numQ; 200 // number of systems in the simulation 201 int numSys; 202 // number of queues in the state machine 203 int numQs; 204 // maximum connection id assigned so far 205 uint64_t conId; 206 207 // Convert state strings into state ids 208 typedef m5::hash_map<std::string, int> SCache; 209 typedef std::vector<SCache> StCache; 210 211 // Convert sm and queue name,id into queue id 212 typedef std::pair<std::string, uint64_t> Id; 213 typedef m5::hash_map<Id, int> IdHCache; 214 typedef std::vector<IdHCache> IdCache; 215 216 // Hold mapping of sm and queues to output python 217 typedef std::vector<std::pair<int, Id> > IdMap; 218 219 // System pointer to name,id 220 typedef std::map<System*, std::pair<std::string, int> > NameCache; 221 222 // array of systems each of which is a stack of running sm 223 typedef std::pair<int, uint64_t> StackId; 224 typedef std::map<StackId, std::vector<int> > SmStack; 225 226 // map of each context and if it's currently in explict state mode 227 // states are not automatically updated until it leaves 228 typedef std::map<StackId, bool> SwExpl; 229 230 typedef std::map<int,int> IMap; 231 // List of annotate records have not been written/completed yet 232 typedef std::list<AnnDataPtr> AnnotateList; 233 234 // Maintain link state information 235 typedef std::map<int, int> LinkMap; 236 237 // SC Links 238 typedef m5::hash_map<Id, AnnDataPtr> ScHCache; 239 typedef std::vector<ScHCache> ScCache; 240 241 242 AnnotateList data; 243 244 // vector indexed by queueid to find current number of elements and bytes 245 std::vector<int> qSize; 246 std::vector<int32_t> qBytes; 247 248 249 // Turn state machine string into state machine id (small int) 250 // Used for outputting key to convert id back into string 251 SCache smtCache; 252 // Turn state machine id, state name into state id (small int) 253 StCache stCache; 254 // turn system, queue, and queue identify into qid (small int) 255 // turn system, state, and context into state machine id (small int) 256 IdCache qCache, smCache; 257 //Link state machines accross system calls 258 ScCache scLinks; 259 // System pointer to name,id 260 NameCache nameCache; 261 // Stack of state machines currently nested (should unwind correctly) 262 SmStack smStack; 263 // Map of currently outstanding links 264 LinkMap lnMap; 265 // If the state machine is currently exculding automatic changes 266 SwExpl swExpl; 267 // Last state that a given state machine was in 268 IMap lastState; 269 // Hold mapping of sm and queues to output python 270 IdMap smMap, qMap; 271 // Items still in queue, used for sanity checking 272 std::vector<AnnotateList> qData; 273 274 void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi, 275 int count); 276 void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi, 277 int count); 278 279 void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame); 280 281 // Turn a system id, state machine string, state machine id into a small int 282 // for annotation output 283 int 284 getSm(int sysi, std::string si, uint64_t id) 285 { 286 int smi; 287 Id smid = Id(si, id); 288 289 smi = smCache[sysi-1][smid]; 290 if (smi == 0) { 291 smCache[sysi-1][smid] = smi = ++numSm; 292 assert(smi < 65535); 293 smMap.push_back(std::make_pair<int, Id>(sysi, smid)); 294 } 295 return smi; 296 } 297 298 // Turn a state machine string, state string into a small int 299 // for annotation output 300 int 301 getSt(std::string sm, std::string s) 302 { 303 int sti, smi; 304 305 smi = smtCache[sm]; 306 if (smi == 0) 307 smi = smtCache[sm] = ++numSmt; 308 309 while (stCache.size() < smi) { 310 //stCache.resize(sm); 311 stCache.push_back(SCache()); 312 numSt.push_back(0); 313 } 314 //assert(stCache.size() == sm); 315 //assert(numSt.size() == sm); 316 sti = stCache[smi-1][s]; 317 if (sti == 0) 318 stCache[smi-1][s] = sti = ++numSt[smi-1]; 319 return sti; 320 } 321 322 // Turn state machine pointer into a smal int for annotation output 323 int 324 getSys(System *s) 325 { 326 NameCache::iterator i = nameCache.find(s); 327 if (i == nameCache.end()) { 328 nameCache[s] = std::make_pair<std::string,int>(s->name(), ++numSys); 329 i = nameCache.find(s); 330 // might need to put smstackid into map here, but perhaps not 331 //smStack.push_back(std::vector<int>()); 332 //swExpl.push_back(false); 333 numQ.push_back(0); 334 qCache.push_back(IdHCache()); 335 smCache.push_back(IdHCache()); 336 scLinks.push_back(ScHCache()); 337 } 338 return i->second.second; 339 } 340 341 // Turn queue name, and queue context into small int for 342 // annotation output 343 int 344 getQ(int sys, std::string q, uint64_t id) 345 { 346 int qi; 347 Id qid = Id(q, id); 348 349 qi = qCache[sys-1][qid]; 350 if (qi == 0) { 351 qi = qCache[sys-1][qid] = ++numQs; 352 assert(qi < 65535); 353 qSize.push_back(0); 354 qBytes.push_back(0); 355 qData.push_back(AnnotateList()); 356 numQ[sys-1]++; 357 qMap.push_back(std::make_pair<int, Id>(sys, qid)); 358 } 359 return qi; 360 } 361 362 void swBegin(System *sys, int cpuid, std::string st, uint64_t frame, 363 bool expl = false, int flags = FL_NONE); 364 365 AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0); 366 367 std::ostream *osbin; 368 369 bool _enabled; 370 371 /** Only allow one CPA object in a system. It doesn't make sense to have 372 * more that one per simulation because if a part of the system was 373 * important it would have annotations and queues, and with more than one 374 * object none of the sanity checking for queues will work. */ 375 static bool exists; 376 static CPA *_cpa; 377 378 379 std::map<std::string, SymbolTable*> userApp; 380 381 public: 382 static CPA *cpa() { return _cpa; } 383 void swSmBegin(ThreadContext *tc); 384 void swSmEnd(ThreadContext *tc); 385 void swExplictBegin(ThreadContext *tc); 386 void swAutoBegin(ThreadContext *tc, Addr next_pc); 387 void swEnd(ThreadContext *tc); 388 void swQ(ThreadContext *tc); 389 void swDq(ThreadContext *tc); 390 void swPq(ThreadContext *tc); 391 void swRq(ThreadContext *tc); 392 void swWf(ThreadContext *tc); 393 void swWe(ThreadContext *tc); 394 void swSq(ThreadContext *tc); 395 void swAq(ThreadContext *tc); 396 void swLink(ThreadContext *tc); 397 void swIdentify(ThreadContext *tc); 398 uint64_t swGetId(ThreadContext *tc); 399 void swSyscallLink(ThreadContext *tc); 400 401 inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm, 402 std::string st) 403 { 404 if (!enabled()) 405 return; 406 407 int sysi = getSys(sys); 408 int smi = getSm(sysi, sm, frame); 409 add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st)); 410 if (f & FL_BAD) 411 warn("BAD state encountered: at cycle %d: %s\n", curTick, st); 412 } 413 414 inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm, 415 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 416 { 417 if (!enabled()) 418 return; 419 420 int sysi = getSys(sys); 421 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 422 DPRINTFS(AnnotateQ, sys, 423 "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n", 424 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); 425 doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count); 426 427 } 428 429 inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm, 430 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 431 { 432 if (!enabled()) 433 return; 434 435 int sysi = getSys(sys); 436 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 437 DPRINTFS(AnnotateQ, sys, 438 "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n", 439 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); 440 doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count); 441 } 442 443 inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm, 444 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 445 { 446 if (!enabled()) 447 return; 448 449 int sysi = getSys(sys); 450 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 451 DPRINTFS(AnnotateQ, sys, 452 "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n", 453 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); 454 add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); 455 } 456 457 inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm, 458 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 459 { 460 if (!enabled()) 461 return; 462 463 int sysi = getSys(sys); 464 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 465 DPRINTFS(AnnotateQ, sys, 466 "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n", 467 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count); 468 add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); 469 } 470 471 inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm, 472 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 473 { 474 if (!enabled()) 475 return; 476 477 int sysi = getSys(sys); 478 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 479 add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); 480 } 481 482 inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm, 483 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1) 484 { 485 if (!enabled()) 486 return; 487 488 int sysi = getSys(sys); 489 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid); 490 add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count); 491 } 492 493 public: 494 CPA(Params *p); 495 void startup(); 496 497 // This code is ISA specific and will need to be changed 498 // if the annotation code is used for something other than Alpha 499 inline uint64_t getFrame(ThreadContext *tc) 500 { return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) & 501 ~ULL(0x3FFF)); } 502 503 static bool available() { return true; } 504 505 bool 506 enabled() 507 { 508 if (!this) 509 return false; 510 return _enabled; 511 } 512 513 void dump(bool all); 514 void dumpKey(); 515 516 void serialize(std::ostream &os); 517 void unserialize(Checkpoint *cp, const std::string §ion); 518 519}; 520#endif // !CP_ANNOTATE 521 522#endif //__BASE__CP_ANNOTATE_HH__ 523
|