Updates to fix merge issues and bring almost everything up to working speed. Ozone...
[gem5.git] / src / cpu / ozone / cpu.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 * Authors: Kevin Lim
29 */
30
31 #ifndef __CPU_OZONE_CPU_HH__
32 #define __CPU_OZONE_CPU_HH__
33
34 #include <set>
35
36 #include "arch/regfile.hh"
37 #include "base/statistics.hh"
38 #include "base/timebuf.hh"
39 #include "config/full_system.hh"
40 #include "cpu/base.hh"
41 #include "cpu/thread_context.hh"
42 #include "cpu/inst_seq.hh"
43 #include "cpu/ozone/rename_table.hh"
44 #include "cpu/ozone/thread_state.hh"
45 #include "cpu/pc_event.hh"
46 #include "cpu/static_inst.hh"
47 #include "mem/page_table.hh"
48 #include "sim/eventq.hh"
49
50 // forward declarations
51 #if FULL_SYSTEM
52 #include "arch/alpha/tlb.hh"
53
54 class AlphaITB;
55 class AlphaDTB;
56 class PhysicalMemory;
57 class MemoryController;
58
59 class RemoteGDB;
60 class GDBListener;
61
62 namespace Kernel {
63 class Statistics;
64 };
65
66 #else
67
68 class Process;
69
70 #endif // FULL_SYSTEM
71
72 class Checkpoint;
73 class EndQuiesceEvent;
74 class MemObject;
75 class Request;
76
77 namespace Trace {
78 class InstRecord;
79 }
80
81 template <class>
82 class Checker;
83
84 /**
85 * Light weight out of order CPU model that approximates an out of
86 * order CPU. It is separated into a front end and a back end, with
87 * the template parameter Impl describing the classes used for each.
88 * The goal is to be able to specify through the Impl the class to use
89 * for the front end and back end, with different classes used to
90 * model different levels of detail.
91 */
92 template <class Impl>
93 class OzoneCPU : public BaseCPU
94 {
95 private:
96 typedef typename Impl::FrontEnd FrontEnd;
97 typedef typename Impl::BackEnd BackEnd;
98 typedef typename Impl::DynInst DynInst;
99 typedef typename Impl::DynInstPtr DynInstPtr;
100
101 typedef TheISA::FloatReg FloatReg;
102 typedef TheISA::FloatRegBits FloatRegBits;
103 typedef TheISA::MiscReg MiscReg;
104
105 public:
106 class OzoneTC : public ThreadContext {
107 public:
108 OzoneCPU<Impl> *cpu;
109
110 OzoneThreadState<Impl> *thread;
111
112 BaseCPU *getCpuPtr();
113
114 void setCpuId(int id);
115
116 int readCpuId() { return thread->readCpuId(); }
117
118 #if FULL_SYSTEM
119 System *getSystemPtr() { return cpu->system; }
120
121 PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
122
123 AlphaITB *getITBPtr() { return cpu->itb; }
124
125 AlphaDTB * getDTBPtr() { return cpu->dtb; }
126
127 Kernel::Statistics *getKernelStats()
128 { return thread->getKernelStats(); }
129
130 FunctionalPort *getPhysPort() { return thread->getPhysPort(); }
131
132 VirtualPort *getVirtPort(ThreadContext *tc = NULL)
133 { return thread->getVirtPort(tc); }
134
135 void delVirtPort(VirtualPort *vp);
136 #else
137 TranslatingPort *getMemPort() { return thread->getMemPort(); }
138
139 Process *getProcessPtr() { return thread->getProcessPtr(); }
140 #endif
141
142 Status status() const { return thread->status(); }
143
144 void setStatus(Status new_status);
145
146 /// Set the status to Active. Optional delay indicates number of
147 /// cycles to wait before beginning execution.
148 void activate(int delay = 1);
149
150 /// Set the status to Suspended.
151 void suspend();
152
153 /// Set the status to Unallocated.
154 void deallocate(int delay = 0);
155
156 /// Set the status to Halted.
157 void halt();
158
159 #if FULL_SYSTEM
160 void dumpFuncProfile();
161 #endif
162
163 void takeOverFrom(ThreadContext *old_context);
164
165 void regStats(const std::string &name);
166
167 void serialize(std::ostream &os);
168 void unserialize(Checkpoint *cp, const std::string &section);
169
170 #if FULL_SYSTEM
171 EndQuiesceEvent *getQuiesceEvent();
172
173 Tick readLastActivate();
174 Tick readLastSuspend();
175
176 void profileClear();
177 void profileSample();
178 #endif
179
180 int getThreadNum();
181
182 // Also somewhat obnoxious. Really only used for the TLB fault.
183 TheISA::MachInst getInst();
184
185 void copyArchRegs(ThreadContext *tc);
186
187 void clearArchRegs();
188
189 uint64_t readIntReg(int reg_idx);
190
191 FloatReg readFloatReg(int reg_idx, int width);
192
193 FloatReg readFloatReg(int reg_idx);
194
195 FloatRegBits readFloatRegBits(int reg_idx, int width);
196
197 FloatRegBits readFloatRegBits(int reg_idx);
198
199 void setIntReg(int reg_idx, uint64_t val);
200
201 void setFloatReg(int reg_idx, FloatReg val, int width);
202
203 void setFloatReg(int reg_idx, FloatReg val);
204
205 void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
206
207 void setFloatRegBits(int reg_idx, FloatRegBits val);
208
209 uint64_t readPC() { return thread->PC; }
210 void setPC(Addr val);
211
212 uint64_t readNextPC() { return thread->nextPC; }
213 void setNextPC(Addr val);
214
215 uint64_t readNextNPC()
216 {
217 return 0;
218 }
219
220 void setNextNPC(uint64_t val)
221 { }
222
223 public:
224 // ISA stuff:
225 MiscReg readMiscReg(int misc_reg);
226
227 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault);
228
229 Fault setMiscReg(int misc_reg, const MiscReg &val);
230
231 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
232
233 unsigned readStCondFailures()
234 { return thread->storeCondFailures; }
235
236 void setStCondFailures(unsigned sc_failures)
237 { thread->storeCondFailures = sc_failures; }
238
239 #if FULL_SYSTEM
240 bool inPalMode() { return cpu->inPalMode(); }
241 #endif
242
243 bool misspeculating() { return false; }
244
245 #if !FULL_SYSTEM
246 TheISA::IntReg getSyscallArg(int i)
247 { return thread->renameTable[TheISA::ArgumentReg0 + i]->readIntResult(); }
248
249 // used to shift args for indirect syscall
250 void setSyscallArg(int i, TheISA::IntReg val)
251 { thread->renameTable[TheISA::ArgumentReg0 + i]->setIntResult(i); }
252
253 void setSyscallReturn(SyscallReturn return_value)
254 { cpu->setSyscallReturn(return_value, thread->readTid()); }
255
256 Counter readFuncExeInst() { return thread->funcExeInst; }
257
258 void setFuncExeInst(Counter new_val)
259 { thread->funcExeInst = new_val; }
260 #endif
261 void changeRegFileContext(TheISA::RegContextParam param,
262 TheISA::RegContextVal val)
263 { panic("Not supported on Alpha!"); }
264 };
265
266 // Ozone specific thread context
267 OzoneTC ozoneTC;
268 // Thread context to be used
269 ThreadContext *tc;
270 // Checker thread context; will wrap the OzoneTC if a checker is
271 // being used.
272 ThreadContext *checkerTC;
273
274 typedef OzoneThreadState<Impl> ImplState;
275
276 private:
277 // Committed thread state for the OzoneCPU.
278 OzoneThreadState<Impl> thread;
279
280 public:
281 // main simulation loop (one cycle)
282 void tick();
283
284 std::set<InstSeqNum> snList;
285 std::set<Addr> lockAddrList;
286 private:
287 struct TickEvent : public Event
288 {
289 OzoneCPU *cpu;
290 int width;
291
292 TickEvent(OzoneCPU *c, int w);
293 void process();
294 const char *description();
295 };
296
297 TickEvent tickEvent;
298
299 /// Schedule tick event, regardless of its current state.
300 void scheduleTickEvent(int delay)
301 {
302 if (tickEvent.squashed())
303 tickEvent.reschedule(curTick + cycles(delay));
304 else if (!tickEvent.scheduled())
305 tickEvent.schedule(curTick + cycles(delay));
306 }
307
308 /// Unschedule tick event, regardless of its current state.
309 void unscheduleTickEvent()
310 {
311 if (tickEvent.scheduled())
312 tickEvent.squash();
313 }
314
315 public:
316 enum Status {
317 Running,
318 Idle,
319 SwitchedOut
320 };
321
322 Status _status;
323
324 public:
325 void post_interrupt(int int_num, int index);
326
327 void zero_fill_64(Addr addr) {
328 static int warned = 0;
329 if (!warned) {
330 warn ("WH64 is not implemented");
331 warned = 1;
332 }
333 };
334
335 typedef typename Impl::Params Params;
336
337 OzoneCPU(Params *params);
338
339 virtual ~OzoneCPU();
340
341 void init();
342
343 public:
344 BaseCPU *getCpuPtr() { return this; }
345
346 void setCpuId(int id) { cpuId = id; }
347
348 int readCpuId() { return cpuId; }
349
350 int cpuId;
351
352 void switchOut();
353 void signalSwitched();
354 void takeOverFrom(BaseCPU *oldCPU);
355
356 int switchCount;
357
358 #if FULL_SYSTEM
359 Addr dbg_vtophys(Addr addr);
360
361 bool interval_stats;
362
363 AlphaITB *itb;
364 AlphaDTB *dtb;
365 System *system;
366 PhysicalMemory *physmem;
367 #endif
368
369 virtual Port *getPort(const std::string &name, int idx);
370
371 MemObject *mem;
372
373 FrontEnd *frontEnd;
374
375 BackEnd *backEnd;
376
377 private:
378 Status status() const { return _status; }
379 void setStatus(Status new_status) { _status = new_status; }
380
381 virtual void activateContext(int thread_num, int delay);
382 virtual void suspendContext(int thread_num);
383 virtual void deallocateContext(int thread_num, int delay);
384 virtual void haltContext(int thread_num);
385
386 // statistics
387 virtual void regStats();
388 virtual void resetStats();
389
390 // number of simulated instructions
391 public:
392 Counter numInst;
393 Counter startNumInst;
394
395 virtual Counter totalInstructions() const
396 {
397 return numInst - startNumInst;
398 }
399
400 private:
401 // number of simulated loads
402 Counter numLoad;
403 Counter startNumLoad;
404
405 // number of idle cycles
406 Stats::Average<> notIdleFraction;
407 Stats::Formula idleFraction;
408
409 public:
410 virtual void serialize(std::ostream &os);
411 virtual void unserialize(Checkpoint *cp, const std::string &section);
412
413 #if FULL_SYSTEM
414 /** Translates instruction requestion. */
415 Fault translateInstReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
416 {
417 return itb->translate(req, thread->getTC());
418 }
419
420 /** Translates data read request. */
421 Fault translateDataReadReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
422 {
423 return dtb->translate(req, thread->getTC(), false);
424 }
425
426 /** Translates data write request. */
427 Fault translateDataWriteReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
428 {
429 return dtb->translate(req, thread->getTC(), true);
430 }
431
432 #else
433 /** Translates instruction requestion in syscall emulation mode. */
434 Fault translateInstReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
435 {
436 return thread->getProcessPtr()->pTable->translate(req);
437 }
438
439 /** Translates data read request in syscall emulation mode. */
440 Fault translateDataReadReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
441 {
442 return thread->getProcessPtr()->pTable->translate(req);
443 }
444
445 /** Translates data write request in syscall emulation mode. */
446 Fault translateDataWriteReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
447 {
448 return thread->getProcessPtr()->pTable->translate(req);
449 }
450 #endif
451
452 /** Old CPU read from memory function. No longer used. */
453 template <class T>
454 Fault read(Request *req, T &data)
455 {
456 #if 0
457 #if FULL_SYSTEM && defined(TARGET_ALPHA)
458 if (req->flags & LOCKED) {
459 req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
460 req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
461 }
462 #endif
463 if (req->flags & LOCKED) {
464 lockAddrList.insert(req->paddr);
465 lockFlag = true;
466 }
467 #endif
468 Fault error;
469
470 error = this->mem->read(req, data);
471 data = gtoh(data);
472 return error;
473 }
474
475
476 /** CPU read function, forwards read to LSQ. */
477 template <class T>
478 Fault read(Request *req, T &data, int load_idx)
479 {
480 return backEnd->read(req, data, load_idx);
481 }
482
483 /** Old CPU write to memory function. No longer used. */
484 template <class T>
485 Fault write(Request *req, T &data)
486 {
487 #if 0
488 #if FULL_SYSTEM && defined(TARGET_ALPHA)
489 ExecContext *xc;
490
491 // If this is a store conditional, act appropriately
492 if (req->flags & LOCKED) {
493 xc = req->xc;
494
495 if (req->flags & UNCACHEABLE) {
496 // Don't update result register (see stq_c in isa_desc)
497 req->result = 2;
498 xc->setStCondFailures(0);//Needed? [RGD]
499 } else {
500 bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
501 Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
502 req->result = lock_flag;
503 if (!lock_flag ||
504 ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
505 xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
506 xc->setStCondFailures(xc->readStCondFailures() + 1);
507 if (((xc->readStCondFailures()) % 100000) == 0) {
508 std::cerr << "Warning: "
509 << xc->readStCondFailures()
510 << " consecutive store conditional failures "
511 << "on cpu " << req->xc->readCpuId()
512 << std::endl;
513 }
514 return NoFault;
515 }
516 else xc->setStCondFailures(0);
517 }
518 }
519
520 // Need to clear any locked flags on other proccessors for
521 // this address. Only do this for succsful Store Conditionals
522 // and all other stores (WH64?). Unsuccessful Store
523 // Conditionals would have returned above, and wouldn't fall
524 // through.
525 for (int i = 0; i < this->system->threadContexts.size(); i++){
526 xc = this->system->threadContexts[i];
527 if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
528 (req->paddr & ~0xf)) {
529 xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
530 }
531 }
532
533 #endif
534
535 if (req->flags & LOCKED) {
536 if (req->flags & UNCACHEABLE) {
537 req->result = 2;
538 } else {
539 if (this->lockFlag) {
540 if (lockAddrList.find(req->paddr) !=
541 lockAddrList.end()) {
542 req->result = 1;
543 } else {
544 req->result = 0;
545 return NoFault;
546 }
547 } else {
548 req->result = 0;
549 return NoFault;
550 }
551 }
552 }
553 #endif
554
555 return this->mem->write(req, (T)htog(data));
556 }
557
558 /** CPU write function, forwards write to LSQ. */
559 template <class T>
560 Fault write(Request *req, T &data, int store_idx)
561 {
562 return backEnd->write(req, data, store_idx);
563 }
564
565 void prefetch(Addr addr, unsigned flags)
566 {
567 // need to do this...
568 }
569
570 void writeHint(Addr addr, int size, unsigned flags)
571 {
572 // need to do this...
573 }
574
575 Fault copySrcTranslate(Addr src);
576
577 Fault copy(Addr dest);
578
579 public:
580 void squashFromTC();
581
582 void dumpInsts() { frontEnd->dumpInsts(); }
583
584 #if FULL_SYSTEM
585 Fault hwrei();
586 int readIntrFlag() { return thread.intrflag; }
587 void setIntrFlag(int val) { thread.intrflag = val; }
588 bool inPalMode() { return AlphaISA::PcPAL(thread.PC); }
589 bool inPalMode(Addr pc) { return AlphaISA::PcPAL(pc); }
590 bool simPalCheck(int palFunc);
591 void processInterrupts();
592 #else
593 void syscall(uint64_t &callnum);
594 void setSyscallReturn(SyscallReturn return_value, int tid);
595 #endif
596
597 ThreadContext *tcBase() { return tc; }
598
599 struct CommStruct {
600 InstSeqNum doneSeqNum;
601 InstSeqNum nonSpecSeqNum;
602 bool uncached;
603 unsigned lqIdx;
604
605 bool stall;
606 };
607
608 InstSeqNum globalSeqNum;
609
610 TimeBuffer<CommStruct> comm;
611
612 bool decoupledFrontEnd;
613
614 bool lockFlag;
615
616 Stats::Scalar<> quiesceCycles;
617
618 Checker<DynInstPtr> *checker;
619 };
620
621 #endif // __CPU_OZONE_CPU_HH__