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