atomic.cc (10913:38dbdeea7f1f) atomic.cc (11147:cc8d6e99cf46)
1/*
2 * Copyright 2014 Google, Inc.
1/*
2 * Copyright 2014 Google, Inc.
3 * Copyright (c) 2012-2013 ARM Limited
3 * Copyright (c) 2012-2013,2015 ARM Limited
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated

--- 67 unchanged lines hidden (view full) ---

79AtomicSimpleCPU::TickEvent::description() const
80{
81 return "AtomicSimpleCPU tick";
82}
83
84void
85AtomicSimpleCPU::init()
86{
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated

--- 67 unchanged lines hidden (view full) ---

79AtomicSimpleCPU::TickEvent::description() const
80{
81 return "AtomicSimpleCPU tick";
82}
83
84void
85AtomicSimpleCPU::init()
86{
87 BaseCPU::init();
87 BaseSimpleCPU::init();
88
88
89 // Initialise the ThreadContext's memory proxies
90 tcBase()->initMemProxies(tcBase());
91
92 if (FullSystem && !params()->switched_out) {
93 ThreadID size = threadContexts.size();
94 for (ThreadID i = 0; i < size; ++i) {
95 ThreadContext *tc = threadContexts[i];
96 // initialize CPU, including PC
97 TheISA::initCPU(tc, tc->contextId());
98 }
99 }
100
101 // Atomic doesn't do MT right now, so contextId == threadId
102 ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT
103 data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too
104 data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too
89 ifetch_req.setThreadContext(_cpuId, 0);
90 data_read_req.setThreadContext(_cpuId, 0);
91 data_write_req.setThreadContext(_cpuId, 0);
105}
106
107AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
108 : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false),
109 simulate_data_stalls(p->simulate_data_stalls),
110 simulate_inst_stalls(p->simulate_inst_stalls),
111 icachePort(name() + ".icache_port", this),
112 dcachePort(name() + ".dcache_port", this),

--- 13 unchanged lines hidden (view full) ---

126
127DrainState
128AtomicSimpleCPU::drain()
129{
130 if (switchedOut())
131 return DrainState::Drained;
132
133 if (!isDrained()) {
92}
93
94AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
95 : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false),
96 simulate_data_stalls(p->simulate_data_stalls),
97 simulate_inst_stalls(p->simulate_inst_stalls),
98 icachePort(name() + ".icache_port", this),
99 dcachePort(name() + ".dcache_port", this),

--- 13 unchanged lines hidden (view full) ---

113
114DrainState
115AtomicSimpleCPU::drain()
116{
117 if (switchedOut())
118 return DrainState::Drained;
119
120 if (!isDrained()) {
134 DPRINTF(Drain, "Requesting drain: %s\n", pcState());
121 DPRINTF(Drain, "Requesting drain.\n");
135 return DrainState::Draining;
136 } else {
137 if (tickEvent.scheduled())
138 deschedule(tickEvent);
139
122 return DrainState::Draining;
123 } else {
124 if (tickEvent.scheduled())
125 deschedule(tickEvent);
126
127 activeThreads.clear();
140 DPRINTF(Drain, "Not executing microcode, no need to drain.\n");
141 return DrainState::Drained;
142 }
143}
144
145void
146AtomicSimpleCPU::drainResume()
147{
148 assert(!tickEvent.scheduled());
149 if (switchedOut())
150 return;
151
152 DPRINTF(SimpleCPU, "Resume\n");
153 verifyMemoryMode();
154
155 assert(!threadContexts.empty());
128 DPRINTF(Drain, "Not executing microcode, no need to drain.\n");
129 return DrainState::Drained;
130 }
131}
132
133void
134AtomicSimpleCPU::drainResume()
135{
136 assert(!tickEvent.scheduled());
137 if (switchedOut())
138 return;
139
140 DPRINTF(SimpleCPU, "Resume\n");
141 verifyMemoryMode();
142
143 assert(!threadContexts.empty());
156 if (threadContexts.size() > 1)
157 fatal("The atomic CPU only supports one thread.\n");
158
144
159 if (thread->status() == ThreadContext::Active) {
160 schedule(tickEvent, nextCycle());
161 _status = BaseSimpleCPU::Running;
162 notIdleFraction = 1;
163 } else {
164 _status = BaseSimpleCPU::Idle;
165 notIdleFraction = 0;
145 _status = BaseSimpleCPU::Idle;
146
147 for (ThreadID tid = 0; tid < numThreads; tid++) {
148 if (threadInfo[tid]->thread->status() == ThreadContext::Active) {
149 threadInfo[tid]->notIdleFraction = 1;
150 activeThreads.push_back(tid);
151 _status = BaseSimpleCPU::Running;
152
153 // Tick if any threads active
154 if (!tickEvent.scheduled()) {
155 schedule(tickEvent, nextCycle());
156 }
157 } else {
158 threadInfo[tid]->notIdleFraction = 0;
159 }
166 }
167}
168
169bool
170AtomicSimpleCPU::tryCompleteDrain()
171{
172 if (drainState() != DrainState::Draining)
173 return false;
174
160 }
161}
162
163bool
164AtomicSimpleCPU::tryCompleteDrain()
165{
166 if (drainState() != DrainState::Draining)
167 return false;
168
175 DPRINTF(Drain, "tryCompleteDrain: %s\n", pcState());
169 DPRINTF(Drain, "tryCompleteDrain.\n");
176 if (!isDrained())
177 return false;
178
179 DPRINTF(Drain, "CPU done draining, processing drain event\n");
180 signalDrainDone();
181
182 return true;
183}

--- 12 unchanged lines hidden (view full) ---

196
197void
198AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
199{
200 BaseSimpleCPU::takeOverFrom(oldCPU);
201
202 // The tick event should have been descheduled by drain()
203 assert(!tickEvent.scheduled());
170 if (!isDrained())
171 return false;
172
173 DPRINTF(Drain, "CPU done draining, processing drain event\n");
174 signalDrainDone();
175
176 return true;
177}

--- 12 unchanged lines hidden (view full) ---

190
191void
192AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
193{
194 BaseSimpleCPU::takeOverFrom(oldCPU);
195
196 // The tick event should have been descheduled by drain()
197 assert(!tickEvent.scheduled());
204
205 ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT
206 data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too
207 data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too
208}
209
210void
211AtomicSimpleCPU::verifyMemoryMode() const
212{
213 if (!system->isAtomicMode()) {
214 fatal("The atomic CPU requires the memory system to be in "
215 "'atomic' mode.\n");
216 }
217}
218
219void
220AtomicSimpleCPU::activateContext(ThreadID thread_num)
221{
222 DPRINTF(SimpleCPU, "ActivateContext %d\n", thread_num);
223
198}
199
200void
201AtomicSimpleCPU::verifyMemoryMode() const
202{
203 if (!system->isAtomicMode()) {
204 fatal("The atomic CPU requires the memory system to be in "
205 "'atomic' mode.\n");
206 }
207}
208
209void
210AtomicSimpleCPU::activateContext(ThreadID thread_num)
211{
212 DPRINTF(SimpleCPU, "ActivateContext %d\n", thread_num);
213
224 assert(thread_num == 0);
225 assert(thread);
214 assert(thread_num < numThreads);
226
215
227 assert(_status == Idle);
228 assert(!tickEvent.scheduled());
229
230 notIdleFraction = 1;
231 Cycles delta = ticksToCycles(thread->lastActivate - thread->lastSuspend);
216 threadInfo[thread_num]->notIdleFraction = 1;
217 Cycles delta = ticksToCycles(threadInfo[thread_num]->thread->lastActivate -
218 threadInfo[thread_num]->thread->lastSuspend);
232 numCycles += delta;
233 ppCycles->notify(delta);
234
219 numCycles += delta;
220 ppCycles->notify(delta);
221
235 //Make sure ticks are still on multiples of cycles
236 schedule(tickEvent, clockEdge(Cycles(0)));
222 if (!tickEvent.scheduled()) {
223 //Make sure ticks are still on multiples of cycles
224 schedule(tickEvent, clockEdge(Cycles(0)));
225 }
237 _status = BaseSimpleCPU::Running;
226 _status = BaseSimpleCPU::Running;
227 if (std::find(activeThreads.begin(), activeThreads.end(), thread_num)
228 == activeThreads.end()) {
229 activeThreads.push_back(thread_num);
230 }
238}
239
240
241void
242AtomicSimpleCPU::suspendContext(ThreadID thread_num)
243{
244 DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
245
231}
232
233
234void
235AtomicSimpleCPU::suspendContext(ThreadID thread_num)
236{
237 DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
238
246 assert(thread_num == 0);
247 assert(thread);
239 assert(thread_num < numThreads);
240 activeThreads.remove(thread_num);
248
249 if (_status == Idle)
250 return;
251
252 assert(_status == BaseSimpleCPU::Running);
253
241
242 if (_status == Idle)
243 return;
244
245 assert(_status == BaseSimpleCPU::Running);
246
254 // tick event may not be scheduled if this gets called from inside
255 // an instruction's execution, e.g. "quiesce"
256 if (tickEvent.scheduled())
257 deschedule(tickEvent);
247 threadInfo[thread_num]->notIdleFraction = 0;
258
248
259 notIdleFraction = 0;
260 _status = Idle;
249 if (activeThreads.empty()) {
250 _status = Idle;
251
252 if (tickEvent.scheduled()) {
253 deschedule(tickEvent);
254 }
255 }
256
261}
262
263
264Tick
265AtomicSimpleCPU::AtomicCPUDPort::recvAtomicSnoop(PacketPtr pkt)
266{
267 DPRINTF(SimpleCPU, "received snoop pkt for addr:%#x %s\n", pkt->getAddr(),
268 pkt->cmdString());
269
270 // X86 ISA: Snooping an invalidation for monitor/mwait
271 AtomicSimpleCPU *cpu = (AtomicSimpleCPU *)(&owner);
257}
258
259
260Tick
261AtomicSimpleCPU::AtomicCPUDPort::recvAtomicSnoop(PacketPtr pkt)
262{
263 DPRINTF(SimpleCPU, "received snoop pkt for addr:%#x %s\n", pkt->getAddr(),
264 pkt->cmdString());
265
266 // X86 ISA: Snooping an invalidation for monitor/mwait
267 AtomicSimpleCPU *cpu = (AtomicSimpleCPU *)(&owner);
272 if(cpu->getAddrMonitor()->doMonitor(pkt)) {
268 if(cpu->getCpuAddrMonitor()->doMonitor(pkt)) {
273 cpu->wakeup();
274 }
275
276 // if snoop invalidates, release any associated locks
277 if (pkt->isInvalidate()) {
278 DPRINTF(SimpleCPU, "received invalidation for addr:%#x\n",
279 pkt->getAddr());
269 cpu->wakeup();
270 }
271
272 // if snoop invalidates, release any associated locks
273 if (pkt->isInvalidate()) {
274 DPRINTF(SimpleCPU, "received invalidation for addr:%#x\n",
275 pkt->getAddr());
280 TheISA::handleLockedSnoop(cpu->thread, pkt, cacheBlockMask);
276 for (auto &t_info : cpu->threadInfo) {
277 TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
278 }
281 }
282
283 return 0;
284}
285
286void
287AtomicSimpleCPU::AtomicCPUDPort::recvFunctionalSnoop(PacketPtr pkt)
288{
289 DPRINTF(SimpleCPU, "received snoop pkt for addr:%#x %s\n", pkt->getAddr(),
290 pkt->cmdString());
291
292 // X86 ISA: Snooping an invalidation for monitor/mwait
293 AtomicSimpleCPU *cpu = (AtomicSimpleCPU *)(&owner);
279 }
280
281 return 0;
282}
283
284void
285AtomicSimpleCPU::AtomicCPUDPort::recvFunctionalSnoop(PacketPtr pkt)
286{
287 DPRINTF(SimpleCPU, "received snoop pkt for addr:%#x %s\n", pkt->getAddr(),
288 pkt->cmdString());
289
290 // X86 ISA: Snooping an invalidation for monitor/mwait
291 AtomicSimpleCPU *cpu = (AtomicSimpleCPU *)(&owner);
294 if(cpu->getAddrMonitor()->doMonitor(pkt)) {
292 if(cpu->getCpuAddrMonitor()->doMonitor(pkt)) {
295 cpu->wakeup();
296 }
297
298 // if snoop invalidates, release any associated locks
299 if (pkt->isInvalidate()) {
300 DPRINTF(SimpleCPU, "received invalidation for addr:%#x\n",
301 pkt->getAddr());
293 cpu->wakeup();
294 }
295
296 // if snoop invalidates, release any associated locks
297 if (pkt->isInvalidate()) {
298 DPRINTF(SimpleCPU, "received invalidation for addr:%#x\n",
299 pkt->getAddr());
302 TheISA::handleLockedSnoop(cpu->thread, pkt, cacheBlockMask);
300 for (auto &t_info : cpu->threadInfo) {
301 TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
302 }
303 }
304}
305
306Fault
307AtomicSimpleCPU::readMem(Addr addr, uint8_t * data,
308 unsigned size, unsigned flags)
309{
303 }
304}
305
306Fault
307AtomicSimpleCPU::readMem(Addr addr, uint8_t * data,
308 unsigned size, unsigned flags)
309{
310 SimpleExecContext& t_info = *threadInfo[curThread];
311 SimpleThread* thread = t_info.thread;
312
310 // use the CPU's statically allocated read request and packet objects
311 Request *req = &data_read_req;
312
313 if (traceData)
314 traceData->setMem(addr, size, flags);
315
316 //The size of the data we're trying to read.
317 int fullSize = size;

--- 7 unchanged lines hidden (view full) ---

325
326 dcache_latency = 0;
327
328 req->taskId(taskId());
329 while (1) {
330 req->setVirt(0, addr, size, flags, dataMasterId(), thread->pcState().instAddr());
331
332 // translate to physical address
313 // use the CPU's statically allocated read request and packet objects
314 Request *req = &data_read_req;
315
316 if (traceData)
317 traceData->setMem(addr, size, flags);
318
319 //The size of the data we're trying to read.
320 int fullSize = size;

--- 7 unchanged lines hidden (view full) ---

328
329 dcache_latency = 0;
330
331 req->taskId(taskId());
332 while (1) {
333 req->setVirt(0, addr, size, flags, dataMasterId(), thread->pcState().instAddr());
334
335 // translate to physical address
333 Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
336 Fault fault = thread->dtb->translateAtomic(req, thread->getTC(),
337 BaseTLB::Read);
334
335 // Now do the access.
336 if (fault == NoFault && !req->getFlags().isSet(Request::NO_ACCESS)) {
337 Packet pkt(req, Packet::makeReadCmd(req));
338 pkt.dataStatic(data);
339
340 if (req->isMmappedIpr())
341 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);

--- 23 unchanged lines hidden (view full) ---

365
366 //If we don't need to access a second cache line, stop now.
367 if (secondAddr <= addr)
368 {
369 if (req->isLockedRMW() && fault == NoFault) {
370 assert(!locked);
371 locked = true;
372 }
338
339 // Now do the access.
340 if (fault == NoFault && !req->getFlags().isSet(Request::NO_ACCESS)) {
341 Packet pkt(req, Packet::makeReadCmd(req));
342 pkt.dataStatic(data);
343
344 if (req->isMmappedIpr())
345 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt);

--- 23 unchanged lines hidden (view full) ---

369
370 //If we don't need to access a second cache line, stop now.
371 if (secondAddr <= addr)
372 {
373 if (req->isLockedRMW() && fault == NoFault) {
374 assert(!locked);
375 locked = true;
376 }
377
373 return fault;
374 }
375
376 /*
377 * Set up for accessing the second cache line.
378 */
379
380 //Move the pointer we're reading into to the correct location.

