timing.cc (10913:38dbdeea7f1f) timing.cc (11147:cc8d6e99cf46)
1/*
2 * Copyright 2014 Google, Inc.
1/*
2 * Copyright 2014 Google, Inc.
3 * Copyright (c) 2010-2013 ARM Limited
3 * Copyright (c) 2010-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

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

62#include "debug/Mwait.hh"
63
64using namespace std;
65using namespace TheISA;
66
67void
68TimingSimpleCPU::init()
69{
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

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

62#include "debug/Mwait.hh"
63
64using namespace std;
65using namespace TheISA;
66
67void
68TimingSimpleCPU::init()
69{
70 BaseCPU::init();
71
72 // Initialise the ThreadContext's memory proxies
73 tcBase()->initMemProxies(tcBase());
74
75 if (FullSystem && !params()->switched_out) {
76 for (int i = 0; i < threadContexts.size(); ++i) {
77 ThreadContext *tc = threadContexts[i];
78 // initialize CPU, including PC
79 TheISA::initCPU(tc, _cpuId);
80 }
81 }
70 BaseSimpleCPU::init();
82}
83
84void
85TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
86{
87 pkt = _pkt;
88 cpu->schedule(this, t);
89}

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

106TimingSimpleCPU::drain()
107{
108 if (switchedOut())
109 return DrainState::Drained;
110
111 if (_status == Idle ||
112 (_status == BaseSimpleCPU::Running && isDrained())) {
113 DPRINTF(Drain, "No need to drain.\n");
71}
72
73void
74TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
75{
76 pkt = _pkt;
77 cpu->schedule(this, t);
78}

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

95TimingSimpleCPU::drain()
96{
97 if (switchedOut())
98 return DrainState::Drained;
99
100 if (_status == Idle ||
101 (_status == BaseSimpleCPU::Running && isDrained())) {
102 DPRINTF(Drain, "No need to drain.\n");
103 activeThreads.clear();
114 return DrainState::Drained;
115 } else {
104 return DrainState::Drained;
105 } else {
116 DPRINTF(Drain, "Requesting drain: %s\n", pcState());
106 DPRINTF(Drain, "Requesting drain.\n");
117
118 // The fetch event can become descheduled if a drain didn't
119 // succeed on the first attempt. We need to reschedule it if
120 // the CPU is waiting for a microcode routine to complete.
121 if (_status == BaseSimpleCPU::Running && !fetchEvent.scheduled())
122 schedule(fetchEvent, clockEdge());
123
124 return DrainState::Draining;

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

131 assert(!fetchEvent.scheduled());
132 if (switchedOut())
133 return;
134
135 DPRINTF(SimpleCPU, "Resume\n");
136 verifyMemoryMode();
137
138 assert(!threadContexts.empty());
107
108 // The fetch event can become descheduled if a drain didn't
109 // succeed on the first attempt. We need to reschedule it if
110 // the CPU is waiting for a microcode routine to complete.
111 if (_status == BaseSimpleCPU::Running && !fetchEvent.scheduled())
112 schedule(fetchEvent, clockEdge());
113
114 return DrainState::Draining;

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

121 assert(!fetchEvent.scheduled());
122 if (switchedOut())
123 return;
124
125 DPRINTF(SimpleCPU, "Resume\n");
126 verifyMemoryMode();
127
128 assert(!threadContexts.empty());
139 if (threadContexts.size() > 1)
140 fatal("The timing CPU only supports one thread.\n");
141
129
142 if (thread->status() == ThreadContext::Active) {
143 schedule(fetchEvent, nextCycle());
144 _status = BaseSimpleCPU::Running;
145 notIdleFraction = 1;
146 } else {
147 _status = BaseSimpleCPU::Idle;
148 notIdleFraction = 0;
130 _status = BaseSimpleCPU::Idle;
131
132 for (ThreadID tid = 0; tid < numThreads; tid++) {
133 if (threadInfo[tid]->thread->status() == ThreadContext::Active) {
134 threadInfo[tid]->notIdleFraction = 1;
135
136 activeThreads.push_back(tid);
137
138 _status = BaseSimpleCPU::Running;
139
140 // Fetch if any threads active
141 if (!fetchEvent.scheduled()) {
142 schedule(fetchEvent, nextCycle());
143 }
144 } else {
145 threadInfo[tid]->notIdleFraction = 0;
146 }
149 }
147 }
148
149 system->totalNumInsts = 0;
150}
151
152bool
153TimingSimpleCPU::tryCompleteDrain()
154{
155 if (drainState() != DrainState::Draining)
156 return false;
157
150}
151
152bool
153TimingSimpleCPU::tryCompleteDrain()
154{
155 if (drainState() != DrainState::Draining)
156 return false;
157
158 DPRINTF(Drain, "tryCompleteDrain: %s\n", pcState());
158 DPRINTF(Drain, "tryCompleteDrain.\n");
159 if (!isDrained())
160 return false;
161
162 DPRINTF(Drain, "CPU done draining, processing drain event\n");
163 signalDrainDone();
164
165 return true;
166}
167
168void
169TimingSimpleCPU::switchOut()
170{
159 if (!isDrained())
160 return false;
161
162 DPRINTF(Drain, "CPU done draining, processing drain event\n");
163 signalDrainDone();
164
165 return true;
166}
167
168void
169TimingSimpleCPU::switchOut()
170{
171 SimpleExecContext& t_info = *threadInfo[curThread];
172 M5_VAR_USED SimpleThread* thread = t_info.thread;
173
171 BaseSimpleCPU::switchOut();
172
173 assert(!fetchEvent.scheduled());
174 assert(_status == BaseSimpleCPU::Running || _status == Idle);
174 BaseSimpleCPU::switchOut();
175
176 assert(!fetchEvent.scheduled());
177 assert(_status == BaseSimpleCPU::Running || _status == Idle);
175 assert(!stayAtPC);
176 assert(microPC() == 0);
178 assert(!t_info.stayAtPC);
179 assert(thread->microPC() == 0);
177
178 updateCycleCounts();
179}
180
181
182void
183TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
184{

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

196 }
197}
198
199void
200TimingSimpleCPU::activateContext(ThreadID thread_num)
201{
202 DPRINTF(SimpleCPU, "ActivateContext %d\n", thread_num);
203
180
181 updateCycleCounts();
182}
183
184
185void
186TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
187{

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

199 }
200}
201
202void
203TimingSimpleCPU::activateContext(ThreadID thread_num)
204{
205 DPRINTF(SimpleCPU, "ActivateContext %d\n", thread_num);
206
204 assert(thread_num == 0);
205 assert(thread);
207 assert(thread_num < numThreads);
206
208
207 assert(_status == Idle);
209 threadInfo[thread_num]->notIdleFraction = 1;
210 if (_status == BaseSimpleCPU::Idle)
211 _status = BaseSimpleCPU::Running;
208
212
209 notIdleFraction = 1;
210 _status = BaseSimpleCPU::Running;
211
212 // kick things off by initiating the fetch of the next instruction
213 // kick things off by initiating the fetch of the next instruction
213 schedule(fetchEvent, clockEdge(Cycles(0)));
214 if (!fetchEvent.scheduled())
215 schedule(fetchEvent, clockEdge(Cycles(0)));
216
217 if (std::find(activeThreads.begin(), activeThreads.end(), thread_num)
218 == activeThreads.end()) {
219 activeThreads.push_back(thread_num);
220 }
214}
215
216
217void
218TimingSimpleCPU::suspendContext(ThreadID thread_num)
219{
220 DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
221
221}
222
223
224void
225TimingSimpleCPU::suspendContext(ThreadID thread_num)
226{
227 DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
228
222 assert(thread_num == 0);
223 assert(thread);
229 assert(thread_num < numThreads);
230 activeThreads.remove(thread_num);
224
225 if (_status == Idle)
226 return;
227
228 assert(_status == BaseSimpleCPU::Running);
229
231
232 if (_status == Idle)
233 return;
234
235 assert(_status == BaseSimpleCPU::Running);
236
230 // just change status to Idle... if status != Running,
231 // completeInst() will not initiate fetch of next instruction.
237 threadInfo[thread_num]->notIdleFraction = 0;
232
238
233 notIdleFraction = 0;
234 _status = Idle;
239 if (activeThreads.empty()) {
240 _status = Idle;
241
242 if (fetchEvent.scheduled()) {
243 deschedule(fetchEvent);
244 }
245 }
235}
236
237bool
238TimingSimpleCPU::handleReadPacket(PacketPtr pkt)
239{
246}
247
248bool
249TimingSimpleCPU::handleReadPacket(PacketPtr pkt)
250{
251 SimpleExecContext &t_info = *threadInfo[curThread];
252 SimpleThread* thread = t_info.thread;
253
240 RequestPtr req = pkt->req;
241
242 // We're about the issues a locked load, so tell the monitor
243 // to start caring about this address
244 if (pkt->isRead() && pkt->req->isLLSC()) {
245 TheISA::handleLockedRead(thread, pkt->req);
246 }
247 if (req->isMmappedIpr()) {

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

259 }
260 return dcache_pkt == NULL;
261}
262
263void
264TimingSimpleCPU::sendData(RequestPtr req, uint8_t *data, uint64_t *res,
265 bool read)
266{
254 RequestPtr req = pkt->req;
255
256 // We're about the issues a locked load, so tell the monitor
257 // to start caring about this address
258 if (pkt->isRead() && pkt->req->isLLSC()) {
259 TheISA::handleLockedRead(thread, pkt->req);
260 }
261 if (req->isMmappedIpr()) {

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

273 }
274 return dcache_pkt == NULL;
275}
276
277void
278TimingSimpleCPU::sendData(RequestPtr req, uint8_t *data, uint64_t *res,
279 bool read)
280{
281 SimpleExecContext &t_info = *threadInfo[curThread];
282 SimpleThread* thread = t_info.thread;
283
267 PacketPtr pkt = buildPacket(req, read);
268 pkt->dataDynamic<uint8_t>(data);
269 if (req->getFlags().isSet(Request::NO_ACCESS)) {
270 assert(!dcache_pkt);
271 pkt->makeResponse();
272 completeDataAccess(pkt);
273 } else if (read) {
274 handleReadPacket(pkt);

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

384 pkt1->senderState = new SplitFragmentSenderState(pkt, 0);
385 pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
386}
387
388Fault
389TimingSimpleCPU::readMem(Addr addr, uint8_t *data,
390 unsigned size, unsigned flags)
391{
284 PacketPtr pkt = buildPacket(req, read);
285 pkt->dataDynamic<uint8_t>(data);
286 if (req->getFlags().isSet(Request::NO_ACCESS)) {
287 assert(!dcache_pkt);
288 pkt->makeResponse();
289 completeDataAccess(pkt);
290 } else if (read) {
291 handleReadPacket(pkt);

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

401 pkt1->senderState = new SplitFragmentSenderState(pkt, 0);
402 pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
403}
404
405Fault
406TimingSimpleCPU::readMem(Addr addr, uint8_t *data,
407 unsigned size, unsigned flags)
408{
409 SimpleExecContext &t_info = *threadInfo[curThread];
410 SimpleThread* thread = t_info.thread;
411
392 Fault fault;
393 const int asid = 0;
412 Fault fault;
413 const int asid = 0;
394 const ThreadID tid = 0;
414 const ThreadID tid = curThread;
395 const Addr pc = thread->instAddr();
396 unsigned block_size = cacheLineSize();
397 BaseTLB::Mode mode = BaseTLB::Read;
398
399 if (traceData)
400 traceData->setMem(addr, size, flags);
401
402 RequestPtr req = new Request(asid, addr, size,
415 const Addr pc = thread->instAddr();
416 unsigned block_size = cacheLineSize();
417 BaseTLB::Mode mode = BaseTLB::Read;
418
419 if (traceData)
420 traceData->setMem(addr, size, flags);
421
422 RequestPtr req = new Request(asid, addr, size,
403 flags, dataMasterId(), pc, _cpuId, tid);
423 flags, dataMasterId(), pc,
424 thread->contextId(), tid);
404
405 req->taskId(taskId());
406
407 Addr split_addr = roundDown(addr + size - 1, block_size);
408 assert(split_addr <= addr || split_addr - addr < block_size);
409
410 _status = DTBWaitResponse;
411 if (split_addr > addr) {

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

416 WholeTranslationState *state =
417 new WholeTranslationState(req, req1, req2, new uint8_t[size],
418 NULL, mode);
419 DataTranslation<TimingSimpleCPU *> *trans1 =
420 new DataTranslation<TimingSimpleCPU *>(this, state, 0);
421 DataTranslation<TimingSimpleCPU *> *trans2 =
422 new DataTranslation<TimingSimpleCPU *>(this, state, 1);
423
425
426 req->taskId(taskId());
427
428 Addr split_addr = roundDown(addr + size - 1, block_size);
429 assert(split_addr <= addr || split_addr - addr < block_size);
430
431 _status = DTBWaitResponse;
432 if (split_addr > addr) {

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

437 WholeTranslationState *state =
438 new WholeTranslationState(req, req1, req2, new uint8_t[size],
439 NULL, mode);
440 DataTranslation<TimingSimpleCPU *> *trans1 =
441 new DataTranslation<TimingSimpleCPU *>(this, state, 0);
442 DataTranslation<TimingSimpleCPU *> *trans2 =
443 new DataTranslation<TimingSimpleCPU *>(this, state, 1);
444
424 thread->dtb->translateTiming(req1, tc, trans1, mode);
425 thread->dtb->translateTiming(req2, tc, trans2, mode);
445 thread->dtb->translateTiming(req1, thread->getTC(), trans1, mode);
446 thread->dtb->translateTiming(req2, thread->getTC(), trans2, mode);
426 } else {
427 WholeTranslationState *state =
428 new WholeTranslationState(req, new uint8_t[size], NULL, mode);
429 DataTranslation<TimingSimpleCPU *> *translation
430 = new DataTranslation<TimingSimpleCPU *>(this, state);
447 } else {
448 WholeTranslationState *state =
449 new WholeTranslationState(req, new uint8_t[size], NULL, mode);
450 DataTranslation<TimingSimpleCPU *> *translation
451 = new DataTranslation<TimingSimpleCPU *>(this, state);
431 thread->dtb->translateTiming(req, tc, translation, mode);
452 thread->dtb->translateTiming(req, thread->getTC(), translation, mode);
432 }
433
434 return NoFault;
435}
436
437bool
438TimingSimpleCPU::handleWritePacket()
439{
453 }
454
455 return NoFault;
456}
457
458bool
459TimingSimpleCPU::handleWritePacket()
460{
461 SimpleExecContext &t_info = *threadInfo[curThread];
462 SimpleThread* thread = t_info.thread;
463
440 RequestPtr req = dcache_pkt->req;
441 if (req->isMmappedIpr()) {
442 Cycles delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt);
443 new IprEvent(dcache_pkt, this, clockEdge(delay));
444 _status = DcacheWaitResponse;
445 dcache_pkt = NULL;
446 } else if (!dcachePort.sendTimingReq(dcache_pkt)) {
447 _status = DcacheRetry;

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

452 }
453 return dcache_pkt == NULL;
454}
455
456Fault
457TimingSimpleCPU::writeMem(uint8_t *data, unsigned size,
458 Addr addr, unsigned flags, uint64_t *res)
459{
464 RequestPtr req = dcache_pkt->req;
465 if (req->isMmappedIpr()) {
466 Cycles delay = TheISA::handleIprWrite(thread->getTC(), dcache_pkt);
467 new IprEvent(dcache_pkt, this, clockEdge(delay));
468 _status = DcacheWaitResponse;
469 dcache_pkt = NULL;
470 } else if (!dcachePort.sendTimingReq(dcache_pkt)) {
471 _status = DcacheRetry;

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

476 }
477 return dcache_pkt == NULL;
478}
479
480Fault
481TimingSimpleCPU::writeMem(uint8_t *data, unsigned size,
482 Addr addr, unsigned flags, uint64_t *res)
483{
484 SimpleExecContext &t_info = *threadInfo[curThread];
485 SimpleThread* thread = t_info.thread;
486
460 uint8_t *newData = new uint8_t[size];
461 const int asid = 0;
487 uint8_t *newData = new uint8_t[size];
488 const int asid = 0;
462 const ThreadID tid = 0;
489 const ThreadID tid = curThread;
463 const Addr pc = thread->instAddr();
464 unsigned block_size = cacheLineSize();
465 BaseTLB::Mode mode = BaseTLB::Write;
466
467 if (data == NULL) {
468 assert(flags & Request::CACHE_BLOCK_ZERO);
469 // This must be a cache block cleaning request
470 memset(newData, 0, size);
471 } else {
472 memcpy(newData, data, size);
473 }
474
475 if (traceData)
476 traceData->setMem(addr, size, flags);
477
478 RequestPtr req = new Request(asid, addr, size,
490 const Addr pc = thread->instAddr();
491 unsigned block_size = cacheLineSize();
492 BaseTLB::Mode mode = BaseTLB::Write;
493
494 if (data == NULL) {
495 assert(flags & Request::CACHE_BLOCK_ZERO);
496 // This must be a cache block cleaning request
497 memset(newData, 0, size);
498 } else {
499 memcpy(newData, data, size);
500 }
501
502 if (traceData)
503 traceData->setMem(addr, size, flags);
504
505 RequestPtr req = new Request(asid, addr, size,
479 flags, dataMasterId(), pc, _cpuId, tid);
506 flags, dataMasterId(), pc,
507 thread->contextId(), tid);
480
481 req->taskId(taskId());
482
483 Addr split_addr = roundDown(addr + size - 1, block_size);
484 assert(split_addr <= addr || split_addr - addr < block_size);
485
486 _status = DTBWaitResponse;
487 if (split_addr > addr) {
488 RequestPtr req1, req2;
489 assert(!req->isLLSC() && !req->isSwap());
490 req->splitOnVaddr(split_addr, req1, req2);
491
492 WholeTranslationState *state =
493 new WholeTranslationState(req, req1, req2, newData, res, mode);
494 DataTranslation<TimingSimpleCPU *> *trans1 =
495 new DataTranslation<TimingSimpleCPU *>(this, state, 0);
496 DataTranslation<TimingSimpleCPU *> *trans2 =
497 new DataTranslation<TimingSimpleCPU *>(this, state, 1);
498
508
509 req->taskId(taskId());
510
511 Addr split_addr = roundDown(addr + size - 1, block_size);
512 assert(split_addr <= addr || split_addr - addr < block_size);
513
514 _status = DTBWaitResponse;
515 if (split_addr > addr) {
516 RequestPtr req1, req2;
517 assert(!req->isLLSC() && !req->isSwap());
518 req->splitOnVaddr(split_addr, req1, req2);
519
520 WholeTranslationState *state =
521 new WholeTranslationState(req, req1, req2, newData, res, mode);
522 DataTranslation<TimingSimpleCPU *> *trans1 =
523 new DataTranslation<TimingSimpleCPU *>(this, state, 0);
524 DataTranslation<TimingSimpleCPU *> *trans2 =
525 new DataTranslation<TimingSimpleCPU *>(this, state, 1);
526
499 thread->dtb->translateTiming(req1, tc, trans1, mode);
500 thread->dtb->translateTiming(req2, tc, trans2, mode);
527 thread->dtb->translateTiming(req1, thread->getTC(), trans1, mode);
528 thread->dtb->translateTiming(req2, thread->getTC(), trans2, mode);
501 } else {
502 WholeTranslationState *state =
503 new WholeTranslationState(req, newData, res, mode);
504 DataTranslation<TimingSimpleCPU *> *translation =
505 new DataTranslation<TimingSimpleCPU *>(this, state);
529 } else {
530 WholeTranslationState *state =
531 new WholeTranslationState(req, newData, res, mode);
532 DataTranslation<TimingSimpleCPU *> *translation =
533 new DataTranslation<TimingSimpleCPU *>(this, state);
506 thread->dtb->translateTiming(req, tc, translation, mode);
534 thread->dtb->translateTiming(req, thread->getTC(), translation, mode);
507 }
508
509 // Translation faults will be returned via finishTranslation()
510 return NoFault;
511}
512
513
514void

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

535
536 delete state;
537}
538
539
540void
541TimingSimpleCPU::fetch()
542{
535 }
536
537 // Translation faults will be returned via finishTranslation()
538 return NoFault;
539}
540
541
542void

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

563
564 delete state;
565}
566
567
568void
569TimingSimpleCPU::fetch()
570{
571 // Change thread if multi-threaded
572 swapActiveThread();
573
574 SimpleExecContext &t_info = *threadInfo[curThread];
575 SimpleThread* thread = t_info.thread;
576
543 DPRINTF(SimpleCPU, "Fetch\n");
544
545 if (!curStaticInst || !curStaticInst->isDelayedCommit()) {
546 checkForInterrupts();
547 checkPcEventQueue();
548 }
549
550 // We must have just got suspended by a PC event
551 if (_status == Idle)
552 return;
553
554 TheISA::PCState pcState = thread->pcState();
577 DPRINTF(SimpleCPU, "Fetch\n");
578
579 if (!curStaticInst || !curStaticInst->isDelayedCommit()) {
580 checkForInterrupts();
581 checkPcEventQueue();
582 }
583
584 // We must have just got suspended by a PC event
585 if (_status == Idle)
586 return;
587
588 TheISA::PCState pcState = thread->pcState();
555 bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst;
589 bool needToFetch = !isRomMicroPC(pcState.microPC()) &&
590 !curMacroStaticInst;
556
557 if (needToFetch) {
558 _status = BaseSimpleCPU::Running;
559 Request *ifetch_req = new Request();
560 ifetch_req->taskId(taskId());
591
592 if (needToFetch) {
593 _status = BaseSimpleCPU::Running;
594 Request *ifetch_req = new Request();
595 ifetch_req->taskId(taskId());
561 ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
596 ifetch_req->setThreadContext(thread->contextId(), curThread);
562 setupFetchRequest(ifetch_req);
563 DPRINTF(SimpleCPU, "Translating address %#x\n", ifetch_req->getVaddr());
597 setupFetchRequest(ifetch_req);
598 DPRINTF(SimpleCPU, "Translating address %#x\n", ifetch_req->getVaddr());
564 thread->itb->translateTiming(ifetch_req, tc, &fetchTranslation,
565 BaseTLB::Execute);
599 thread->itb->translateTiming(ifetch_req, thread->getTC(),
600 &fetchTranslation, BaseTLB::Execute);
566 } else {
567 _status = IcacheWaitResponse;
568 completeIfetch(NULL);
569
570 updateCycleCounts();
571 }
572}
573

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

602
603 updateCycleCounts();
604}
605
606
607void
608TimingSimpleCPU::advanceInst(const Fault &fault)
609{
601 } else {
602 _status = IcacheWaitResponse;
603 completeIfetch(NULL);
604
605 updateCycleCounts();
606 }
607}
608

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

637
638 updateCycleCounts();
639}
640
641
642void
643TimingSimpleCPU::advanceInst(const Fault &fault)
644{
645 SimpleExecContext &t_info = *threadInfo[curThread];
646
610 if (_status == Faulting)
611 return;
612
613 if (fault != NoFault) {
614 advancePC(fault);
615 DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n");
616 reschedule(fetchEvent, clockEdge(), true);
617 _status = Faulting;
618 return;
619 }
620
621
647 if (_status == Faulting)
648 return;
649
650 if (fault != NoFault) {
651 advancePC(fault);
652 DPRINTF(SimpleCPU, "Fault occured, scheduling fetch event\n");
653 reschedule(fetchEvent, clockEdge(), true);
654 _status = Faulting;
655 return;
656 }
657
658
622 if (!stayAtPC)
659 if (!t_info.stayAtPC)
623 advancePC(fault);
624
625 if (tryCompleteDrain())
626 return;
627
628 if (_status == BaseSimpleCPU::Running) {
629 // kick off fetch of next instruction... callback from icache
630 // response will cause that instruction to be executed,
631 // keeping the CPU running.
632 fetch();
633 }
634}
635
636
637void
638TimingSimpleCPU::completeIfetch(PacketPtr pkt)
639{
660 advancePC(fault);
661
662 if (tryCompleteDrain())
663 return;
664
665 if (_status == BaseSimpleCPU::Running) {
666 // kick off fetch of next instruction... callback from icache
667 // response will cause that instruction to be executed,
668 // keeping the CPU running.
669 fetch();
670 }
671}
672
673
674void
675TimingSimpleCPU::completeIfetch(PacketPtr pkt)
676{
677 SimpleExecContext& t_info = *threadInfo[curThread];
678
640 DPRINTF(SimpleCPU, "Complete ICache Fetch for addr %#x\n", pkt ?
641 pkt->getAddr() : 0);
642
643 // received a response from the icache: execute the received
644 // instruction
645 assert(!pkt || !pkt->isError());
646 assert(_status == IcacheWaitResponse);
647
648 _status = BaseSimpleCPU::Running;
649
650 updateCycleCounts();
651
652 if (pkt)
653 pkt->req->setAccessLatency();
654
655
656 preExecute();
657 if (curStaticInst && curStaticInst->isMemRef()) {
658 // load or store: just send to dcache
679 DPRINTF(SimpleCPU, "Complete ICache Fetch for addr %#x\n", pkt ?
680 pkt->getAddr() : 0);
681
682 // received a response from the icache: execute the received
683 // instruction
684 assert(!pkt || !pkt->isError());
685 assert(_status == IcacheWaitResponse);
686
687 _status = BaseSimpleCPU::Running;
688
689 updateCycleCounts();
690
691 if (pkt)
692 pkt->req->setAccessLatency();
693
694
695 preExecute();
696 if (curStaticInst && curStaticInst->isMemRef()) {
697 // load or store: just send to dcache
659 Fault fault = curStaticInst->initiateAcc(this, traceData);
698 Fault fault = curStaticInst->initiateAcc(&t_info, traceData);
660
661 // If we're not running now the instruction will complete in a dcache
662 // response callback or the instruction faulted and has started an
663 // ifetch
664 if (_status == BaseSimpleCPU::Running) {
665 if (fault != NoFault && traceData) {
666 // If there was a fault, we shouldn't trace this instruction.
667 delete traceData;

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

672 // @todo remove me after debugging with legion done
673 if (curStaticInst && (!curStaticInst->isMicroop() ||
674 curStaticInst->isFirstMicroop()))
675 instCnt++;
676 advanceInst(fault);
677 }
678 } else if (curStaticInst) {
679 // non-memory instruction: execute completely now
699
700 // If we're not running now the instruction will complete in a dcache
701 // response callback or the instruction faulted and has started an
702 // ifetch
703 if (_status == BaseSimpleCPU::Running) {
704 if (fault != NoFault && traceData) {
705 // If there was a fault, we shouldn't trace this instruction.
706 delete traceData;

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

711 // @todo remove me after debugging with legion done
712 if (curStaticInst && (!curStaticInst->isMicroop() ||
713 curStaticInst->isFirstMicroop()))
714 instCnt++;
715 advanceInst(fault);
716 }
717 } else if (curStaticInst) {
718 // non-memory instruction: execute completely now
680 Fault fault = curStaticInst->execute(this, traceData);
719 Fault fault = curStaticInst->execute(&t_info, traceData);
681
682 // keep an instruction count
683 if (fault == NoFault)
684 countInst();
685 else if (traceData && !DTRACE(ExecFaulting)) {
686 delete traceData;
687 traceData = NULL;
688 }
689
690 postExecute();
691 // @todo remove me after debugging with legion done
692 if (curStaticInst && (!curStaticInst->isMicroop() ||
720
721 // keep an instruction count
722 if (fault == NoFault)
723 countInst();
724 else if (traceData && !DTRACE(ExecFaulting)) {
725 delete traceData;
726 traceData = NULL;
727 }
728
729 postExecute();
730 // @todo remove me after debugging with legion done
731 if (curStaticInst && (!curStaticInst->isMicroop() ||
693 curStaticInst->isFirstMicroop()))
732 curStaticInst->isFirstMicroop()))
694 instCnt++;
695 advanceInst(fault);
696 } else {
697 advanceInst(NoFault);
698 }
699
700 if (pkt) {
701 delete pkt->req;

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

771 delete main_send_state;
772 big_pkt->senderState = NULL;
773 pkt = big_pkt;
774 }
775 }
776
777 _status = BaseSimpleCPU::Running;
778
733 instCnt++;
734 advanceInst(fault);
735 } else {
736 advanceInst(NoFault);
737 }
738
739 if (pkt) {
740 delete pkt->req;

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

810 delete main_send_state;
811 big_pkt->senderState = NULL;
812 pkt = big_pkt;
813 }
814 }
815
816 _status = BaseSimpleCPU::Running;
817
779 Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
818 Fault fault = curStaticInst->completeAcc(pkt, threadInfo[curThread],
819 traceData);
780
781 // keep an instruction count
782 if (fault == NoFault)
783 countInst();
784 else if (traceData) {
785 // If there was a fault, we shouldn't trace this instruction.
786 delete traceData;
787 traceData = NULL;

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

805
806 previousCycle = curCycle();
807}
808
809void
810TimingSimpleCPU::DcachePort::recvTimingSnoopReq(PacketPtr pkt)
811{
812 // X86 ISA: Snooping an invalidation for monitor/mwait
820
821 // keep an instruction count
822 if (fault == NoFault)
823 countInst();
824 else if (traceData) {
825 // If there was a fault, we shouldn't trace this instruction.
826 delete traceData;
827 traceData = NULL;

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

845
846 previousCycle = curCycle();
847}
848
849void
850TimingSimpleCPU::DcachePort::recvTimingSnoopReq(PacketPtr pkt)
851{
852 // X86 ISA: Snooping an invalidation for monitor/mwait
813 if(cpu->getAddrMonitor()->doMonitor(pkt)) {
853 if(cpu->getCpuAddrMonitor()->doMonitor(pkt)) {
814 cpu->wakeup();
815 }
854 cpu->wakeup();
855 }
816 TheISA::handleLockedSnoop(cpu->thread, pkt, cacheBlockMask);
856
857 for (auto &t_info : cpu->threadInfo) {
858 TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
859 }
817}
818
819void
820TimingSimpleCPU::DcachePort::recvFunctionalSnoop(PacketPtr pkt)
821{
822 // X86 ISA: Snooping an invalidation for monitor/mwait
860}
861
862void
863TimingSimpleCPU::DcachePort::recvFunctionalSnoop(PacketPtr pkt)
864{
865 // X86 ISA: Snooping an invalidation for monitor/mwait
823 if(cpu->getAddrMonitor()->doMonitor(pkt)) {
866 if(cpu->getCpuAddrMonitor()->doMonitor(pkt)) {
824 cpu->wakeup();
825 }
826}
827
828bool
829TimingSimpleCPU::DcachePort::recvTimingResp(PacketPtr pkt)
830{
831 DPRINTF(SimpleCPU, "Received load/store response %#x\n", pkt->getAddr());

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

925
926////////////////////////////////////////////////////////////////////////
927//
928// TimingSimpleCPU Simulation Object
929//
930TimingSimpleCPU *
931TimingSimpleCPUParams::create()
932{
867 cpu->wakeup();
868 }
869}
870
871bool
872TimingSimpleCPU::DcachePort::recvTimingResp(PacketPtr pkt)
873{
874 DPRINTF(SimpleCPU, "Received load/store response %#x\n", pkt->getAddr());

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

968
969////////////////////////////////////////////////////////////////////////
970//
971// TimingSimpleCPU Simulation Object
972//
973TimingSimpleCPU *
974TimingSimpleCPUParams::create()
975{
933 numThreads = 1;
934 if (!FullSystem && workload.size() != 1)
935 panic("only one workload allowed");
936 return new TimingSimpleCPU(this);
937}
976 return new TimingSimpleCPU(this);
977}