system.hh (9645:c483700ae0ce) system.hh (9814:7ad2b0186a32)
1/*
2 * Copyright (c) 2012 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) 2002-2005 The Regents of The University of Michigan
15 * Copyright (c) 2011 Regents of the University of California
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Steve Reinhardt
42 * Lisa Hsu
43 * Nathan Binkert
44 * Rick Strong
45 */
46
47#ifndef __SYSTEM_HH__
48#define __SYSTEM_HH__
49
50#include <string>
51#include <utility>
52#include <vector>
53
54#include "base/loader/symtab.hh"
55#include "base/misc.hh"
56#include "base/statistics.hh"
57#include "cpu/pc_event.hh"
58#include "enums/MemoryMode.hh"
59#include "kern/system_events.hh"
60#include "mem/fs_translating_port_proxy.hh"
61#include "mem/mem_object.hh"
62#include "mem/port.hh"
63#include "mem/physical.hh"
64#include "params/System.hh"
65
66class BaseCPU;
67class BaseRemoteGDB;
68class GDBListener;
69class ObjectFile;
70class Platform;
71class ThreadContext;
72
73class System : public MemObject
74{
75 private:
76
77 /**
78 * Private class for the system port which is only used as a
79 * master for debug access and for non-structural entities that do
80 * not have a port of their own.
81 */
82 class SystemPort : public MasterPort
83 {
84 public:
85
86 /**
87 * Create a system port with a name and an owner.
88 */
89 SystemPort(const std::string &_name, MemObject *_owner)
90 : MasterPort(_name, _owner)
91 { }
92 bool recvTimingResp(PacketPtr pkt)
93 { panic("SystemPort does not receive timing!\n"); return false; }
94 void recvRetry()
95 { panic("SystemPort does not expect retry!\n"); }
96 };
97
98 SystemPort _systemPort;
99
100 public:
101
102 /**
103 * After all objects have been created and all ports are
104 * connected, check that the system port is connected.
105 */
106 virtual void init();
107
108 /**
109 * Get a reference to the system port that can be used by
110 * non-structural simulation objects like processes or threads, or
111 * external entities like loaders and debuggers, etc, to access
112 * the memory system.
113 *
114 * @return a reference to the system port we own
115 */
116 MasterPort& getSystemPort() { return _systemPort; }
117
118 /**
119 * Additional function to return the Port of a memory object.
120 */
121 BaseMasterPort& getMasterPort(const std::string &if_name,
122 PortID idx = InvalidPortID);
123
124 static const char *MemoryModeStrings[4];
125
126 /** @{ */
127 /**
128 * Is the system in atomic mode?
129 *
130 * There are currently two different atomic memory modes:
131 * 'atomic', which supports caches; and 'atomic_noncaching', which
132 * bypasses caches. The latter is used by hardware virtualized
133 * CPUs. SimObjects are expected to use Port::sendAtomic() and
134 * Port::recvAtomic() when accessing memory in this mode.
135 */
136 bool isAtomicMode() const {
137 return memoryMode == Enums::atomic ||
138 memoryMode == Enums::atomic_noncaching;
139 }
140
141 /**
142 * Is the system in timing mode?
143 *
144 * SimObjects are expected to use Port::sendTiming() and
145 * Port::recvTiming() when accessing memory in this mode.
146 */
147 bool isTimingMode() const {
148 return memoryMode == Enums::timing;
149 }
150
151 /**
152 * Should caches be bypassed?
153 *
154 * Some CPUs need to bypass caches to allow direct memory
155 * accesses, which is required for hardware virtualization.
156 */
157 bool bypassCaches() const {
158 return memoryMode == Enums::atomic_noncaching;
159 }
160 /** @} */
161
162 /** @{ */
163 /**
164 * Get the memory mode of the system.
165 *
166 * \warn This should only be used by the Python world. The C++
167 * world should use one of the query functions above
168 * (isAtomicMode(), isTimingMode(), bypassCaches()).
169 */
170 Enums::MemoryMode getMemoryMode() const { return memoryMode; }
171
172 /**
173 * Change the memory mode of the system.
174 *
175 * \warn This should only be called by the Python!
176 *
177 * @param mode Mode to change to (atomic/timing/...)
178 */
179 void setMemoryMode(Enums::MemoryMode mode);
180 /** @} */
181
1/*
2 * Copyright (c) 2012 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) 2002-2005 The Regents of The University of Michigan
15 * Copyright (c) 2011 Regents of the University of California
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Steve Reinhardt
42 * Lisa Hsu
43 * Nathan Binkert
44 * Rick Strong
45 */
46
47#ifndef __SYSTEM_HH__
48#define __SYSTEM_HH__
49
50#include <string>
51#include <utility>
52#include <vector>
53
54#include "base/loader/symtab.hh"
55#include "base/misc.hh"
56#include "base/statistics.hh"
57#include "cpu/pc_event.hh"
58#include "enums/MemoryMode.hh"
59#include "kern/system_events.hh"
60#include "mem/fs_translating_port_proxy.hh"
61#include "mem/mem_object.hh"
62#include "mem/port.hh"
63#include "mem/physical.hh"
64#include "params/System.hh"
65
66class BaseCPU;
67class BaseRemoteGDB;
68class GDBListener;
69class ObjectFile;
70class Platform;
71class ThreadContext;
72
73class System : public MemObject
74{
75 private:
76
77 /**
78 * Private class for the system port which is only used as a
79 * master for debug access and for non-structural entities that do
80 * not have a port of their own.
81 */
82 class SystemPort : public MasterPort
83 {
84 public:
85
86 /**
87 * Create a system port with a name and an owner.
88 */
89 SystemPort(const std::string &_name, MemObject *_owner)
90 : MasterPort(_name, _owner)
91 { }
92 bool recvTimingResp(PacketPtr pkt)
93 { panic("SystemPort does not receive timing!\n"); return false; }
94 void recvRetry()
95 { panic("SystemPort does not expect retry!\n"); }
96 };
97
98 SystemPort _systemPort;
99
100 public:
101
102 /**
103 * After all objects have been created and all ports are
104 * connected, check that the system port is connected.
105 */
106 virtual void init();
107
108 /**
109 * Get a reference to the system port that can be used by
110 * non-structural simulation objects like processes or threads, or
111 * external entities like loaders and debuggers, etc, to access
112 * the memory system.
113 *
114 * @return a reference to the system port we own
115 */
116 MasterPort& getSystemPort() { return _systemPort; }
117
118 /**
119 * Additional function to return the Port of a memory object.
120 */
121 BaseMasterPort& getMasterPort(const std::string &if_name,
122 PortID idx = InvalidPortID);
123
124 static const char *MemoryModeStrings[4];
125
126 /** @{ */
127 /**
128 * Is the system in atomic mode?
129 *
130 * There are currently two different atomic memory modes:
131 * 'atomic', which supports caches; and 'atomic_noncaching', which
132 * bypasses caches. The latter is used by hardware virtualized
133 * CPUs. SimObjects are expected to use Port::sendAtomic() and
134 * Port::recvAtomic() when accessing memory in this mode.
135 */
136 bool isAtomicMode() const {
137 return memoryMode == Enums::atomic ||
138 memoryMode == Enums::atomic_noncaching;
139 }
140
141 /**
142 * Is the system in timing mode?
143 *
144 * SimObjects are expected to use Port::sendTiming() and
145 * Port::recvTiming() when accessing memory in this mode.
146 */
147 bool isTimingMode() const {
148 return memoryMode == Enums::timing;
149 }
150
151 /**
152 * Should caches be bypassed?
153 *
154 * Some CPUs need to bypass caches to allow direct memory
155 * accesses, which is required for hardware virtualization.
156 */
157 bool bypassCaches() const {
158 return memoryMode == Enums::atomic_noncaching;
159 }
160 /** @} */
161
162 /** @{ */
163 /**
164 * Get the memory mode of the system.
165 *
166 * \warn This should only be used by the Python world. The C++
167 * world should use one of the query functions above
168 * (isAtomicMode(), isTimingMode(), bypassCaches()).
169 */
170 Enums::MemoryMode getMemoryMode() const { return memoryMode; }
171
172 /**
173 * Change the memory mode of the system.
174 *
175 * \warn This should only be called by the Python!
176 *
177 * @param mode Mode to change to (atomic/timing/...)
178 */
179 void setMemoryMode(Enums::MemoryMode mode);
180 /** @} */
181
182 /**
183 * Get the cache line size of the system.
184 */
185 unsigned int cacheLineSize() const { return _cacheLineSize; }
186
182 PCEventQueue pcEventQueue;
183
184 std::vector<ThreadContext *> threadContexts;
185 int _numContexts;
186
187 ThreadContext *getThreadContext(ThreadID tid)
188 {
189 return threadContexts[tid];
190 }
191
192 int numContexts()
193 {
194 assert(_numContexts == (int)threadContexts.size());
195 return _numContexts;
196 }
197
198 /** Return number of running (non-halted) thread contexts in
199 * system. These threads could be Active or Suspended. */
200 int numRunningContexts();
201
202 Addr pagePtr;
203
204 uint64_t init_param;
205
206 /** Port to physical memory used for writing object files into ram at
207 * boot.*/
208 PortProxy physProxy;
209 FSTranslatingPortProxy virtProxy;
210
211 /** kernel symbol table */
212 SymbolTable *kernelSymtab;
213
214 /** Object pointer for the kernel code */
215 ObjectFile *kernel;
216
217 /** Begining of kernel code */
218 Addr kernelStart;
219
220 /** End of kernel code */
221 Addr kernelEnd;
222
223 /** Entry point in the kernel to start at */
224 Addr kernelEntry;
225
226 /** Mask that should be anded for binary/symbol loading.
227 * This allows one two different OS requirements for the same ISA to be
228 * handled. Some OSes are compiled for a virtual address and need to be
229 * loaded into physical memory that starts at address 0, while other
230 * bare metal tools generate images that start at address 0.
231 */
232 Addr loadAddrMask;
233
234 protected:
235 uint64_t nextPID;
236
237 public:
238 uint64_t allocatePID()
239 {
240 return nextPID++;
241 }
242
243 /** Get a pointer to access the physical memory of the system */
244 PhysicalMemory& getPhysMem() { return physmem; }
245
246 /** Amount of physical memory that is still free */
247 Addr freeMemSize() const;
248
249 /** Amount of physical memory that exists */
250 Addr memSize() const;
251
252 /**
253 * Check if a physical address is within a range of a memory that
254 * is part of the global address map.
255 *
256 * @param addr A physical address
257 * @return Whether the address corresponds to a memory
258 */
259 bool isMemAddr(Addr addr) const;
260
261 protected:
262
263 PhysicalMemory physmem;
264
265 Enums::MemoryMode memoryMode;
187 PCEventQueue pcEventQueue;
188
189 std::vector<ThreadContext *> threadContexts;
190 int _numContexts;
191
192 ThreadContext *getThreadContext(ThreadID tid)
193 {
194 return threadContexts[tid];
195 }
196
197 int numContexts()
198 {
199 assert(_numContexts == (int)threadContexts.size());
200 return _numContexts;
201 }
202
203 /** Return number of running (non-halted) thread contexts in
204 * system. These threads could be Active or Suspended. */
205 int numRunningContexts();
206
207 Addr pagePtr;
208
209 uint64_t init_param;
210
211 /** Port to physical memory used for writing object files into ram at
212 * boot.*/
213 PortProxy physProxy;
214 FSTranslatingPortProxy virtProxy;
215
216 /** kernel symbol table */
217 SymbolTable *kernelSymtab;
218
219 /** Object pointer for the kernel code */
220 ObjectFile *kernel;
221
222 /** Begining of kernel code */
223 Addr kernelStart;
224
225 /** End of kernel code */
226 Addr kernelEnd;
227
228 /** Entry point in the kernel to start at */
229 Addr kernelEntry;
230
231 /** Mask that should be anded for binary/symbol loading.
232 * This allows one two different OS requirements for the same ISA to be
233 * handled. Some OSes are compiled for a virtual address and need to be
234 * loaded into physical memory that starts at address 0, while other
235 * bare metal tools generate images that start at address 0.
236 */
237 Addr loadAddrMask;
238
239 protected:
240 uint64_t nextPID;
241
242 public:
243 uint64_t allocatePID()
244 {
245 return nextPID++;
246 }
247
248 /** Get a pointer to access the physical memory of the system */
249 PhysicalMemory& getPhysMem() { return physmem; }
250
251 /** Amount of physical memory that is still free */
252 Addr freeMemSize() const;
253
254 /** Amount of physical memory that exists */
255 Addr memSize() const;
256
257 /**
258 * Check if a physical address is within a range of a memory that
259 * is part of the global address map.
260 *
261 * @param addr A physical address
262 * @return Whether the address corresponds to a memory
263 */
264 bool isMemAddr(Addr addr) const;
265
266 protected:
267
268 PhysicalMemory physmem;
269
270 Enums::MemoryMode memoryMode;
271
272 const unsigned int _cacheLineSize;
273
266 uint64_t workItemsBegin;
267 uint64_t workItemsEnd;
268 uint32_t numWorkIds;
269 std::vector<bool> activeCpus;
270
271 /** This array is a per-sytem list of all devices capable of issuing a
272 * memory system request and an associated string for each master id.
273 * It's used to uniquely id any master in the system by name for things
274 * like cache statistics.
275 */
276 std::vector<std::string> masterIds;
277
278 public:
279
280 /** Request an id used to create a request object in the system. All objects
281 * that intend to issues requests into the memory system must request an id
282 * in the init() phase of startup. All master ids must be fixed by the
283 * regStats() phase that immediately preceeds it. This allows objects in the
284 * memory system to understand how many masters may exist and
285 * appropriately name the bins of their per-master stats before the stats
286 * are finalized
287 */
288 MasterID getMasterId(std::string req_name);
289
290 /** Get the name of an object for a given request id.
291 */
292 std::string getMasterName(MasterID master_id);
293
294 /** Get the number of masters registered in the system */
295 MasterID maxMasters()
296 {
297 return masterIds.size();
298 }
299
300 virtual void regStats();
301 /**
302 * Called by pseudo_inst to track the number of work items started by this
303 * system.
304 */
305 uint64_t
306 incWorkItemsBegin()
307 {
308 return ++workItemsBegin;
309 }
310
311 /**
312 * Called by pseudo_inst to track the number of work items completed by
313 * this system.
314 */
315 uint64_t
316 incWorkItemsEnd()
317 {
318 return ++workItemsEnd;
319 }
320
321 /**
322 * Called by pseudo_inst to mark the cpus actively executing work items.
323 * Returns the total number of cpus that have executed work item begin or
324 * ends.
325 */
326 int
327 markWorkItem(int index)
328 {
329 int count = 0;
330 assert(index < activeCpus.size());
331 activeCpus[index] = true;
332 for (std::vector<bool>::iterator i = activeCpus.begin();
333 i < activeCpus.end(); i++) {
334 if (*i) count++;
335 }
336 return count;
337 }
338
339 inline void workItemBegin(uint32_t tid, uint32_t workid)
340 {
341 std::pair<uint32_t,uint32_t> p(tid, workid);
342 lastWorkItemStarted[p] = curTick();
343 }
344
345 void workItemEnd(uint32_t tid, uint32_t workid);
346
347 /**
348 * Fix up an address used to match PCs for hooking simulator
349 * events on to target function executions. See comment in
350 * system.cc for details.
351 */
352 virtual Addr fixFuncEventAddr(Addr addr)
353 {
354 panic("Base fixFuncEventAddr not implemented.\n");
355 }
356
357 /** @{ */
358 /**
359 * Add a function-based event to the given function, to be looked
360 * up in the specified symbol table.
361 *
362 * The ...OrPanic flavor of the method causes the simulator to
363 * panic if the symbol can't be found.
364 *
365 * @param symtab Symbol table to use for look up.
366 * @param lbl Function to hook the event to.
367 * @param desc Description to be passed to the event.
368 * @param args Arguments to be forwarded to the event constructor.
369 */
370 template <class T, typename... Args>
371 T *addFuncEvent(const SymbolTable *symtab, const char *lbl,
372 const std::string &desc, Args... args)
373 {
374 Addr addr = 0; // initialize only to avoid compiler warning
375
376 if (symtab->findAddress(lbl, addr)) {
377 T *ev = new T(&pcEventQueue, desc, fixFuncEventAddr(addr),
378 std::forward<Args>(args)...);
379 return ev;
380 }
381
382 return NULL;
383 }
384
385 template <class T>
386 T *addFuncEvent(const SymbolTable *symtab, const char *lbl)
387 {
388 return addFuncEvent<T>(symtab, lbl, lbl);
389 }
390
391 template <class T, typename... Args>
392 T *addFuncEventOrPanic(const SymbolTable *symtab, const char *lbl,
393 Args... args)
394 {
395 T *e(addFuncEvent<T>(symtab, lbl, std::forward<Args>(args)...));
396 if (!e)
397 panic("Failed to find symbol '%s'", lbl);
398 return e;
399 }
400 /** @} */
401
402 /** @{ */
403 /**
404 * Add a function-based event to a kernel symbol.
405 *
406 * These functions work like their addFuncEvent() and
407 * addFuncEventOrPanic() counterparts. The only difference is that
408 * they automatically use the kernel symbol table. All arguments
409 * are forwarded to the underlying method.
410 *
411 * @see addFuncEvent()
412 * @see addFuncEventOrPanic()
413 *
414 * @param lbl Function to hook the event to.
415 * @param args Arguments to be passed to addFuncEvent
416 */
417 template <class T, typename... Args>
418 T *addKernelFuncEvent(const char *lbl, Args... args)
419 {
420 return addFuncEvent<T>(kernelSymtab, lbl,
421 std::forward<Args>(args)...);
422 }
423
424 template <class T, typename... Args>
425 T *addKernelFuncEventOrPanic(const char *lbl, Args... args)
426 {
427 T *e(addFuncEvent<T>(kernelSymtab, lbl,
428 std::forward<Args>(args)...));
429 if (!e)
430 panic("Failed to find kernel symbol '%s'", lbl);
431 return e;
432 }
433 /** @} */
434
435 public:
436 std::vector<BaseRemoteGDB *> remoteGDB;
437 std::vector<GDBListener *> gdbListen;
438 bool breakpoint();
439
440 public:
441 typedef SystemParams Params;
442
443 protected:
444 Params *_params;
445
446 public:
447 System(Params *p);
448 ~System();
449
450 void initState();
451
452 const Params *params() const { return (const Params *)_params; }
453
454 public:
455
456 /**
457 * Returns the addess the kernel starts at.
458 * @return address the kernel starts at
459 */
460 Addr getKernelStart() const { return kernelStart; }
461
462 /**
463 * Returns the addess the kernel ends at.
464 * @return address the kernel ends at
465 */
466 Addr getKernelEnd() const { return kernelEnd; }
467
468 /**
469 * Returns the addess the entry point to the kernel code.
470 * @return entry point of the kernel code
471 */
472 Addr getKernelEntry() const { return kernelEntry; }
473
474 /// Allocate npages contiguous unused physical pages
475 /// @return Starting address of first page
476 Addr allocPhysPages(int npages);
477
478 int registerThreadContext(ThreadContext *tc, int assigned=-1);
479 void replaceThreadContext(ThreadContext *tc, int context_id);
480
481 void serialize(std::ostream &os);
482 void unserialize(Checkpoint *cp, const std::string &section);
483
484 unsigned int drain(DrainManager *dm);
485 void drainResume();
486
487 public:
488 Counter totalNumInsts;
489 EventQueue instEventQueue;
490 std::map<std::pair<uint32_t,uint32_t>, Tick> lastWorkItemStarted;
491 std::map<uint32_t, Stats::Histogram*> workItemStats;
492
493 ////////////////////////////////////////////
494 //
495 // STATIC GLOBAL SYSTEM LIST
496 //
497 ////////////////////////////////////////////
498
499 static std::vector<System *> systemList;
500 static int numSystemsRunning;
501
502 static void printSystems();
503
504 // For futex system call
505 std::map<uint64_t, std::list<ThreadContext *> * > futexMap;
506
507 protected:
508
509 /**
510 * If needed, serialize additional symbol table entries for a
511 * specific subclass of this sytem. Currently this is used by
512 * Alpha and MIPS.
513 *
514 * @param os stream to serialize to
515 */
516 virtual void serializeSymtab(std::ostream &os) {}
517
518 /**
519 * If needed, unserialize additional symbol table entries for a
520 * specific subclass of this system.
521 *
522 * @param cp checkpoint to unserialize from
523 * @param section relevant section in the checkpoint
524 */
525 virtual void unserializeSymtab(Checkpoint *cp,
526 const std::string &section) {}
527
528};
529
530void printSystems();
531
532#endif // __SYSTEM_HH__
274 uint64_t workItemsBegin;
275 uint64_t workItemsEnd;
276 uint32_t numWorkIds;
277 std::vector<bool> activeCpus;
278
279 /** This array is a per-sytem list of all devices capable of issuing a
280 * memory system request and an associated string for each master id.
281 * It's used to uniquely id any master in the system by name for things
282 * like cache statistics.
283 */
284 std::vector<std::string> masterIds;
285
286 public:
287
288 /** Request an id used to create a request object in the system. All objects
289 * that intend to issues requests into the memory system must request an id
290 * in the init() phase of startup. All master ids must be fixed by the
291 * regStats() phase that immediately preceeds it. This allows objects in the
292 * memory system to understand how many masters may exist and
293 * appropriately name the bins of their per-master stats before the stats
294 * are finalized
295 */
296 MasterID getMasterId(std::string req_name);
297
298 /** Get the name of an object for a given request id.
299 */
300 std::string getMasterName(MasterID master_id);
301
302 /** Get the number of masters registered in the system */
303 MasterID maxMasters()
304 {
305 return masterIds.size();
306 }
307
308 virtual void regStats();
309 /**
310 * Called by pseudo_inst to track the number of work items started by this
311 * system.
312 */
313 uint64_t
314 incWorkItemsBegin()
315 {
316 return ++workItemsBegin;
317 }
318
319 /**
320 * Called by pseudo_inst to track the number of work items completed by
321 * this system.
322 */
323 uint64_t
324 incWorkItemsEnd()
325 {
326 return ++workItemsEnd;
327 }
328
329 /**
330 * Called by pseudo_inst to mark the cpus actively executing work items.
331 * Returns the total number of cpus that have executed work item begin or
332 * ends.
333 */
334 int
335 markWorkItem(int index)
336 {
337 int count = 0;
338 assert(index < activeCpus.size());
339 activeCpus[index] = true;
340 for (std::vector<bool>::iterator i = activeCpus.begin();
341 i < activeCpus.end(); i++) {
342 if (*i) count++;
343 }
344 return count;
345 }
346
347 inline void workItemBegin(uint32_t tid, uint32_t workid)
348 {
349 std::pair<uint32_t,uint32_t> p(tid, workid);
350 lastWorkItemStarted[p] = curTick();
351 }
352
353 void workItemEnd(uint32_t tid, uint32_t workid);
354
355 /**
356 * Fix up an address used to match PCs for hooking simulator
357 * events on to target function executions. See comment in
358 * system.cc for details.
359 */
360 virtual Addr fixFuncEventAddr(Addr addr)
361 {
362 panic("Base fixFuncEventAddr not implemented.\n");
363 }
364
365 /** @{ */
366 /**
367 * Add a function-based event to the given function, to be looked
368 * up in the specified symbol table.
369 *
370 * The ...OrPanic flavor of the method causes the simulator to
371 * panic if the symbol can't be found.
372 *
373 * @param symtab Symbol table to use for look up.
374 * @param lbl Function to hook the event to.
375 * @param desc Description to be passed to the event.
376 * @param args Arguments to be forwarded to the event constructor.
377 */
378 template <class T, typename... Args>
379 T *addFuncEvent(const SymbolTable *symtab, const char *lbl,
380 const std::string &desc, Args... args)
381 {
382 Addr addr = 0; // initialize only to avoid compiler warning
383
384 if (symtab->findAddress(lbl, addr)) {
385 T *ev = new T(&pcEventQueue, desc, fixFuncEventAddr(addr),
386 std::forward<Args>(args)...);
387 return ev;
388 }
389
390 return NULL;
391 }
392
393 template <class T>
394 T *addFuncEvent(const SymbolTable *symtab, const char *lbl)
395 {
396 return addFuncEvent<T>(symtab, lbl, lbl);
397 }
398
399 template <class T, typename... Args>
400 T *addFuncEventOrPanic(const SymbolTable *symtab, const char *lbl,
401 Args... args)
402 {
403 T *e(addFuncEvent<T>(symtab, lbl, std::forward<Args>(args)...));
404 if (!e)
405 panic("Failed to find symbol '%s'", lbl);
406 return e;
407 }
408 /** @} */
409
410 /** @{ */
411 /**
412 * Add a function-based event to a kernel symbol.
413 *
414 * These functions work like their addFuncEvent() and
415 * addFuncEventOrPanic() counterparts. The only difference is that
416 * they automatically use the kernel symbol table. All arguments
417 * are forwarded to the underlying method.
418 *
419 * @see addFuncEvent()
420 * @see addFuncEventOrPanic()
421 *
422 * @param lbl Function to hook the event to.
423 * @param args Arguments to be passed to addFuncEvent
424 */
425 template <class T, typename... Args>
426 T *addKernelFuncEvent(const char *lbl, Args... args)
427 {
428 return addFuncEvent<T>(kernelSymtab, lbl,
429 std::forward<Args>(args)...);
430 }
431
432 template <class T, typename... Args>
433 T *addKernelFuncEventOrPanic(const char *lbl, Args... args)
434 {
435 T *e(addFuncEvent<T>(kernelSymtab, lbl,
436 std::forward<Args>(args)...));
437 if (!e)
438 panic("Failed to find kernel symbol '%s'", lbl);
439 return e;
440 }
441 /** @} */
442
443 public:
444 std::vector<BaseRemoteGDB *> remoteGDB;
445 std::vector<GDBListener *> gdbListen;
446 bool breakpoint();
447
448 public:
449 typedef SystemParams Params;
450
451 protected:
452 Params *_params;
453
454 public:
455 System(Params *p);
456 ~System();
457
458 void initState();
459
460 const Params *params() const { return (const Params *)_params; }
461
462 public:
463
464 /**
465 * Returns the addess the kernel starts at.
466 * @return address the kernel starts at
467 */
468 Addr getKernelStart() const { return kernelStart; }
469
470 /**
471 * Returns the addess the kernel ends at.
472 * @return address the kernel ends at
473 */
474 Addr getKernelEnd() const { return kernelEnd; }
475
476 /**
477 * Returns the addess the entry point to the kernel code.
478 * @return entry point of the kernel code
479 */
480 Addr getKernelEntry() const { return kernelEntry; }
481
482 /// Allocate npages contiguous unused physical pages
483 /// @return Starting address of first page
484 Addr allocPhysPages(int npages);
485
486 int registerThreadContext(ThreadContext *tc, int assigned=-1);
487 void replaceThreadContext(ThreadContext *tc, int context_id);
488
489 void serialize(std::ostream &os);
490 void unserialize(Checkpoint *cp, const std::string &section);
491
492 unsigned int drain(DrainManager *dm);
493 void drainResume();
494
495 public:
496 Counter totalNumInsts;
497 EventQueue instEventQueue;
498 std::map<std::pair<uint32_t,uint32_t>, Tick> lastWorkItemStarted;
499 std::map<uint32_t, Stats::Histogram*> workItemStats;
500
501 ////////////////////////////////////////////
502 //
503 // STATIC GLOBAL SYSTEM LIST
504 //
505 ////////////////////////////////////////////
506
507 static std::vector<System *> systemList;
508 static int numSystemsRunning;
509
510 static void printSystems();
511
512 // For futex system call
513 std::map<uint64_t, std::list<ThreadContext *> * > futexMap;
514
515 protected:
516
517 /**
518 * If needed, serialize additional symbol table entries for a
519 * specific subclass of this sytem. Currently this is used by
520 * Alpha and MIPS.
521 *
522 * @param os stream to serialize to
523 */
524 virtual void serializeSymtab(std::ostream &os) {}
525
526 /**
527 * If needed, unserialize additional symbol table entries for a
528 * specific subclass of this system.
529 *
530 * @param cp checkpoint to unserialize from
531 * @param section relevant section in the checkpoint
532 */
533 virtual void unserializeSymtab(Checkpoint *cp,
534 const std::string &section) {}
535
536};
537
538void printSystems();
539
540#endif // __SYSTEM_HH__