cp_annotate.hh (10470:2c6a72e919f6) cp_annotate.hh (10905:a6ca6831e775)
1/*
2 * Copyright (c) 2014 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2006-2009 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Ali Saidi
41 */
42
43#ifndef __BASE__CP_ANNOTATE_HH__
44#define __BASE__CP_ANNOTATE_HH__
45
46#include <list>
47#include <map>
48#include <memory>
49#include <string>
50#include <vector>
51
52#include "base/loader/symtab.hh"
53#include "base/hashmap.hh"
54#include "base/trace.hh"
55#include "base/types.hh"
56#include "debug/AnnotateQ.hh"
57#include "config/cp_annotate.hh"
58#include "config/the_isa.hh"
59#include "sim/serialize.hh"
60#include "sim/system.hh"
61
62#if CP_ANNOTATE
63#include "params/CPA.hh"
64#endif
65
66class System;
67class ThreadContext;
68
69
70#if !CP_ANNOTATE
71class CPA
72{
73 public:
74 enum flags {
75 FL_NONE = 0x00,
76 FL_HW = 0x01,
77 FL_BAD = 0x02,
78 FL_QOPP = 0x04,
79 FL_WAIT = 0x08,
80 FL_LINK = 0x10,
81 FL_RESET = 0x20
82 };
83
84 static CPA *cpa() { return NULL; }
85 static bool available() { return false; }
86 bool enabled() { return false; }
87 void swSmBegin(ThreadContext *tc) { return; }
88 void swSmEnd(ThreadContext *tc) { return; }
89 void swExplictBegin(ThreadContext *tc) { return; }
90 void swAutoBegin(ThreadContext *tc, Addr next_pc) { return; }
91 void swEnd(ThreadContext *tc) { return; }
92 void swQ(ThreadContext *tc) { return; }
93 void swDq(ThreadContext *tc) { return; }
94 void swPq(ThreadContext *tc) { return; }
95 void swRq(ThreadContext *tc) { return; }
96 void swWf(ThreadContext *tc) { return; }
97 void swWe(ThreadContext *tc) { return; }
98 void swSq(ThreadContext *tc) { return; }
99 void swAq(ThreadContext *tc) { return; }
100 void swLink(ThreadContext *tc) { return; }
101 void swIdentify(ThreadContext *tc) { return; }
102 uint64_t swGetId(ThreadContext *tc) { return 0; }
103 void swSyscallLink(ThreadContext *tc) { return; }
104 void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
105 std::string st) { return; }
106 void hwQ(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 void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
110 std::string q, uint64_t qid, System *q_sys = NULL,
111 int32_t count = 1) { return; }
112 void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
113 std::string q, uint64_t qid, System *q_sys = NULL,
114 int32_t count = 1) { return; }
115 void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
116 std::string q, uint64_t qid, System *q_sys = NULL,
117 int32_t count = 1) { return; }
118 void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
119 std::string q, uint64_t qid, System *q_sys = NULL,
120 int32_t count = 1) { return; }
121 void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
122 std::string q, uint64_t qid, System *q_sys = NULL,
123 int32_t count = 1) { return; }
124};
125#else
126
127/**
128 * Provide a hash function for the CPI Id type
129 */
130__hash_namespace_begin
131template <>
132struct hash<std::pair<std::string, uint64_t> >
133{
134
135 size_t
136 operator()(const std::pair<std::string, uint64_t>& x) const
137 {
138 return hash<std::string>()(x.first);
139 }
140
141};
142__hash_namespace_end
143
144class CPA : SimObject
145{
146 public:
147 typedef CPAParams Params;
148
149 /** The known operations that are written to the annotation output file. */
150 enum ops {
151 OP_BEGIN = 0x01,
152 OP_WAIT_EMPTY = 0x02,
153 OP_WAIT_FULL = 0x03,
154 OP_QUEUE = 0x04,
155 OP_DEQUEUE = 0x05,
156 OP_SIZE_QUEUE = 0x08,
157 OP_PEEK = 0x09,
158 OP_LINK = 0x0A,
159 OP_IDENT = 0x0B,
160 OP_RESERVE = 0x0C
161 };
162
163 /** Flags for the various options.*/
164 enum flags {
165 /* no flags */
166 FL_NONE = 0x00,
167 /* operation was done on hardware */
168 FL_HW = 0x01,
169 /* operation should cause a warning when encountered */
170 FL_BAD = 0x02,
171 /* Queue like a stack, not a queue */
172 FL_QOPP = 0x04,
173 /* Mark HW state as waiting for some non-resource constraint
174 * (e.g. wait because SM only starts after 10 items are queued) */
175 FL_WAIT = 0x08,
176 /* operation is linking to another state machine */
177 FL_LINK = 0x10,
178 /* queue should be completely cleared/reset before executing this
179 * operation */
180 FL_RESET = 0x20
181 };
182
183
184
185 protected:
186 const Params *
187 params() const
188 {
189 return dynamic_cast<const Params *>(_params);
190 }
191
192 /* struct that is written to the annotation output file */
1/*
2 * Copyright (c) 2014 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2006-2009 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Ali Saidi
41 */
42
43#ifndef __BASE__CP_ANNOTATE_HH__
44#define __BASE__CP_ANNOTATE_HH__
45
46#include <list>
47#include <map>
48#include <memory>
49#include <string>
50#include <vector>
51
52#include "base/loader/symtab.hh"
53#include "base/hashmap.hh"
54#include "base/trace.hh"
55#include "base/types.hh"
56#include "debug/AnnotateQ.hh"
57#include "config/cp_annotate.hh"
58#include "config/the_isa.hh"
59#include "sim/serialize.hh"
60#include "sim/system.hh"
61
62#if CP_ANNOTATE
63#include "params/CPA.hh"
64#endif
65
66class System;
67class ThreadContext;
68
69
70#if !CP_ANNOTATE
71class CPA
72{
73 public:
74 enum flags {
75 FL_NONE = 0x00,
76 FL_HW = 0x01,
77 FL_BAD = 0x02,
78 FL_QOPP = 0x04,
79 FL_WAIT = 0x08,
80 FL_LINK = 0x10,
81 FL_RESET = 0x20
82 };
83
84 static CPA *cpa() { return NULL; }
85 static bool available() { return false; }
86 bool enabled() { return false; }
87 void swSmBegin(ThreadContext *tc) { return; }
88 void swSmEnd(ThreadContext *tc) { return; }
89 void swExplictBegin(ThreadContext *tc) { return; }
90 void swAutoBegin(ThreadContext *tc, Addr next_pc) { return; }
91 void swEnd(ThreadContext *tc) { return; }
92 void swQ(ThreadContext *tc) { return; }
93 void swDq(ThreadContext *tc) { return; }
94 void swPq(ThreadContext *tc) { return; }
95 void swRq(ThreadContext *tc) { return; }
96 void swWf(ThreadContext *tc) { return; }
97 void swWe(ThreadContext *tc) { return; }
98 void swSq(ThreadContext *tc) { return; }
99 void swAq(ThreadContext *tc) { return; }
100 void swLink(ThreadContext *tc) { return; }
101 void swIdentify(ThreadContext *tc) { return; }
102 uint64_t swGetId(ThreadContext *tc) { return 0; }
103 void swSyscallLink(ThreadContext *tc) { return; }
104 void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
105 std::string st) { return; }
106 void hwQ(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 void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
110 std::string q, uint64_t qid, System *q_sys = NULL,
111 int32_t count = 1) { return; }
112 void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
113 std::string q, uint64_t qid, System *q_sys = NULL,
114 int32_t count = 1) { return; }
115 void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
116 std::string q, uint64_t qid, System *q_sys = NULL,
117 int32_t count = 1) { return; }
118 void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
119 std::string q, uint64_t qid, System *q_sys = NULL,
120 int32_t count = 1) { return; }
121 void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
122 std::string q, uint64_t qid, System *q_sys = NULL,
123 int32_t count = 1) { return; }
124};
125#else
126
127/**
128 * Provide a hash function for the CPI Id type
129 */
130__hash_namespace_begin
131template <>
132struct hash<std::pair<std::string, uint64_t> >
133{
134
135 size_t
136 operator()(const std::pair<std::string, uint64_t>& x) const
137 {
138 return hash<std::string>()(x.first);
139 }
140
141};
142__hash_namespace_end
143
144class CPA : SimObject
145{
146 public:
147 typedef CPAParams Params;
148
149 /** The known operations that are written to the annotation output file. */
150 enum ops {
151 OP_BEGIN = 0x01,
152 OP_WAIT_EMPTY = 0x02,
153 OP_WAIT_FULL = 0x03,
154 OP_QUEUE = 0x04,
155 OP_DEQUEUE = 0x05,
156 OP_SIZE_QUEUE = 0x08,
157 OP_PEEK = 0x09,
158 OP_LINK = 0x0A,
159 OP_IDENT = 0x0B,
160 OP_RESERVE = 0x0C
161 };
162
163 /** Flags for the various options.*/
164 enum flags {
165 /* no flags */
166 FL_NONE = 0x00,
167 /* operation was done on hardware */
168 FL_HW = 0x01,
169 /* operation should cause a warning when encountered */
170 FL_BAD = 0x02,
171 /* Queue like a stack, not a queue */
172 FL_QOPP = 0x04,
173 /* Mark HW state as waiting for some non-resource constraint
174 * (e.g. wait because SM only starts after 10 items are queued) */
175 FL_WAIT = 0x08,
176 /* operation is linking to another state machine */
177 FL_LINK = 0x10,
178 /* queue should be completely cleared/reset before executing this
179 * operation */
180 FL_RESET = 0x20
181 };
182
183
184
185 protected:
186 const Params *
187 params() const
188 {
189 return dynamic_cast<const Params *>(_params);
190 }
191
192 /* struct that is written to the annotation output file */
193 struct AnnotateData {
193 struct AnnotateData : public Serializable {
194
195 Tick time;
196 uint32_t data;
197 uint32_t orig_data;
198 uint16_t sm;
199 uint16_t stq;
200 uint8_t op;
201 uint8_t flag;
202 uint8_t cpu;
203 bool dump;
204
194
195 Tick time;
196 uint32_t data;
197 uint32_t orig_data;
198 uint16_t sm;
199 uint16_t stq;
200 uint8_t op;
201 uint8_t flag;
202 uint8_t cpu;
203 bool dump;
204
205 void serialize(std::ostream &os);
206 void unserialize(Checkpoint *cp, const std::string &section);
207
205 void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
206 void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
208 };
209
210 typedef std::shared_ptr<AnnotateData> AnnDataPtr;
211
212 /* header for the annotation file */
213 struct AnnotateHeader {
214 uint64_t version;
215 uint64_t num_recs;
216 uint64_t key_off;
217 uint64_t idx_off;
218 uint32_t key_len;
219 uint32_t idx_len;
220 };
221
222 AnnotateHeader ah;
223
224 std::vector<uint64_t> annotateIdx;
225
226 // number of state machines encountered in the simulation
227 int numSm;
228 // number of states encountered in the simulation
229 int numSmt;
230 // number of states/queues for a given state machine/system respectively
231 std::vector<int> numSt, numQ;
232 // number of systems in the simulation
233 int numSys;
234 // number of queues in the state machine
235 int numQs;
236 // maximum connection id assigned so far
237 uint64_t conId;
238
239 // Convert state strings into state ids
240 typedef m5::hash_map<std::string, int> SCache;
241 typedef std::vector<SCache> StCache;
242
243 // Convert sm and queue name,id into queue id
244 typedef std::pair<std::string, uint64_t> Id;
245 typedef m5::hash_map<Id, int> IdHCache;
246 typedef std::vector<IdHCache> IdCache;
247
248 // Hold mapping of sm and queues to output python
249 typedef std::vector<std::pair<int, Id> > IdMap;
250
251 // System pointer to name,id
252 typedef std::map<System*, std::pair<std::string, int> > NameCache;
253
254 // array of systems each of which is a stack of running sm
255 typedef std::pair<int, uint64_t> StackId;
256 typedef std::map<StackId, std::vector<int> > SmStack;
257
258 // map of each context and if it's currently in explict state mode
259 // states are not automatically updated until it leaves
260 typedef std::map<StackId, bool> SwExpl;
261
262 typedef std::map<int,int> IMap;
263 // List of annotate records have not been written/completed yet
264 typedef std::list<AnnDataPtr> AnnotateList;
265
266 // Maintain link state information
267 typedef std::map<int, int> LinkMap;
268
269 // SC Links
270 typedef m5::hash_map<Id, AnnDataPtr> ScHCache;
271 typedef std::vector<ScHCache> ScCache;
272
273
274 AnnotateList data;
275
276 // vector indexed by queueid to find current number of elements and bytes
277 std::vector<int> qSize;
278 std::vector<int32_t> qBytes;
279
280
281 // Turn state machine string into state machine id (small int)
282 // Used for outputting key to convert id back into string
283 SCache smtCache;
284 // Turn state machine id, state name into state id (small int)
285 StCache stCache;
286 // turn system, queue, and queue identify into qid (small int)
287 // turn system, state, and context into state machine id (small int)
288 IdCache qCache, smCache;
289 //Link state machines accross system calls
290 ScCache scLinks;
291 // System pointer to name,id
292 NameCache nameCache;
293 // Stack of state machines currently nested (should unwind correctly)
294 SmStack smStack;
295 // Map of currently outstanding links
296 LinkMap lnMap;
297 // If the state machine is currently exculding automatic changes
298 SwExpl swExpl;
299 // Last state that a given state machine was in
300 IMap lastState;
301 // Hold mapping of sm and queues to output python
302 IdMap smMap, qMap;
303 // Items still in queue, used for sanity checking
304 std::vector<AnnotateList> qData;
305
306 void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi,
307 int count);
308 void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi,
309 int count);
310
311 void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame);
312
313 // Turn a system id, state machine string, state machine id into a small int
314 // for annotation output
315 int
316 getSm(int sysi, std::string si, uint64_t id)
317 {
318 int smi;
319 Id smid = Id(si, id);
320
321 smi = smCache[sysi-1][smid];
322 if (smi == 0) {
323 smCache[sysi-1][smid] = smi = ++numSm;
324 assert(smi < 65535);
325 smMap.push_back(std::make_pair(sysi, smid));
326 }
327 return smi;
328 }
329
330 // Turn a state machine string, state string into a small int
331 // for annotation output
332 int
333 getSt(std::string sm, std::string s)
334 {
335 int sti, smi;
336
337 smi = smtCache[sm];
338 if (smi == 0)
339 smi = smtCache[sm] = ++numSmt;
340
341 while (stCache.size() < smi) {
342 //stCache.resize(sm);
343 stCache.push_back(SCache());
344 numSt.push_back(0);
345 }
346 //assert(stCache.size() == sm);
347 //assert(numSt.size() == sm);
348 sti = stCache[smi-1][s];
349 if (sti == 0)
350 stCache[smi-1][s] = sti = ++numSt[smi-1];
351 return sti;
352 }
353
354 // Turn state machine pointer into a smal int for annotation output
355 int
356 getSys(System *s)
357 {
358 NameCache::iterator i = nameCache.find(s);
359 if (i == nameCache.end()) {
360 nameCache[s] = std::make_pair(s->name(), ++numSys);
361 i = nameCache.find(s);
362 // might need to put smstackid into map here, but perhaps not
363 //smStack.push_back(std::vector<int>());
364 //swExpl.push_back(false);
365 numQ.push_back(0);
366 qCache.push_back(IdHCache());
367 smCache.push_back(IdHCache());
368 scLinks.push_back(ScHCache());
369 }
370 return i->second.second;
371 }
372
373 // Turn queue name, and queue context into small int for
374 // annotation output
375 int
376 getQ(int sys, std::string q, uint64_t id)
377 {
378 int qi;
379 Id qid = Id(q, id);
380
381 qi = qCache[sys-1][qid];
382 if (qi == 0) {
383 qi = qCache[sys-1][qid] = ++numQs;
384 assert(qi < 65535);
385 qSize.push_back(0);
386 qBytes.push_back(0);
387 qData.push_back(AnnotateList());
388 numQ[sys-1]++;
389 qMap.push_back(std::make_pair(sys, qid));
390 }
391 return qi;
392 }
393
394 void swBegin(System *sys, int cpuid, std::string st, uint64_t frame,
395 bool expl = false, int flags = FL_NONE);
396
397 AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0);
398
399 std::ostream *osbin;
400
401 bool _enabled;
402
403 /** Only allow one CPA object in a system. It doesn't make sense to have
404 * more that one per simulation because if a part of the system was
405 * important it would have annotations and queues, and with more than one
406 * object none of the sanity checking for queues will work. */
407 static bool exists;
408 static CPA *_cpa;
409
410
411 std::map<std::string, SymbolTable*> userApp;
412
413 public:
414 static CPA *cpa() { return _cpa; }
415 void swSmBegin(ThreadContext *tc);
416 void swSmEnd(ThreadContext *tc);
417 void swExplictBegin(ThreadContext *tc);
418 void swAutoBegin(ThreadContext *tc, Addr next_pc);
419 void swEnd(ThreadContext *tc);
420 void swQ(ThreadContext *tc);
421 void swDq(ThreadContext *tc);
422 void swPq(ThreadContext *tc);
423 void swRq(ThreadContext *tc);
424 void swWf(ThreadContext *tc);
425 void swWe(ThreadContext *tc);
426 void swSq(ThreadContext *tc);
427 void swAq(ThreadContext *tc);
428 void swLink(ThreadContext *tc);
429 void swIdentify(ThreadContext *tc);
430 uint64_t swGetId(ThreadContext *tc);
431 void swSyscallLink(ThreadContext *tc);
432
433 inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
434 std::string st)
435 {
436 if (!enabled())
437 return;
438
439 int sysi = getSys(sys);
440 int smi = getSm(sysi, sm, frame);
441 add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st));
442 if (f & FL_BAD)
443 warn("BAD state encountered: at cycle %d: %s\n", curTick(), st);
444 }
445
446 inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
447 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
448 {
449 if (!enabled())
450 return;
451
452 int sysi = getSys(sys);
453 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
454 DPRINTFS(AnnotateQ, sys,
455 "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
456 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
457 doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count);
458
459 }
460
461 inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
462 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
463 {
464 if (!enabled())
465 return;
466
467 int sysi = getSys(sys);
468 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
469 DPRINTFS(AnnotateQ, sys,
470 "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
471 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
472 doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count);
473 }
474
475 inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
476 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
477 {
478 if (!enabled())
479 return;
480
481 int sysi = getSys(sys);
482 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
483 DPRINTFS(AnnotateQ, sys,
484 "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n",
485 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
486 add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
487 }
488
489 inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
490 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
491 {
492 if (!enabled())
493 return;
494
495 int sysi = getSys(sys);
496 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
497 DPRINTFS(AnnotateQ, sys,
498 "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n",
499 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
500 add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
501 }
502
503 inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
504 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
505 {
506 if (!enabled())
507 return;
508
509 int sysi = getSys(sys);
510 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
511 add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
512 }
513
514 inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
515 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
516 {
517 if (!enabled())
518 return;
519
520 int sysi = getSys(sys);
521 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
522 add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
523 }
524
525 public:
526 CPA(Params *p);
527 void startup();
528
529 uint64_t getFrame(ThreadContext *tc);
530
531 static bool available() { return true; }
532
533 bool
534 enabled()
535 {
536 if (!this)
537 return false;
538 return _enabled;
539 }
540
541 void dump(bool all);
542 void dumpKey();
543
207 };
208
209 typedef std::shared_ptr<AnnotateData> AnnDataPtr;
210
211 /* header for the annotation file */
212 struct AnnotateHeader {
213 uint64_t version;
214 uint64_t num_recs;
215 uint64_t key_off;
216 uint64_t idx_off;
217 uint32_t key_len;
218 uint32_t idx_len;
219 };
220
221 AnnotateHeader ah;
222
223 std::vector<uint64_t> annotateIdx;
224
225 // number of state machines encountered in the simulation
226 int numSm;
227 // number of states encountered in the simulation
228 int numSmt;
229 // number of states/queues for a given state machine/system respectively
230 std::vector<int> numSt, numQ;
231 // number of systems in the simulation
232 int numSys;
233 // number of queues in the state machine
234 int numQs;
235 // maximum connection id assigned so far
236 uint64_t conId;
237
238 // Convert state strings into state ids
239 typedef m5::hash_map<std::string, int> SCache;
240 typedef std::vector<SCache> StCache;
241
242 // Convert sm and queue name,id into queue id
243 typedef std::pair<std::string, uint64_t> Id;
244 typedef m5::hash_map<Id, int> IdHCache;
245 typedef std::vector<IdHCache> IdCache;
246
247 // Hold mapping of sm and queues to output python
248 typedef std::vector<std::pair<int, Id> > IdMap;
249
250 // System pointer to name,id
251 typedef std::map<System*, std::pair<std::string, int> > NameCache;
252
253 // array of systems each of which is a stack of running sm
254 typedef std::pair<int, uint64_t> StackId;
255 typedef std::map<StackId, std::vector<int> > SmStack;
256
257 // map of each context and if it's currently in explict state mode
258 // states are not automatically updated until it leaves
259 typedef std::map<StackId, bool> SwExpl;
260
261 typedef std::map<int,int> IMap;
262 // List of annotate records have not been written/completed yet
263 typedef std::list<AnnDataPtr> AnnotateList;
264
265 // Maintain link state information
266 typedef std::map<int, int> LinkMap;
267
268 // SC Links
269 typedef m5::hash_map<Id, AnnDataPtr> ScHCache;
270 typedef std::vector<ScHCache> ScCache;
271
272
273 AnnotateList data;
274
275 // vector indexed by queueid to find current number of elements and bytes
276 std::vector<int> qSize;
277 std::vector<int32_t> qBytes;
278
279
280 // Turn state machine string into state machine id (small int)
281 // Used for outputting key to convert id back into string
282 SCache smtCache;
283 // Turn state machine id, state name into state id (small int)
284 StCache stCache;
285 // turn system, queue, and queue identify into qid (small int)
286 // turn system, state, and context into state machine id (small int)
287 IdCache qCache, smCache;
288 //Link state machines accross system calls
289 ScCache scLinks;
290 // System pointer to name,id
291 NameCache nameCache;
292 // Stack of state machines currently nested (should unwind correctly)
293 SmStack smStack;
294 // Map of currently outstanding links
295 LinkMap lnMap;
296 // If the state machine is currently exculding automatic changes
297 SwExpl swExpl;
298 // Last state that a given state machine was in
299 IMap lastState;
300 // Hold mapping of sm and queues to output python
301 IdMap smMap, qMap;
302 // Items still in queue, used for sanity checking
303 std::vector<AnnotateList> qData;
304
305 void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi,
306 int count);
307 void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi,
308 int count);
309
310 void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame);
311
312 // Turn a system id, state machine string, state machine id into a small int
313 // for annotation output
314 int
315 getSm(int sysi, std::string si, uint64_t id)
316 {
317 int smi;
318 Id smid = Id(si, id);
319
320 smi = smCache[sysi-1][smid];
321 if (smi == 0) {
322 smCache[sysi-1][smid] = smi = ++numSm;
323 assert(smi < 65535);
324 smMap.push_back(std::make_pair(sysi, smid));
325 }
326 return smi;
327 }
328
329 // Turn a state machine string, state string into a small int
330 // for annotation output
331 int
332 getSt(std::string sm, std::string s)
333 {
334 int sti, smi;
335
336 smi = smtCache[sm];
337 if (smi == 0)
338 smi = smtCache[sm] = ++numSmt;
339
340 while (stCache.size() < smi) {
341 //stCache.resize(sm);
342 stCache.push_back(SCache());
343 numSt.push_back(0);
344 }
345 //assert(stCache.size() == sm);
346 //assert(numSt.size() == sm);
347 sti = stCache[smi-1][s];
348 if (sti == 0)
349 stCache[smi-1][s] = sti = ++numSt[smi-1];
350 return sti;
351 }
352
353 // Turn state machine pointer into a smal int for annotation output
354 int
355 getSys(System *s)
356 {
357 NameCache::iterator i = nameCache.find(s);
358 if (i == nameCache.end()) {
359 nameCache[s] = std::make_pair(s->name(), ++numSys);
360 i = nameCache.find(s);
361 // might need to put smstackid into map here, but perhaps not
362 //smStack.push_back(std::vector<int>());
363 //swExpl.push_back(false);
364 numQ.push_back(0);
365 qCache.push_back(IdHCache());
366 smCache.push_back(IdHCache());
367 scLinks.push_back(ScHCache());
368 }
369 return i->second.second;
370 }
371
372 // Turn queue name, and queue context into small int for
373 // annotation output
374 int
375 getQ(int sys, std::string q, uint64_t id)
376 {
377 int qi;
378 Id qid = Id(q, id);
379
380 qi = qCache[sys-1][qid];
381 if (qi == 0) {
382 qi = qCache[sys-1][qid] = ++numQs;
383 assert(qi < 65535);
384 qSize.push_back(0);
385 qBytes.push_back(0);
386 qData.push_back(AnnotateList());
387 numQ[sys-1]++;
388 qMap.push_back(std::make_pair(sys, qid));
389 }
390 return qi;
391 }
392
393 void swBegin(System *sys, int cpuid, std::string st, uint64_t frame,
394 bool expl = false, int flags = FL_NONE);
395
396 AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0);
397
398 std::ostream *osbin;
399
400 bool _enabled;
401
402 /** Only allow one CPA object in a system. It doesn't make sense to have
403 * more that one per simulation because if a part of the system was
404 * important it would have annotations and queues, and with more than one
405 * object none of the sanity checking for queues will work. */
406 static bool exists;
407 static CPA *_cpa;
408
409
410 std::map<std::string, SymbolTable*> userApp;
411
412 public:
413 static CPA *cpa() { return _cpa; }
414 void swSmBegin(ThreadContext *tc);
415 void swSmEnd(ThreadContext *tc);
416 void swExplictBegin(ThreadContext *tc);
417 void swAutoBegin(ThreadContext *tc, Addr next_pc);
418 void swEnd(ThreadContext *tc);
419 void swQ(ThreadContext *tc);
420 void swDq(ThreadContext *tc);
421 void swPq(ThreadContext *tc);
422 void swRq(ThreadContext *tc);
423 void swWf(ThreadContext *tc);
424 void swWe(ThreadContext *tc);
425 void swSq(ThreadContext *tc);
426 void swAq(ThreadContext *tc);
427 void swLink(ThreadContext *tc);
428 void swIdentify(ThreadContext *tc);
429 uint64_t swGetId(ThreadContext *tc);
430 void swSyscallLink(ThreadContext *tc);
431
432 inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
433 std::string st)
434 {
435 if (!enabled())
436 return;
437
438 int sysi = getSys(sys);
439 int smi = getSm(sysi, sm, frame);
440 add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st));
441 if (f & FL_BAD)
442 warn("BAD state encountered: at cycle %d: %s\n", curTick(), st);
443 }
444
445 inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
446 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
447 {
448 if (!enabled())
449 return;
450
451 int sysi = getSys(sys);
452 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
453 DPRINTFS(AnnotateQ, sys,
454 "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
455 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
456 doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count);
457
458 }
459
460 inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
461 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
462 {
463 if (!enabled())
464 return;
465
466 int sysi = getSys(sys);
467 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
468 DPRINTFS(AnnotateQ, sys,
469 "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
470 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
471 doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count);
472 }
473
474 inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
475 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
476 {
477 if (!enabled())
478 return;
479
480 int sysi = getSys(sys);
481 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
482 DPRINTFS(AnnotateQ, sys,
483 "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n",
484 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
485 add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
486 }
487
488 inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
489 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
490 {
491 if (!enabled())
492 return;
493
494 int sysi = getSys(sys);
495 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
496 DPRINTFS(AnnotateQ, sys,
497 "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n",
498 q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
499 add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
500 }
501
502 inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
503 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
504 {
505 if (!enabled())
506 return;
507
508 int sysi = getSys(sys);
509 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
510 add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
511 }
512
513 inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
514 std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
515 {
516 if (!enabled())
517 return;
518
519 int sysi = getSys(sys);
520 int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
521 add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
522 }
523
524 public:
525 CPA(Params *p);
526 void startup();
527
528 uint64_t getFrame(ThreadContext *tc);
529
530 static bool available() { return true; }
531
532 bool
533 enabled()
534 {
535 if (!this)
536 return false;
537 return _enabled;
538 }
539
540 void dump(bool all);
541 void dumpKey();
542
544 void serialize(std::ostream &os);
545 void unserialize(Checkpoint *cp, const std::string &section);
546
543 void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
544 void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
547};
548#endif // !CP_ANNOTATE
549
550#endif //__BASE__CP_ANNOTATE_HH__
551
545};
546#endif // !CP_ANNOTATE
547
548#endif //__BASE__CP_ANNOTATE_HH__
549