cp_annotate.hh (6002:7d75f1a525db) cp_annotate.hh (6214:1ec0ec8933ae)
1/*
2 * Copyright (c) 2006-2009 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31#ifndef __BASE__CP_ANNOTATE_HH__
32#define __BASE__CP_ANNOTATE_HH__
33
34#include "base/loader/symtab.hh"
35#include "config/cp_annotate.hh"
1/*
2 * Copyright (c) 2006-2009 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31#ifndef __BASE__CP_ANNOTATE_HH__
32#define __BASE__CP_ANNOTATE_HH__
33
34#include "base/loader/symtab.hh"
35#include "config/cp_annotate.hh"
36#include "sim/host.hh"
36#include "base/types.hh"
37#include "sim/serialize.hh"
38#include "sim/startup.hh"
39#include "sim/system.hh"
40
41#include <string>
42#include <list>
43#include <vector>
44#include <map>
45#include "base/hashmap.hh"
46#include "base/trace.hh"
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 &section);
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 &section);
517
518};
519#endif // !CP_ANNOTATE
520
521#endif //__BASE__CP_ANNOTATE_HH__
522
37#include "sim/serialize.hh"
38#include "sim/startup.hh"
39#include "sim/system.hh"
40
41#include <string>
42#include <list>
43#include <vector>
44#include <map>
45#include "base/hashmap.hh"
46#include "base/trace.hh"
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 &section);
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 &section);
517
518};
519#endif // !CP_ANNOTATE
520
521#endif //__BASE__CP_ANNOTATE_HH__
522