system.cc (8826:6cc162805986) system.cc (8832:247fee427324)
1/*
2 * Copyright (c) 2011-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) 2003-2006 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 * Ali Saidi
45 * Rick Strong
46 */
47
48#include "arch/isa_traits.hh"
49#include "arch/remote_gdb.hh"
50#include "arch/utility.hh"
51#include "arch/vtophys.hh"
52#include "base/loader/object_file.hh"
53#include "base/loader/symtab.hh"
54#include "base/trace.hh"
55#include "config/the_isa.hh"
56#include "cpu/thread_context.hh"
57#include "debug/Loader.hh"
58#include "debug/WorkItems.hh"
59#include "kern/kernel_stats.hh"
60#include "mem/fs_translating_port_proxy.hh"
61#include "mem/mem_object.hh"
62#include "mem/physical.hh"
63#include "params/System.hh"
64#include "sim/byteswap.hh"
65#include "sim/debug.hh"
66#include "sim/full_system.hh"
67#include "sim/system.hh"
68
69using namespace std;
70using namespace TheISA;
71
72vector<System *> System::systemList;
73
74int System::numSystemsRunning = 0;
75
76System::System(Params *p)
77 : MemObject(p), _systemPort("system_port", this),
78 physmem(p->physmem),
79 _numContexts(0),
80 pagePtr(0),
81 init_param(p->init_param),
82 loadAddrMask(p->load_addr_mask),
83 nextPID(0),
84 memoryMode(p->mem_mode),
85 workItemsBegin(0),
86 workItemsEnd(0),
87 numWorkIds(p->num_work_ids),
88 _params(p),
89 totalNumInsts(0),
90 instEventQueue("system instruction-based event queue")
91{
92 // add self to global system list
93 systemList.push_back(this);
94
95 /** Keep track of all memories we can execute code out of
96 * in our system
97 */
98 for (int x = 0; x < p->memories.size(); x++) {
99 if (!p->memories[x])
100 continue;
101 memRanges.push_back(RangeSize(p->memories[x]->start(),
102 p->memories[x]->size()));
103 }
104
105 if (FullSystem) {
106 kernelSymtab = new SymbolTable;
107 if (!debugSymbolTable)
108 debugSymbolTable = new SymbolTable;
109
110 /**
111 * Get a port proxy to memory
112 */
113 physProxy = new PortProxy(*getSystemPort());
114 virtProxy = new FSTranslatingPortProxy(*getSystemPort());
115 }
1/*
2 * Copyright (c) 2011-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) 2003-2006 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 * Ali Saidi
45 * Rick Strong
46 */
47
48#include "arch/isa_traits.hh"
49#include "arch/remote_gdb.hh"
50#include "arch/utility.hh"
51#include "arch/vtophys.hh"
52#include "base/loader/object_file.hh"
53#include "base/loader/symtab.hh"
54#include "base/trace.hh"
55#include "config/the_isa.hh"
56#include "cpu/thread_context.hh"
57#include "debug/Loader.hh"
58#include "debug/WorkItems.hh"
59#include "kern/kernel_stats.hh"
60#include "mem/fs_translating_port_proxy.hh"
61#include "mem/mem_object.hh"
62#include "mem/physical.hh"
63#include "params/System.hh"
64#include "sim/byteswap.hh"
65#include "sim/debug.hh"
66#include "sim/full_system.hh"
67#include "sim/system.hh"
68
69using namespace std;
70using namespace TheISA;
71
72vector<System *> System::systemList;
73
74int System::numSystemsRunning = 0;
75
76System::System(Params *p)
77 : MemObject(p), _systemPort("system_port", this),
78 physmem(p->physmem),
79 _numContexts(0),
80 pagePtr(0),
81 init_param(p->init_param),
82 loadAddrMask(p->load_addr_mask),
83 nextPID(0),
84 memoryMode(p->mem_mode),
85 workItemsBegin(0),
86 workItemsEnd(0),
87 numWorkIds(p->num_work_ids),
88 _params(p),
89 totalNumInsts(0),
90 instEventQueue("system instruction-based event queue")
91{
92 // add self to global system list
93 systemList.push_back(this);
94
95 /** Keep track of all memories we can execute code out of
96 * in our system
97 */
98 for (int x = 0; x < p->memories.size(); x++) {
99 if (!p->memories[x])
100 continue;
101 memRanges.push_back(RangeSize(p->memories[x]->start(),
102 p->memories[x]->size()));
103 }
104
105 if (FullSystem) {
106 kernelSymtab = new SymbolTable;
107 if (!debugSymbolTable)
108 debugSymbolTable = new SymbolTable;
109
110 /**
111 * Get a port proxy to memory
112 */
113 physProxy = new PortProxy(*getSystemPort());
114 virtProxy = new FSTranslatingPortProxy(*getSystemPort());
115 }
116
117 // Get the generic system master IDs
118 MasterID tmp_id M5_VAR_USED;
119 tmp_id = getMasterId("writebacks");
120 assert(tmp_id == Request::wbMasterId);
121 tmp_id = getMasterId("functional");
122 assert(tmp_id == Request::funcMasterId);
123 tmp_id = getMasterId("interrupt");
124 assert(tmp_id == Request::intMasterId);
125
116}
117
118System::~System()
119{
120 delete kernelSymtab;
121 delete kernel;
122
123 for (uint32_t j = 0; j < numWorkIds; j++)
124 delete workItemStats[j];
125}
126
127void
128System::init()
129{
130 // check that the system port is connected
131 if (!_systemPort.isConnected())
132 panic("System port on %s is not connected.\n", name());
133}
134
135Port*
136System::getPort(const std::string &if_name, int idx)
137{
138 // no need to distinguish at the moment (besides checking)
139 return &_systemPort;
140}
141
142void
143System::setMemoryMode(Enums::MemoryMode mode)
144{
145 assert(getState() == Drained);
146 memoryMode = mode;
147}
148
149bool System::breakpoint()
150{
151 if (remoteGDB.size())
152 return remoteGDB[0]->breakpoint();
153 return false;
154}
155
156/**
157 * Setting rgdb_wait to a positive integer waits for a remote debugger to
158 * connect to that context ID before continuing. This should really
159 be a parameter on the CPU object or something...
160 */
161int rgdb_wait = -1;
162
163int
164System::registerThreadContext(ThreadContext *tc, int assigned)
165{
166 int id;
167 if (assigned == -1) {
168 for (id = 0; id < threadContexts.size(); id++) {
169 if (!threadContexts[id])
170 break;
171 }
172
173 if (threadContexts.size() <= id)
174 threadContexts.resize(id + 1);
175 } else {
176 if (threadContexts.size() <= assigned)
177 threadContexts.resize(assigned + 1);
178 id = assigned;
179 }
180
181 if (threadContexts[id])
182 fatal("Cannot have two CPUs with the same id (%d)\n", id);
183
184 threadContexts[id] = tc;
185 _numContexts++;
186
187 int port = getRemoteGDBPort();
188 if (port) {
189 RemoteGDB *rgdb = new RemoteGDB(this, tc);
190 GDBListener *gdbl = new GDBListener(rgdb, port + id);
191 gdbl->listen();
192
193 if (rgdb_wait != -1 && rgdb_wait == id)
194 gdbl->accept();
195
196 if (remoteGDB.size() <= id) {
197 remoteGDB.resize(id + 1);
198 }
199
200 remoteGDB[id] = rgdb;
201 }
202
203 activeCpus.push_back(false);
204
205 return id;
206}
207
208int
209System::numRunningContexts()
210{
211 int running = 0;
212 for (int i = 0; i < _numContexts; ++i) {
213 if (threadContexts[i]->status() != ThreadContext::Halted)
214 ++running;
215 }
216 return running;
217}
218
219void
220System::initState()
221{
222 int i;
223 if (FullSystem) {
224 for (i = 0; i < threadContexts.size(); i++)
225 TheISA::startupCPU(threadContexts[i], i);
226 // Moved from the constructor to here since it relies on the
227 // address map being resolved in the interconnect
228 /**
229 * Load the kernel code into memory
230 */
231 if (params()->kernel == "") {
232 inform("No kernel set for full system simulation. "
233 "Assuming you know what you're doing...\n");
234 } else {
235 // Load kernel code
236 kernel = createObjectFile(params()->kernel);
237 inform("kernel located at: %s", params()->kernel);
238
239 if (kernel == NULL)
240 fatal("Could not load kernel file %s", params()->kernel);
241
242 // Load program sections into memory
243 kernel->loadSections(physProxy, loadAddrMask);
244
245 // setup entry points
246 kernelStart = kernel->textBase();
247 kernelEnd = kernel->bssBase() + kernel->bssSize();
248 kernelEntry = kernel->entryPoint();
249
250 // load symbols
251 if (!kernel->loadGlobalSymbols(kernelSymtab))
252 fatal("could not load kernel symbols\n");
253
254 if (!kernel->loadLocalSymbols(kernelSymtab))
255 fatal("could not load kernel local symbols\n");
256
257 if (!kernel->loadGlobalSymbols(debugSymbolTable))
258 fatal("could not load kernel symbols\n");
259
260 if (!kernel->loadLocalSymbols(debugSymbolTable))
261 fatal("could not load kernel local symbols\n");
262
263 DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
264 DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
265 DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
266 DPRINTF(Loader, "Kernel loaded...\n");
267 }
268 }
269
270 // increment the number of running systms
271 numSystemsRunning++;
272
273 activeCpus.clear();
274
275 if (!FullSystem)
276 return;
277
278 for (i = 0; i < threadContexts.size(); i++)
279 TheISA::startupCPU(threadContexts[i], i);
280}
281
282void
283System::replaceThreadContext(ThreadContext *tc, int context_id)
284{
285 if (context_id >= threadContexts.size()) {
286 panic("replaceThreadContext: bad id, %d >= %d\n",
287 context_id, threadContexts.size());
288 }
289
290 threadContexts[context_id] = tc;
291 if (context_id < remoteGDB.size())
292 remoteGDB[context_id]->replaceThreadContext(tc);
293}
294
295Addr
296System::allocPhysPages(int npages)
297{
298 Addr return_addr = pagePtr << LogVMPageSize;
299 pagePtr += npages;
300 if (pagePtr > physmem->size())
301 fatal("Out of memory, please increase size of physical memory.");
302 return return_addr;
303}
304
305Addr
306System::memSize()
307{
308 return physmem->size();
309}
310
311Addr
312System::freeMemSize()
313{
314 return physmem->size() - (pagePtr << LogVMPageSize);
315}
316
317bool
318System::isMemory(const Addr addr) const
319{
320 std::list<Range<Addr> >::const_iterator i;
321 for (i = memRanges.begin(); i != memRanges.end(); i++) {
322 if (*i == addr)
323 return true;
324 }
325 return false;
326}
327
328void
329System::resume()
330{
331 SimObject::resume();
332 totalNumInsts = 0;
333}
334
335void
336System::serialize(ostream &os)
337{
338 if (FullSystem)
339 kernelSymtab->serialize("kernel_symtab", os);
340 SERIALIZE_SCALAR(pagePtr);
341 SERIALIZE_SCALAR(nextPID);
342}
343
344
345void
346System::unserialize(Checkpoint *cp, const string &section)
347{
348 if (FullSystem)
349 kernelSymtab->unserialize("kernel_symtab", cp, section);
350 UNSERIALIZE_SCALAR(pagePtr);
351 UNSERIALIZE_SCALAR(nextPID);
352}
353
354void
355System::regStats()
356{
357 for (uint32_t j = 0; j < numWorkIds ; j++) {
358 workItemStats[j] = new Stats::Histogram();
359 stringstream namestr;
360 ccprintf(namestr, "work_item_type%d", j);
361 workItemStats[j]->init(20)
362 .name(name() + "." + namestr.str())
363 .desc("Run time stat for" + namestr.str())
364 .prereq(*workItemStats[j]);
365 }
366}
367
368void
369System::workItemEnd(uint32_t tid, uint32_t workid)
370{
371 std::pair<uint32_t,uint32_t> p(tid, workid);
372 if (!lastWorkItemStarted.count(p))
373 return;
374
375 Tick samp = curTick() - lastWorkItemStarted[p];
376 DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp);
377
378 if (workid >= numWorkIds)
379 fatal("Got workid greater than specified in system configuration\n");
380
381 workItemStats[workid]->sample(samp);
382 lastWorkItemStarted.erase(p);
383}
384
385void
386System::printSystems()
387{
388 vector<System *>::iterator i = systemList.begin();
389 vector<System *>::iterator end = systemList.end();
390 for (; i != end; ++i) {
391 System *sys = *i;
392 cerr << "System " << sys->name() << ": " << hex << sys << endl;
393 }
394}
395
396void
397printSystems()
398{
399 System::printSystems();
400}
401
126}
127
128System::~System()
129{
130 delete kernelSymtab;
131 delete kernel;
132
133 for (uint32_t j = 0; j < numWorkIds; j++)
134 delete workItemStats[j];
135}
136
137void
138System::init()
139{
140 // check that the system port is connected
141 if (!_systemPort.isConnected())
142 panic("System port on %s is not connected.\n", name());
143}
144
145Port*
146System::getPort(const std::string &if_name, int idx)
147{
148 // no need to distinguish at the moment (besides checking)
149 return &_systemPort;
150}
151
152void
153System::setMemoryMode(Enums::MemoryMode mode)
154{
155 assert(getState() == Drained);
156 memoryMode = mode;
157}
158
159bool System::breakpoint()
160{
161 if (remoteGDB.size())
162 return remoteGDB[0]->breakpoint();
163 return false;
164}
165
166/**
167 * Setting rgdb_wait to a positive integer waits for a remote debugger to
168 * connect to that context ID before continuing. This should really
169 be a parameter on the CPU object or something...
170 */
171int rgdb_wait = -1;
172
173int
174System::registerThreadContext(ThreadContext *tc, int assigned)
175{
176 int id;
177 if (assigned == -1) {
178 for (id = 0; id < threadContexts.size(); id++) {
179 if (!threadContexts[id])
180 break;
181 }
182
183 if (threadContexts.size() <= id)
184 threadContexts.resize(id + 1);
185 } else {
186 if (threadContexts.size() <= assigned)
187 threadContexts.resize(assigned + 1);
188 id = assigned;
189 }
190
191 if (threadContexts[id])
192 fatal("Cannot have two CPUs with the same id (%d)\n", id);
193
194 threadContexts[id] = tc;
195 _numContexts++;
196
197 int port = getRemoteGDBPort();
198 if (port) {
199 RemoteGDB *rgdb = new RemoteGDB(this, tc);
200 GDBListener *gdbl = new GDBListener(rgdb, port + id);
201 gdbl->listen();
202
203 if (rgdb_wait != -1 && rgdb_wait == id)
204 gdbl->accept();
205
206 if (remoteGDB.size() <= id) {
207 remoteGDB.resize(id + 1);
208 }
209
210 remoteGDB[id] = rgdb;
211 }
212
213 activeCpus.push_back(false);
214
215 return id;
216}
217
218int
219System::numRunningContexts()
220{
221 int running = 0;
222 for (int i = 0; i < _numContexts; ++i) {
223 if (threadContexts[i]->status() != ThreadContext::Halted)
224 ++running;
225 }
226 return running;
227}
228
229void
230System::initState()
231{
232 int i;
233 if (FullSystem) {
234 for (i = 0; i < threadContexts.size(); i++)
235 TheISA::startupCPU(threadContexts[i], i);
236 // Moved from the constructor to here since it relies on the
237 // address map being resolved in the interconnect
238 /**
239 * Load the kernel code into memory
240 */
241 if (params()->kernel == "") {
242 inform("No kernel set for full system simulation. "
243 "Assuming you know what you're doing...\n");
244 } else {
245 // Load kernel code
246 kernel = createObjectFile(params()->kernel);
247 inform("kernel located at: %s", params()->kernel);
248
249 if (kernel == NULL)
250 fatal("Could not load kernel file %s", params()->kernel);
251
252 // Load program sections into memory
253 kernel->loadSections(physProxy, loadAddrMask);
254
255 // setup entry points
256 kernelStart = kernel->textBase();
257 kernelEnd = kernel->bssBase() + kernel->bssSize();
258 kernelEntry = kernel->entryPoint();
259
260 // load symbols
261 if (!kernel->loadGlobalSymbols(kernelSymtab))
262 fatal("could not load kernel symbols\n");
263
264 if (!kernel->loadLocalSymbols(kernelSymtab))
265 fatal("could not load kernel local symbols\n");
266
267 if (!kernel->loadGlobalSymbols(debugSymbolTable))
268 fatal("could not load kernel symbols\n");
269
270 if (!kernel->loadLocalSymbols(debugSymbolTable))
271 fatal("could not load kernel local symbols\n");
272
273 DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
274 DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
275 DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
276 DPRINTF(Loader, "Kernel loaded...\n");
277 }
278 }
279
280 // increment the number of running systms
281 numSystemsRunning++;
282
283 activeCpus.clear();
284
285 if (!FullSystem)
286 return;
287
288 for (i = 0; i < threadContexts.size(); i++)
289 TheISA::startupCPU(threadContexts[i], i);
290}
291
292void
293System::replaceThreadContext(ThreadContext *tc, int context_id)
294{
295 if (context_id >= threadContexts.size()) {
296 panic("replaceThreadContext: bad id, %d >= %d\n",
297 context_id, threadContexts.size());
298 }
299
300 threadContexts[context_id] = tc;
301 if (context_id < remoteGDB.size())
302 remoteGDB[context_id]->replaceThreadContext(tc);
303}
304
305Addr
306System::allocPhysPages(int npages)
307{
308 Addr return_addr = pagePtr << LogVMPageSize;
309 pagePtr += npages;
310 if (pagePtr > physmem->size())
311 fatal("Out of memory, please increase size of physical memory.");
312 return return_addr;
313}
314
315Addr
316System::memSize()
317{
318 return physmem->size();
319}
320
321Addr
322System::freeMemSize()
323{
324 return physmem->size() - (pagePtr << LogVMPageSize);
325}
326
327bool
328System::isMemory(const Addr addr) const
329{
330 std::list<Range<Addr> >::const_iterator i;
331 for (i = memRanges.begin(); i != memRanges.end(); i++) {
332 if (*i == addr)
333 return true;
334 }
335 return false;
336}
337
338void
339System::resume()
340{
341 SimObject::resume();
342 totalNumInsts = 0;
343}
344
345void
346System::serialize(ostream &os)
347{
348 if (FullSystem)
349 kernelSymtab->serialize("kernel_symtab", os);
350 SERIALIZE_SCALAR(pagePtr);
351 SERIALIZE_SCALAR(nextPID);
352}
353
354
355void
356System::unserialize(Checkpoint *cp, const string &section)
357{
358 if (FullSystem)
359 kernelSymtab->unserialize("kernel_symtab", cp, section);
360 UNSERIALIZE_SCALAR(pagePtr);
361 UNSERIALIZE_SCALAR(nextPID);
362}
363
364void
365System::regStats()
366{
367 for (uint32_t j = 0; j < numWorkIds ; j++) {
368 workItemStats[j] = new Stats::Histogram();
369 stringstream namestr;
370 ccprintf(namestr, "work_item_type%d", j);
371 workItemStats[j]->init(20)
372 .name(name() + "." + namestr.str())
373 .desc("Run time stat for" + namestr.str())
374 .prereq(*workItemStats[j]);
375 }
376}
377
378void
379System::workItemEnd(uint32_t tid, uint32_t workid)
380{
381 std::pair<uint32_t,uint32_t> p(tid, workid);
382 if (!lastWorkItemStarted.count(p))
383 return;
384
385 Tick samp = curTick() - lastWorkItemStarted[p];
386 DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp);
387
388 if (workid >= numWorkIds)
389 fatal("Got workid greater than specified in system configuration\n");
390
391 workItemStats[workid]->sample(samp);
392 lastWorkItemStarted.erase(p);
393}
394
395void
396System::printSystems()
397{
398 vector<System *>::iterator i = systemList.begin();
399 vector<System *>::iterator end = systemList.end();
400 for (; i != end; ++i) {
401 System *sys = *i;
402 cerr << "System " << sys->name() << ": " << hex << sys << endl;
403 }
404}
405
406void
407printSystems()
408{
409 System::printSystems();
410}
411
412MasterID
413System::getMasterId(std::string master_name)
414{
415 // strip off system name if the string starts with it
416 if (master_name.size() > name().size() &&
417 master_name.compare(0, name().size(), name()) == 0)
418 master_name = master_name.erase(0, name().size() + 1);
419
420 // CPUs in switch_cpus ask for ids again after switching
421 for (int i = 0; i < masterIds.size(); i++) {
422 if (masterIds[i] == master_name) {
423 return i;
424 }
425 }
426
427 // todo: Check if stats are enabled yet
428 // I just don't know a good way to do it
429
430 if (false)
431 fatal("Can't request a masterId after regStats(). \
432 You must do so in init().\n");
433
434 masterIds.push_back(master_name);
435
436 return masterIds.size() - 1;
437}
438
439std::string
440System::getMasterName(MasterID master_id)
441{
442 if (master_id >= masterIds.size())
443 fatal("Invalid master_id passed to getMasterName()\n");
444
445 return masterIds[master_id];
446}
447
402const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
403 "timing"};
404
405System *
406SystemParams::create()
407{
408 return new System(this);
409}
448const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
449 "timing"};
450
451System *
452SystemParams::create()
453{
454 return new System(this);
455}