--- 5 unchanged lines hidden (view full) ---

386 }
387}
388
389
390Fault
391AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size,
392 Addr addr, unsigned flags, uint64_t *res)
393{
378 return fault;
379 }
380
381 /*
382 * Set up for accessing the second cache line.
383 */
384
385 //Move the pointer we're reading into to the correct location.

--- 5 unchanged lines hidden (view full) ---

391 }
392}
393
394
395Fault
396AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size,
397 Addr addr, unsigned flags, uint64_t *res)
398{
394
399 SimpleExecContext& t_info = *threadInfo[curThread];
400 SimpleThread* thread = t_info.thread;
395 static uint8_t zero_array[64] = {};
396
397 if (data == NULL) {
398 assert(size <= 64);
399 assert(flags & Request::CACHE_BLOCK_ZERO);
400 // This must be a cache block cleaning request
401 data = zero_array;
402 }

--- 16 unchanged lines hidden (view full) ---

419
420 dcache_latency = 0;
421
422 req->taskId(taskId());
423 while(1) {
424 req->setVirt(0, addr, size, flags, dataMasterId(), thread->pcState().instAddr());
425
426 // translate to physical address
401 static uint8_t zero_array[64] = {};
402
403 if (data == NULL) {
404 assert(size <= 64);
405 assert(flags & Request::CACHE_BLOCK_ZERO);
406 // This must be a cache block cleaning request
407 data = zero_array;
408 }

--- 16 unchanged lines hidden (view full) ---

425
426 dcache_latency = 0;
427
428 req->taskId(taskId());
429 while(1) {
430 req->setVirt(0, addr, size, flags, dataMasterId(), thread->pcState().instAddr());
431
432 // translate to physical address
427 Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
433 Fault fault = thread->dtb->translateAtomic(req, thread->getTC(), BaseTLB::Write);
428
429 // Now do the access.
430 if (fault == NoFault) {
431 MemCmd cmd = MemCmd::WriteReq; // default
432 bool do_access = true; // flag to suppress cache access
433
434 if (req->isLLSC()) {
435 cmd = MemCmd::StoreCondReq;

--- 36 unchanged lines hidden (view full) ---

472 //If there's a fault or we don't need to access a second cache line,
473 //stop now.
474 if (fault != NoFault || secondAddr <= addr)
475 {
476 if (req->isLockedRMW() && fault == NoFault) {
477 assert(locked);
478 locked = false;
479 }
434
435 // Now do the access.
436 if (fault == NoFault) {
437 MemCmd cmd = MemCmd::WriteReq; // default
438 bool do_access = true; // flag to suppress cache access
439
440 if (req->isLLSC()) {
441 cmd = MemCmd::StoreCondReq;

--- 36 unchanged lines hidden (view full) ---

478 //If there's a fault or we don't need to access a second cache line,
479 //stop now.
480 if (fault != NoFault || secondAddr <= addr)
481 {
482 if (req->isLockedRMW() && fault == NoFault) {
483 assert(locked);
484 locked = false;
485 }
486
487
480 if (fault != NoFault && req->isPrefetch()) {
481 return NoFault;
482 } else {
483 return fault;
484 }
485 }
486
487 /*

--- 10 unchanged lines hidden (view full) ---

498}
499
500
501void
502AtomicSimpleCPU::tick()
503{
504 DPRINTF(SimpleCPU, "Tick\n");
505
488 if (fault != NoFault && req->isPrefetch()) {
489 return NoFault;
490 } else {
491 return fault;
492 }
493 }
494
495 /*

--- 10 unchanged lines hidden (view full) ---

506}
507
508
509void
510AtomicSimpleCPU::tick()
511{
512 DPRINTF(SimpleCPU, "Tick\n");
513
514 // Change thread if multi-threaded
515 swapActiveThread();
516
517 // Set memroy request ids to current thread
518 if (numThreads > 1) {
519 ifetch_req.setThreadContext(_cpuId, curThread);
520 data_read_req.setThreadContext(_cpuId, curThread);
521 data_write_req.setThreadContext(_cpuId, curThread);
522 }
523
524 SimpleExecContext& t_info = *threadInfo[curThread];
525 SimpleThread* thread = t_info.thread;
526
506 Tick latency = 0;
507
508 for (int i = 0; i < width || locked; ++i) {
509 numCycles++;
510 ppCycles->notify(1);
511
512 if (!curStaticInst || !curStaticInst->isDelayedCommit()) {
513 checkForInterrupts();

--- 10 unchanged lines hidden (view full) ---

524
525 TheISA::PCState pcState = thread->pcState();
526
527 bool needToFetch = !isRomMicroPC(pcState.microPC()) &&
528 !curMacroStaticInst;
529 if (needToFetch) {
530 ifetch_req.taskId(taskId());
531 setupFetchRequest(&ifetch_req);
527 Tick latency = 0;
528
529 for (int i = 0; i < width || locked; ++i) {
530 numCycles++;
531 ppCycles->notify(1);
532
533 if (!curStaticInst || !curStaticInst->isDelayedCommit()) {
534 checkForInterrupts();

--- 10 unchanged lines hidden (view full) ---

545
546 TheISA::PCState pcState = thread->pcState();
547
548 bool needToFetch = !isRomMicroPC(pcState.microPC()) &&
549 !curMacroStaticInst;
550 if (needToFetch) {
551 ifetch_req.taskId(taskId());
552 setupFetchRequest(&ifetch_req);
532 fault = thread->itb->translateAtomic(&ifetch_req, tc,
553 fault = thread->itb->translateAtomic(&ifetch_req, thread->getTC(),
533 BaseTLB::Execute);
534 }
535
536 if (fault == NoFault) {
537 Tick icache_latency = 0;
538 bool icache_access = false;
539 dcache_access = false; // assume no dcache access
540

--- 19 unchanged lines hidden (view full) ---

560 // ifetch_req is initialized to read the instruction directly
561 // into the CPU object's inst field.
562 //}
563 }
564
565 preExecute();
566
567 if (curStaticInst) {
554 BaseTLB::Execute);
555 }
556
557 if (fault == NoFault) {
558 Tick icache_latency = 0;
559 bool icache_access = false;
560 dcache_access = false; // assume no dcache access
561

--- 19 unchanged lines hidden (view full) ---

581 // ifetch_req is initialized to read the instruction directly
582 // into the CPU object's inst field.
583 //}
584 }
585
586 preExecute();
587
588 if (curStaticInst) {
568 fault = curStaticInst->execute(this, traceData);
589 fault = curStaticInst->execute(&t_info, traceData);
569
570 // keep an instruction count
571 if (fault == NoFault) {
572 countInst();
573 ppCommit->notify(std::make_pair(thread, curStaticInst));
574 }
575 else if (traceData && !DTRACE(ExecFaulting)) {
576 delete traceData;

--- 19 unchanged lines hidden (view full) ---

596 // the atomic cpu does its accounting in ticks, so
597 // keep counting in ticks but round to the clock
598 // period
599 latency += divCeil(stall_ticks, clockPeriod()) *
600 clockPeriod();
601 }
602
603 }
590
591 // keep an instruction count
592 if (fault == NoFault) {
593 countInst();
594 ppCommit->notify(std::make_pair(thread, curStaticInst));
595 }
596 else if (traceData && !DTRACE(ExecFaulting)) {
597 delete traceData;

--- 19 unchanged lines hidden (view full) ---

617 // the atomic cpu does its accounting in ticks, so
618 // keep counting in ticks but round to the clock
619 // period
620 latency += divCeil(stall_ticks, clockPeriod()) *
621 clockPeriod();
622 }
623
624 }
604 if(fault != NoFault || !stayAtPC)
625 if(fault != NoFault || !t_info.stayAtPC)
605 advancePC(fault);
606 }
607
608 if (tryCompleteDrain())
609 return;
610
611 // instruction takes at least one cycle
612 if (latency < clockPeriod())
613 latency = clockPeriod();
614
615 if (_status != Idle)
626 advancePC(fault);
627 }
628
629 if (tryCompleteDrain())
630 return;
631
632 // instruction takes at least one cycle
633 if (latency < clockPeriod())
634 latency = clockPeriod();
635
636 if (_status != Idle)
616 schedule(tickEvent, curTick() + latency);
637 reschedule(tickEvent, curTick() + latency, true);
617}
618
619void
620AtomicSimpleCPU::regProbePoints()
621{
622 BaseCPU::regProbePoints();
623
624 ppCommit = new ProbePointArg<pair<SimpleThread*, const StaticInstPtr>>

--- 8 unchanged lines hidden (view full) ---

633
634////////////////////////////////////////////////////////////////////////
635//
636// AtomicSimpleCPU Simulation Object
637//
638AtomicSimpleCPU *
639AtomicSimpleCPUParams::create()
640{
638}
639
640void
641AtomicSimpleCPU::regProbePoints()
642{
643 BaseCPU::regProbePoints();
644
645 ppCommit = new ProbePointArg<pair<SimpleThread*, const StaticInstPtr>>

--- 8 unchanged lines hidden (view full) ---

654
655////////////////////////////////////////////////////////////////////////
656//
657// AtomicSimpleCPU Simulation Object
658//
659AtomicSimpleCPU *
660AtomicSimpleCPUParams::create()
661{
641 numThreads = 1;
642 if (!FullSystem && workload.size() != 1)
643 panic("only one workload allowed");
644 return new AtomicSimpleCPU(this);
645}
662 return new AtomicSimpleCPU(this);
663}