cp_annotate.hh (7492:acc1fbbef239) cp_annotate.hh (7823:dac01f14f20f)
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 <string>
35#include <list>
36#include <vector>
37#include <map>
38
39#include "base/hashmap.hh"
40#include "base/loader/symtab.hh"
41#include "base/trace.hh"
42#include "base/types.hh"
43#include "config/cp_annotate.hh"
44#include "config/the_isa.hh"
45#include "sim/serialize.hh"
46#include "sim/system.hh"
47
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 &section);
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)
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 <string>
35#include <list>
36#include <vector>
37#include <map>
38
39#include "base/hashmap.hh"
40#include "base/loader/symtab.hh"
41#include "base/trace.hh"
42#include "base/types.hh"
43#include "config/cp_annotate.hh"
44#include "config/the_isa.hh"
45#include "sim/serialize.hh"
46#include "sim/system.hh"
47
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 &section);
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);
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 &section);
518
519};
520#endif // !CP_ANNOTATE
521
522#endif //__BASE__CP_ANNOTATE_HH__
523
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 &section);
518
519};
520#endif // !CP_ANNOTATE
521
522#endif //__BASE__CP_ANNOTATE_HH__
523