Merge ktlim@zizzer:/bk/newmem
[gem5.git] / src / cpu / ozone / cpu_impl.hh
1 /*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 //#include <cstdio>
30 //#include <cstdlib>
31
32 #include "arch/isa_traits.hh" // For MachInst
33 #include "base/trace.hh"
34 #include "config/full_system.hh"
35 #include "cpu/base.hh"
36 #include "cpu/checker/exec_context.hh"
37 #include "cpu/exec_context.hh"
38 #include "cpu/exetrace.hh"
39 #include "cpu/ozone/cpu.hh"
40 #include "cpu/quiesce_event.hh"
41 #include "cpu/static_inst.hh"
42 //#include "mem/base_mem.hh"
43 #include "mem/mem_interface.hh"
44 #include "sim/sim_object.hh"
45 #include "sim/stats.hh"
46
47 #if FULL_SYSTEM
48 #include "arch/faults.hh"
49 #include "arch/alpha/osfpal.hh"
50 #include "arch/alpha/tlb.hh"
51 #include "arch/vtophys.hh"
52 #include "base/callback.hh"
53 //#include "base/remote_gdb.hh"
54 #include "cpu/profile.hh"
55 #include "kern/kernel_stats.hh"
56 #include "mem/functional/memory_control.hh"
57 #include "mem/functional/physical.hh"
58 #include "sim/faults.hh"
59 #include "sim/sim_events.hh"
60 #include "sim/sim_exit.hh"
61 #include "sim/system.hh"
62 #else // !FULL_SYSTEM
63 #include "mem/functional/functional.hh"
64 #include "sim/process.hh"
65 #endif // FULL_SYSTEM
66
67 using namespace TheISA;
68
69 template <class Impl>
70 template<typename T>
71 void
72 OzoneCPU<Impl>::trace_data(T data) {
73 if (traceData) {
74 traceData->setData(data);
75 }
76 }
77
78 template <class Impl>
79 OzoneCPU<Impl>::TickEvent::TickEvent(OzoneCPU *c, int w)
80 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w)
81 {
82 }
83
84 template <class Impl>
85 void
86 OzoneCPU<Impl>::TickEvent::process()
87 {
88 cpu->tick();
89 }
90
91 template <class Impl>
92 const char *
93 OzoneCPU<Impl>::TickEvent::description()
94 {
95 return "OzoneCPU tick event";
96 }
97
98 template <class Impl>
99 OzoneCPU<Impl>::OzoneCPU(Params *p)
100 #if FULL_SYSTEM
101 : BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width),
102 mem(p->mem),
103 #else
104 : BaseCPU(p), thread(this, 0, p->workload[0], 0), tickEvent(this, p->width),
105 mem(p->workload[0]->getMemory()),
106 #endif
107 comm(5, 5)
108 {
109 frontEnd = new FrontEnd(p);
110 backEnd = new BackEnd(p);
111
112 _status = Idle;
113
114 if (p->checker) {
115 BaseCPU *temp_checker = p->checker;
116 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
117 checker->setMemory(mem);
118 #if FULL_SYSTEM
119 checker->setSystem(p->system);
120 #endif
121 checkerXC = new CheckerExecContext<OzoneXC>(&ozoneXC, checker);
122 thread.xcProxy = checkerXC;
123 xcProxy = checkerXC;
124 } else {
125 checker = NULL;
126 thread.xcProxy = &ozoneXC;
127 xcProxy = &ozoneXC;
128 }
129
130 ozoneXC.cpu = this;
131 ozoneXC.thread = &thread;
132
133 thread.inSyscall = false;
134
135 thread.setStatus(ExecContext::Suspended);
136 #if FULL_SYSTEM
137 /***** All thread state stuff *****/
138 thread.cpu = this;
139 thread.tid = 0;
140 thread.mem = p->mem;
141
142 thread.quiesceEvent = new EndQuiesceEvent(xcProxy);
143
144 system = p->system;
145 itb = p->itb;
146 dtb = p->dtb;
147 memctrl = p->system->memctrl;
148 physmem = p->system->physmem;
149
150 if (p->profile) {
151 thread.profile = new FunctionProfile(p->system->kernelSymtab);
152 // @todo: This might be better as an ExecContext instead of OzoneXC
153 Callback *cb =
154 new MakeCallback<OzoneXC,
155 &OzoneXC::dumpFuncProfile>(&ozoneXC);
156 registerExitCallback(cb);
157 }
158
159 // let's fill with a dummy node for now so we don't get a segfault
160 // on the first cycle when there's no node available.
161 static ProfileNode dummyNode;
162 thread.profileNode = &dummyNode;
163 thread.profilePC = 3;
164 #else
165 thread.cpu = this;
166 thread.tid = 0;
167 thread.process = p->workload[0];
168 thread.asid = 0;
169 #endif // !FULL_SYSTEM
170
171 numInst = 0;
172 startNumInst = 0;
173
174 execContexts.push_back(xcProxy);
175
176 frontEnd->setCPU(this);
177 backEnd->setCPU(this);
178
179 frontEnd->setXC(xcProxy);
180 backEnd->setXC(xcProxy);
181
182 frontEnd->setThreadState(&thread);
183 backEnd->setThreadState(&thread);
184
185 frontEnd->setCommBuffer(&comm);
186 backEnd->setCommBuffer(&comm);
187
188 frontEnd->setBackEnd(backEnd);
189 backEnd->setFrontEnd(frontEnd);
190
191 decoupledFrontEnd = p->decoupledFrontEnd;
192
193 globalSeqNum = 1;
194
195 checkInterrupts = false;
196
197 for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
198 thread.renameTable[i] = new DynInst(this);
199 thread.renameTable[i]->setResultReady();
200 }
201
202 frontEnd->renameTable.copyFrom(thread.renameTable);
203 backEnd->renameTable.copyFrom(thread.renameTable);
204
205 #if !FULL_SYSTEM
206 // pTable = p->pTable;
207 #endif
208
209 lockFlag = 0;
210
211 DPRINTF(OzoneCPU, "OzoneCPU: Created Ozone cpu object.\n");
212 }
213
214 template <class Impl>
215 OzoneCPU<Impl>::~OzoneCPU()
216 {
217 }
218
219 template <class Impl>
220 void
221 OzoneCPU<Impl>::switchOut(Sampler *_sampler)
222 {
223 sampler = _sampler;
224 switchCount = 0;
225 // Front end needs state from back end, so switch out the back end first.
226 backEnd->switchOut();
227 frontEnd->switchOut();
228 }
229
230 template <class Impl>
231 void
232 OzoneCPU<Impl>::signalSwitched()
233 {
234 if (++switchCount == 2) {
235 backEnd->doSwitchOut();
236 frontEnd->doSwitchOut();
237 if (checker)
238 checker->switchOut(sampler);
239 _status = SwitchedOut;
240 if (tickEvent.scheduled())
241 tickEvent.squash();
242 sampler->signalSwitched();
243 }
244 assert(switchCount <= 2);
245 }
246
247 template <class Impl>
248 void
249 OzoneCPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
250 {
251 BaseCPU::takeOverFrom(oldCPU);
252
253 backEnd->takeOverFrom();
254 frontEnd->takeOverFrom();
255 assert(!tickEvent.scheduled());
256
257 // @todo: Fix hardcoded number
258 // Clear out any old information in time buffer.
259 for (int i = 0; i < 6; ++i) {
260 comm.advance();
261 }
262
263 // if any of this CPU's ExecContexts are active, mark the CPU as
264 // running and schedule its tick event.
265 for (int i = 0; i < execContexts.size(); ++i) {
266 ExecContext *xc = execContexts[i];
267 if (xc->status() == ExecContext::Active &&
268 _status != Running) {
269 _status = Running;
270 tickEvent.schedule(curTick);
271 }
272 }
273 // Nothing running, change status to reflect that we're no longer
274 // switched out.
275 if (_status == SwitchedOut) {
276 _status = Idle;
277 }
278 }
279
280 template <class Impl>
281 void
282 OzoneCPU<Impl>::activateContext(int thread_num, int delay)
283 {
284 // Eventually change this in SMT.
285 assert(thread_num == 0);
286
287 assert(_status == Idle);
288 notIdleFraction++;
289 scheduleTickEvent(delay);
290 _status = Running;
291 thread._status = ExecContext::Active;
292 frontEnd->wakeFromQuiesce();
293 }
294
295 template <class Impl>
296 void
297 OzoneCPU<Impl>::suspendContext(int thread_num)
298 {
299 // Eventually change this in SMT.
300 assert(thread_num == 0);
301 // @todo: Figure out how to initially set the status properly so
302 // this is running.
303 // assert(_status == Running);
304 notIdleFraction--;
305 unscheduleTickEvent();
306 _status = Idle;
307 }
308
309 template <class Impl>
310 void
311 OzoneCPU<Impl>::deallocateContext(int thread_num)
312 {
313 // for now, these are equivalent
314 suspendContext(thread_num);
315 }
316
317 template <class Impl>
318 void
319 OzoneCPU<Impl>::haltContext(int thread_num)
320 {
321 // for now, these are equivalent
322 suspendContext(thread_num);
323 }
324
325 template <class Impl>
326 void
327 OzoneCPU<Impl>::regStats()
328 {
329 using namespace Stats;
330
331 BaseCPU::regStats();
332
333 thread.numInsts
334 .name(name() + ".num_insts")
335 .desc("Number of instructions executed")
336 ;
337
338 thread.numMemRefs
339 .name(name() + ".num_refs")
340 .desc("Number of memory references")
341 ;
342
343 notIdleFraction
344 .name(name() + ".not_idle_fraction")
345 .desc("Percentage of non-idle cycles")
346 ;
347
348 idleFraction
349 .name(name() + ".idle_fraction")
350 .desc("Percentage of idle cycles")
351 ;
352
353 quiesceCycles
354 .name(name() + ".quiesce_cycles")
355 .desc("Number of cycles spent in quiesce")
356 ;
357
358 idleFraction = constant(1.0) - notIdleFraction;
359
360 frontEnd->regStats();
361 backEnd->regStats();
362 }
363
364 template <class Impl>
365 void
366 OzoneCPU<Impl>::resetStats()
367 {
368 startNumInst = numInst;
369 notIdleFraction = (_status != Idle);
370 }
371
372 template <class Impl>
373 void
374 OzoneCPU<Impl>::init()
375 {
376 BaseCPU::init();
377
378 // Mark this as in syscall so it won't need to squash
379 thread.inSyscall = true;
380 #if FULL_SYSTEM
381 for (int i = 0; i < execContexts.size(); ++i) {
382 ExecContext *xc = execContexts[i];
383
384 // initialize CPU, including PC
385 TheISA::initCPU(xc, xc->readCpuId());
386 }
387 #endif
388 frontEnd->renameTable.copyFrom(thread.renameTable);
389 backEnd->renameTable.copyFrom(thread.renameTable);
390
391 thread.inSyscall = false;
392 }
393
394 template <class Impl>
395 void
396 OzoneCPU<Impl>::serialize(std::ostream &os)
397 {
398 BaseCPU::serialize(os);
399 SERIALIZE_ENUM(_status);
400 nameOut(os, csprintf("%s.xc", name()));
401 ozoneXC.serialize(os);
402 nameOut(os, csprintf("%s.tickEvent", name()));
403 tickEvent.serialize(os);
404 }
405
406 template <class Impl>
407 void
408 OzoneCPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
409 {
410 BaseCPU::unserialize(cp, section);
411 UNSERIALIZE_ENUM(_status);
412 ozoneXC.unserialize(cp, csprintf("%s.xc", section));
413 tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
414 }
415
416 template <class Impl>
417 Fault
418 OzoneCPU<Impl>::copySrcTranslate(Addr src)
419 {
420 panic("Copy not implemented!\n");
421 return NoFault;
422 #if 0
423 static bool no_warn = true;
424 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
425 // Only support block sizes of 64 atm.
426 assert(blk_size == 64);
427 int offset = src & (blk_size - 1);
428
429 // Make sure block doesn't span page
430 if (no_warn &&
431 (src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) &&
432 (src >> 40) != 0xfffffc) {
433 warn("Copied block source spans pages %x.", src);
434 no_warn = false;
435 }
436
437 memReq->reset(src & ~(blk_size - 1), blk_size);
438
439 // translate to physical address
440 Fault fault = xc->translateDataReadReq(memReq);
441
442 assert(fault != Alignment_Fault);
443
444 if (fault == NoFault) {
445 xc->copySrcAddr = src;
446 xc->copySrcPhysAddr = memReq->paddr + offset;
447 } else {
448 xc->copySrcAddr = 0;
449 xc->copySrcPhysAddr = 0;
450 }
451 return fault;
452 #endif
453 }
454
455 template <class Impl>
456 Fault
457 OzoneCPU<Impl>::copy(Addr dest)
458 {
459 panic("Copy not implemented!\n");
460 return NoFault;
461 #if 0
462 static bool no_warn = true;
463 int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
464 // Only support block sizes of 64 atm.
465 assert(blk_size == 64);
466 uint8_t data[blk_size];
467 //assert(xc->copySrcAddr);
468 int offset = dest & (blk_size - 1);
469
470 // Make sure block doesn't span page
471 if (no_warn &&
472 (dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) &&
473 (dest >> 40) != 0xfffffc) {
474 no_warn = false;
475 warn("Copied block destination spans pages %x. ", dest);
476 }
477
478 memReq->reset(dest & ~(blk_size -1), blk_size);
479 // translate to physical address
480 Fault fault = xc->translateDataWriteReq(memReq);
481
482 assert(fault != Alignment_Fault);
483
484 if (fault == NoFault) {
485 Addr dest_addr = memReq->paddr + offset;
486 // Need to read straight from memory since we have more than 8 bytes.
487 memReq->paddr = xc->copySrcPhysAddr;
488 xc->mem->read(memReq, data);
489 memReq->paddr = dest_addr;
490 xc->mem->write(memReq, data);
491 if (dcacheInterface) {
492 memReq->cmd = Copy;
493 memReq->completionEvent = NULL;
494 memReq->paddr = xc->copySrcPhysAddr;
495 memReq->dest = dest_addr;
496 memReq->size = 64;
497 memReq->time = curTick;
498 dcacheInterface->access(memReq);
499 }
500 }
501 return fault;
502 #endif
503 }
504
505 #if FULL_SYSTEM
506 template <class Impl>
507 Addr
508 OzoneCPU<Impl>::dbg_vtophys(Addr addr)
509 {
510 return vtophys(xcProxy, addr);
511 }
512 #endif // FULL_SYSTEM
513
514 #if FULL_SYSTEM
515 template <class Impl>
516 void
517 OzoneCPU<Impl>::post_interrupt(int int_num, int index)
518 {
519 BaseCPU::post_interrupt(int_num, index);
520
521 if (_status == Idle) {
522 DPRINTF(IPI,"Suspended Processor awoke\n");
523 // thread.activate();
524 // Hack for now. Otherwise might have to go through the xcProxy, or
525 // I need to figure out what's the right thing to call.
526 activateContext(thread.tid, 1);
527 }
528 }
529 #endif // FULL_SYSTEM
530
531 /* start simulation, program loaded, processor precise state initialized */
532 template <class Impl>
533 void
534 OzoneCPU<Impl>::tick()
535 {
536 DPRINTF(OzoneCPU, "\n\nOzoneCPU: Ticking cpu.\n");
537
538 _status = Running;
539 thread.renameTable[ZeroReg]->setIntResult(0);
540 thread.renameTable[ZeroReg+TheISA::FP_Base_DepTag]->
541 setDoubleResult(0.0);
542
543 comm.advance();
544 frontEnd->tick();
545 backEnd->tick();
546
547 // check for instruction-count-based events
548 comInstEventQueue[0]->serviceEvents(numInst);
549
550 if (!tickEvent.scheduled() && _status == Running)
551 tickEvent.schedule(curTick + cycles(1));
552 }
553
554 template <class Impl>
555 void
556 OzoneCPU<Impl>::squashFromXC()
557 {
558 thread.inSyscall = true;
559 backEnd->generateXCEvent();
560 }
561
562 #if !FULL_SYSTEM
563 template <class Impl>
564 void
565 OzoneCPU<Impl>::syscall()
566 {
567 // Not sure this copy is needed, depending on how the XC proxy is made.
568 thread.renameTable.copyFrom(backEnd->renameTable);
569
570 thread.inSyscall = true;
571
572 thread.funcExeInst++;
573
574 DPRINTF(OzoneCPU, "FuncExeInst: %i\n", thread.funcExeInst);
575
576 thread.process->syscall(xcProxy);
577
578 thread.funcExeInst--;
579
580 thread.inSyscall = false;
581
582 frontEnd->renameTable.copyFrom(thread.renameTable);
583 backEnd->renameTable.copyFrom(thread.renameTable);
584 }
585
586 template <class Impl>
587 void
588 OzoneCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
589 {
590 // check for error condition. Alpha syscall convention is to
591 // indicate success/failure in reg a3 (r19) and put the
592 // return value itself in the standard return value reg (v0).
593 if (return_value.successful()) {
594 // no error
595 thread.renameTable[SyscallSuccessReg]->setIntResult(0);
596 thread.renameTable[ReturnValueReg]->setIntResult(
597 return_value.value());
598 } else {
599 // got an error, return details
600 thread.renameTable[SyscallSuccessReg]->setIntResult((IntReg) -1);
601 thread.renameTable[ReturnValueReg]->setIntResult(
602 -return_value.value());
603 }
604 }
605 #else
606 template <class Impl>
607 Fault
608 OzoneCPU<Impl>::hwrei()
609 {
610 // Need to move this to ISA code
611 // May also need to make this per thread
612
613 lockFlag = false;
614 lockAddrList.clear();
615 thread.kernelStats->hwrei();
616
617 checkInterrupts = true;
618
619 // FIXME: XXX check for interrupts? XXX
620 return NoFault;
621 }
622
623 template <class Impl>
624 void
625 OzoneCPU<Impl>::processInterrupts()
626 {
627 // Check for interrupts here. For now can copy the code that
628 // exists within isa_fullsys_traits.hh. Also assume that thread 0
629 // is the one that handles the interrupts.
630
631 // Check if there are any outstanding interrupts
632 //Handle the interrupts
633 int ipl = 0;
634 int summary = 0;
635
636 checkInterrupts = false;
637
638 if (thread.readMiscReg(IPR_ASTRR))
639 panic("asynchronous traps not implemented\n");
640
641 if (thread.readMiscReg(IPR_SIRR)) {
642 for (int i = INTLEVEL_SOFTWARE_MIN;
643 i < INTLEVEL_SOFTWARE_MAX; i++) {
644 if (thread.readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
645 // See table 4-19 of the 21164 hardware reference
646 ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
647 summary |= (ULL(1) << i);
648 }
649 }
650 }
651
652 uint64_t interrupts = intr_status();
653
654 if (interrupts) {
655 for (int i = INTLEVEL_EXTERNAL_MIN;
656 i < INTLEVEL_EXTERNAL_MAX; i++) {
657 if (interrupts & (ULL(1) << i)) {
658 // See table 4-19 of the 21164 hardware reference
659 ipl = i;
660 summary |= (ULL(1) << i);
661 }
662 }
663 }
664
665 if (ipl && ipl > thread.readMiscReg(IPR_IPLR)) {
666 thread.setMiscReg(IPR_ISR, summary);
667 thread.setMiscReg(IPR_INTID, ipl);
668 // @todo: Make this more transparent
669 if (checker) {
670 checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
671 checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
672 }
673 Fault fault = new InterruptFault;
674 fault->invoke(thread.getXCProxy());
675 DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
676 thread.readMiscReg(IPR_IPLR), ipl, summary);
677 }
678 }
679
680 template <class Impl>
681 bool
682 OzoneCPU<Impl>::simPalCheck(int palFunc)
683 {
684 // Need to move this to ISA code
685 // May also need to make this per thread
686 thread.kernelStats->callpal(palFunc, xcProxy);
687
688 switch (palFunc) {
689 case PAL::halt:
690 haltContext(thread.tid);
691 if (--System::numSystemsRunning == 0)
692 new SimExitEvent("all cpus halted");
693 break;
694
695 case PAL::bpt:
696 case PAL::bugchk:
697 if (system->breakpoint())
698 return false;
699 break;
700 }
701
702 return true;
703 }
704 #endif
705
706 template <class Impl>
707 BaseCPU *
708 OzoneCPU<Impl>::OzoneXC::getCpuPtr()
709 {
710 return cpu;
711 }
712
713 template <class Impl>
714 void
715 OzoneCPU<Impl>::OzoneXC::setCpuId(int id)
716 {
717 cpu->cpuId = id;
718 thread->cpuId = id;
719 }
720
721 template <class Impl>
722 void
723 OzoneCPU<Impl>::OzoneXC::setStatus(Status new_status)
724 {
725 thread->_status = new_status;
726 }
727
728 template <class Impl>
729 void
730 OzoneCPU<Impl>::OzoneXC::activate(int delay)
731 {
732 cpu->activateContext(thread->tid, delay);
733 }
734
735 /// Set the status to Suspended.
736 template <class Impl>
737 void
738 OzoneCPU<Impl>::OzoneXC::suspend()
739 {
740 cpu->suspendContext(thread->tid);
741 }
742
743 /// Set the status to Unallocated.
744 template <class Impl>
745 void
746 OzoneCPU<Impl>::OzoneXC::deallocate()
747 {
748 cpu->deallocateContext(thread->tid);
749 }
750
751 /// Set the status to Halted.
752 template <class Impl>
753 void
754 OzoneCPU<Impl>::OzoneXC::halt()
755 {
756 cpu->haltContext(thread->tid);
757 }
758
759 #if FULL_SYSTEM
760 template <class Impl>
761 void
762 OzoneCPU<Impl>::OzoneXC::dumpFuncProfile()
763 { }
764 #endif
765
766 template <class Impl>
767 void
768 OzoneCPU<Impl>::OzoneXC::takeOverFrom(ExecContext *old_context)
769 {
770 // some things should already be set up
771 assert(getMemPtr() == old_context->getMemPtr());
772 #if FULL_SYSTEM
773 assert(getSystemPtr() == old_context->getSystemPtr());
774 #else
775 assert(getProcessPtr() == old_context->getProcessPtr());
776 #endif
777
778 // copy over functional state
779 setStatus(old_context->status());
780 copyArchRegs(old_context);
781 setCpuId(old_context->readCpuId());
782
783 #if !FULL_SYSTEM
784 setFuncExeInst(old_context->readFuncExeInst());
785 #else
786 EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
787 if (other_quiesce) {
788 // Point the quiesce event's XC at this XC so that it wakes up
789 // the proper CPU.
790 other_quiesce->xc = this;
791 }
792 if (thread->quiesceEvent) {
793 thread->quiesceEvent->xc = this;
794 }
795
796 thread->kernelStats = old_context->getKernelStats();
797 // storeCondFailures = 0;
798 cpu->lockFlag = false;
799 #endif
800
801 old_context->setStatus(ExecContext::Unallocated);
802 }
803
804 template <class Impl>
805 void
806 OzoneCPU<Impl>::OzoneXC::regStats(const std::string &name)
807 {
808 #if FULL_SYSTEM
809 thread->kernelStats = new Kernel::Statistics(cpu->system);
810 thread->kernelStats->regStats(name + ".kern");
811 #endif
812 }
813
814 template <class Impl>
815 void
816 OzoneCPU<Impl>::OzoneXC::serialize(std::ostream &os)
817 { }
818
819 template <class Impl>
820 void
821 OzoneCPU<Impl>::OzoneXC::unserialize(Checkpoint *cp, const std::string &section)
822 { }
823
824 #if FULL_SYSTEM
825 template <class Impl>
826 EndQuiesceEvent *
827 OzoneCPU<Impl>::OzoneXC::getQuiesceEvent()
828 {
829 return thread->quiesceEvent;
830 }
831
832 template <class Impl>
833 Tick
834 OzoneCPU<Impl>::OzoneXC::readLastActivate()
835 {
836 return thread->lastActivate;
837 }
838
839 template <class Impl>
840 Tick
841 OzoneCPU<Impl>::OzoneXC::readLastSuspend()
842 {
843 return thread->lastSuspend;
844 }
845
846 template <class Impl>
847 void
848 OzoneCPU<Impl>::OzoneXC::profileClear()
849 {
850 if (thread->profile)
851 thread->profile->clear();
852 }
853
854 template <class Impl>
855 void
856 OzoneCPU<Impl>::OzoneXC::profileSample()
857 {
858 if (thread->profile)
859 thread->profile->sample(thread->profileNode, thread->profilePC);
860 }
861 #endif
862
863 template <class Impl>
864 int
865 OzoneCPU<Impl>::OzoneXC::getThreadNum()
866 {
867 return thread->tid;
868 }
869
870 // Also somewhat obnoxious. Really only used for the TLB fault.
871 template <class Impl>
872 TheISA::MachInst
873 OzoneCPU<Impl>::OzoneXC::getInst()
874 {
875 return thread->inst;
876 }
877
878 template <class Impl>
879 void
880 OzoneCPU<Impl>::OzoneXC::copyArchRegs(ExecContext *xc)
881 {
882 thread->PC = xc->readPC();
883 thread->nextPC = xc->readNextPC();
884
885 cpu->frontEnd->setPC(thread->PC);
886 cpu->frontEnd->setNextPC(thread->nextPC);
887
888 for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
889 if (i < TheISA::FP_Base_DepTag) {
890 thread->renameTable[i]->setIntResult(xc->readIntReg(i));
891 } else if (i < (TheISA::FP_Base_DepTag + TheISA::NumFloatRegs)) {
892 int fp_idx = i - TheISA::FP_Base_DepTag;
893 thread->renameTable[i]->setDoubleResult(
894 xc->readFloatRegDouble(fp_idx));
895 }
896 }
897
898 #if !FULL_SYSTEM
899 thread->funcExeInst = xc->readFuncExeInst();
900 #endif
901
902 // Need to copy the XC values into the current rename table,
903 // copy the misc regs.
904 thread->regs.miscRegs.copyMiscRegs(xc);
905 }
906
907 template <class Impl>
908 void
909 OzoneCPU<Impl>::OzoneXC::clearArchRegs()
910 {
911 panic("Unimplemented!");
912 }
913
914 template <class Impl>
915 uint64_t
916 OzoneCPU<Impl>::OzoneXC::readIntReg(int reg_idx)
917 {
918 return thread->renameTable[reg_idx]->readIntResult();
919 }
920
921 template <class Impl>
922 float
923 OzoneCPU<Impl>::OzoneXC::readFloatRegSingle(int reg_idx)
924 {
925 int idx = reg_idx + TheISA::FP_Base_DepTag;
926 return thread->renameTable[idx]->readFloatResult();
927 }
928
929 template <class Impl>
930 double
931 OzoneCPU<Impl>::OzoneXC::readFloatRegDouble(int reg_idx)
932 {
933 int idx = reg_idx + TheISA::FP_Base_DepTag;
934 return thread->renameTable[idx]->readDoubleResult();
935 }
936
937 template <class Impl>
938 uint64_t
939 OzoneCPU<Impl>::OzoneXC::readFloatRegInt(int reg_idx)
940 {
941 int idx = reg_idx + TheISA::FP_Base_DepTag;
942 return thread->renameTable[idx]->readIntResult();
943 }
944
945 template <class Impl>
946 void
947 OzoneCPU<Impl>::OzoneXC::setIntReg(int reg_idx, uint64_t val)
948 {
949 thread->renameTable[reg_idx]->setIntResult(val);
950
951 if (!thread->inSyscall) {
952 cpu->squashFromXC();
953 }
954 }
955
956 template <class Impl>
957 void
958 OzoneCPU<Impl>::OzoneXC::setFloatRegSingle(int reg_idx, float val)
959 {
960 panic("Unimplemented!");
961 }
962
963 template <class Impl>
964 void
965 OzoneCPU<Impl>::OzoneXC::setFloatRegDouble(int reg_idx, double val)
966 {
967 int idx = reg_idx + TheISA::FP_Base_DepTag;
968
969 thread->renameTable[idx]->setDoubleResult(val);
970
971 if (!thread->inSyscall) {
972 cpu->squashFromXC();
973 }
974 }
975
976 template <class Impl>
977 void
978 OzoneCPU<Impl>::OzoneXC::setFloatRegInt(int reg_idx, uint64_t val)
979 {
980 panic("Unimplemented!");
981 }
982
983 template <class Impl>
984 void
985 OzoneCPU<Impl>::OzoneXC::setPC(Addr val)
986 {
987 thread->PC = val;
988 cpu->frontEnd->setPC(val);
989
990 if (!thread->inSyscall) {
991 cpu->squashFromXC();
992 }
993 }
994
995 template <class Impl>
996 void
997 OzoneCPU<Impl>::OzoneXC::setNextPC(Addr val)
998 {
999 thread->nextPC = val;
1000 cpu->frontEnd->setNextPC(val);
1001
1002 if (!thread->inSyscall) {
1003 cpu->squashFromXC();
1004 }
1005 }
1006
1007 template <class Impl>
1008 TheISA::MiscReg
1009 OzoneCPU<Impl>::OzoneXC::readMiscReg(int misc_reg)
1010 {
1011 return thread->regs.miscRegs.readReg(misc_reg);
1012 }
1013
1014 template <class Impl>
1015 TheISA::MiscReg
1016 OzoneCPU<Impl>::OzoneXC::readMiscRegWithEffect(int misc_reg, Fault &fault)
1017 {
1018 return thread->regs.miscRegs.readRegWithEffect(misc_reg,
1019 fault, this);
1020 }
1021
1022 template <class Impl>
1023 Fault
1024 OzoneCPU<Impl>::OzoneXC::setMiscReg(int misc_reg, const MiscReg &val)
1025 {
1026 // Needs to setup a squash event unless we're in syscall mode
1027 Fault ret_fault = thread->regs.miscRegs.setReg(misc_reg, val);
1028
1029 if (!thread->inSyscall) {
1030 cpu->squashFromXC();
1031 }
1032
1033 return ret_fault;
1034 }
1035
1036 template <class Impl>
1037 Fault
1038 OzoneCPU<Impl>::OzoneXC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
1039 {
1040 // Needs to setup a squash event unless we're in syscall mode
1041 Fault ret_fault = thread->regs.miscRegs.setRegWithEffect(misc_reg, val,
1042 this);
1043
1044 if (!thread->inSyscall) {
1045 cpu->squashFromXC();
1046 }
1047
1048 return ret_fault;
1049 }