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