2 * Copyright (c) 2005 The Regents of The University of Michigan
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.
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.
31 #ifndef __CPU_OZONE_CPU_HH__
32 #define __CPU_OZONE_CPU_HH__
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"
49 // forward declarations
51 #include "arch/alpha/tlb.hh"
56 class MemoryController;
72 class EndQuiesceEvent;
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.
92 class OzoneCPU : public BaseCPU
95 typedef typename Impl::FrontEnd FrontEnd;
96 typedef typename Impl::BackEnd BackEnd;
97 typedef typename Impl::DynInst DynInst;
98 typedef typename Impl::DynInstPtr DynInstPtr;
100 typedef TheISA::FloatReg FloatReg;
101 typedef TheISA::FloatRegBits FloatRegBits;
102 typedef TheISA::MiscReg MiscReg;
105 class OzoneTC : public ThreadContext {
109 OzoneThreadState<Impl> *thread;
111 BaseCPU *getCpuPtr();
113 void setCpuId(int id);
115 int readCpuId() { return thread->readCpuId(); }
118 System *getSystemPtr() { return cpu->system; }
120 PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
122 AlphaITB *getITBPtr() { return cpu->itb; }
124 AlphaDTB * getDTBPtr() { return cpu->dtb; }
126 Kernel::Statistics *getKernelStats()
127 { return thread->getKernelStats(); }
129 FunctionalPort *getPhysPort() { return thread->getPhysPort(); }
131 VirtualPort *getVirtPort(ThreadContext *tc = NULL)
132 { return thread->getVirtPort(tc); }
134 void delVirtPort(VirtualPort *vp);
136 TranslatingPort *getMemPort() { return thread->getMemPort(); }
138 Process *getProcessPtr() { return thread->getProcessPtr(); }
141 Status status() const { return thread->status(); }
143 void setStatus(Status new_status);
145 /// Set the status to Active. Optional delay indicates number of
146 /// cycles to wait before beginning execution.
147 void activate(int delay = 1);
149 /// Set the status to Suspended.
152 /// Set the status to Unallocated.
153 void deallocate(int delay = 0);
155 /// Set the status to Halted.
159 void dumpFuncProfile();
162 void takeOverFrom(ThreadContext *old_context);
164 void regStats(const std::string &name);
166 void serialize(std::ostream &os);
167 void unserialize(Checkpoint *cp, const std::string §ion);
170 EndQuiesceEvent *getQuiesceEvent();
172 Tick readLastActivate();
173 Tick readLastSuspend();
176 void profileSample();
181 // Also somewhat obnoxious. Really only used for the TLB fault.
182 TheISA::MachInst getInst();
184 void copyArchRegs(ThreadContext *tc);
186 void clearArchRegs();
188 uint64_t readIntReg(int reg_idx);
190 FloatReg readFloatReg(int reg_idx, int width);
192 FloatReg readFloatReg(int reg_idx);
194 FloatRegBits readFloatRegBits(int reg_idx, int width);
196 FloatRegBits readFloatRegBits(int reg_idx);
198 void setIntReg(int reg_idx, uint64_t val);
200 void setFloatReg(int reg_idx, FloatReg val, int width);
202 void setFloatReg(int reg_idx, FloatReg val);
204 void setFloatRegBits(int reg_idx, FloatRegBits val, int width);
206 void setFloatRegBits(int reg_idx, FloatRegBits val);
208 uint64_t readPC() { return thread->PC; }
209 void setPC(Addr val);
211 uint64_t readNextPC() { return thread->nextPC; }
212 void setNextPC(Addr val);
214 uint64_t readNextNPC()
219 void setNextNPC(uint64_t val)
224 MiscReg readMiscReg(int misc_reg);
226 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault);
228 Fault setMiscReg(int misc_reg, const MiscReg &val);
230 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
232 unsigned readStCondFailures()
233 { return thread->storeCondFailures; }
235 void setStCondFailures(unsigned sc_failures)
236 { thread->storeCondFailures = sc_failures; }
239 bool inPalMode() { return cpu->inPalMode(); }
242 bool misspeculating() { return false; }
245 TheISA::IntReg getSyscallArg(int i)
246 { return thread->renameTable[TheISA::ArgumentReg0 + i]->readIntResult(); }
248 // used to shift args for indirect syscall
249 void setSyscallArg(int i, TheISA::IntReg val)
250 { thread->renameTable[TheISA::ArgumentReg0 + i]->setIntResult(i); }
252 void setSyscallReturn(SyscallReturn return_value)
253 { cpu->setSyscallReturn(return_value, thread->readTid()); }
255 Counter readFuncExeInst() { return thread->funcExeInst; }
257 void setFuncExeInst(Counter new_val)
258 { thread->funcExeInst = new_val; }
260 void changeRegFileContext(TheISA::RegFile::ContextParam param,
261 TheISA::RegFile::ContextVal val)
262 { panic("Not supported on Alpha!"); }
265 // Ozone specific thread context
267 // Thread context to be used
269 // Checker thread context; will wrap the OzoneTC if a checker is
271 ThreadContext *checkerTC;
273 typedef OzoneThreadState<Impl> ImplState;
276 OzoneThreadState<Impl> thread;
279 // main simulation loop (one cycle)
282 std::set<InstSeqNum> snList;
283 std::set<Addr> lockAddrList;
285 struct TickEvent : public Event
290 TickEvent(OzoneCPU *c, int w);
292 const char *description();
297 /// Schedule tick event, regardless of its current state.
298 void scheduleTickEvent(int delay)
300 if (tickEvent.squashed())
301 tickEvent.reschedule(curTick + cycles(delay));
302 else if (!tickEvent.scheduled())
303 tickEvent.schedule(curTick + cycles(delay));
306 /// Unschedule tick event, regardless of its current state.
307 void unscheduleTickEvent()
309 if (tickEvent.scheduled())
314 Trace::InstRecord *traceData;
317 void trace_data(T data);
329 bool checkInterrupts;
331 void post_interrupt(int int_num, int index);
333 void zero_fill_64(Addr addr) {
334 static int warned = 0;
336 warn ("WH64 is not implemented");
341 typedef typename Impl::Params Params;
343 OzoneCPU(Params *params);
350 BaseCPU *getCpuPtr() { return this; }
352 void setCpuId(int id) { cpuId = id; }
354 int readCpuId() { return cpuId; }
359 void signalSwitched();
360 void takeOverFrom(BaseCPU *oldCPU);
365 Addr dbg_vtophys(Addr addr);
372 PhysicalMemory *physmem;
375 virtual Port *getPort(const std::string &name, int idx);
383 Status status() const { return _status; }
384 void setStatus(Status new_status) { _status = new_status; }
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);
392 virtual void regStats();
393 virtual void resetStats();
395 // number of simulated instructions
398 Counter startNumInst;
400 virtual Counter totalInstructions() const
402 return numInst - startNumInst;
406 // number of simulated loads
408 Counter startNumLoad;
410 // number of idle cycles
411 Stats::Average<> notIdleFraction;
412 Stats::Formula idleFraction;
415 virtual void serialize(std::ostream &os);
416 virtual void unserialize(Checkpoint *cp, const std::string §ion);
420 /** Translates instruction requestion. */
421 Fault translateInstReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
423 return itb->translate(req, thread->getTC());
426 /** Translates data read request. */
427 Fault translateDataReadReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
429 return dtb->translate(req, thread->getTC(), false);
432 /** Translates data write request. */
433 Fault translateDataWriteReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
435 return dtb->translate(req, thread->getTC(), true);
439 /** Translates instruction requestion in syscall emulation mode. */
440 Fault translateInstReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
442 return thread->getProcessPtr()->pTable->translate(req);
445 /** Translates data read request in syscall emulation mode. */
446 Fault translateDataReadReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
448 return thread->getProcessPtr()->pTable->translate(req);
451 /** Translates data write request in syscall emulation mode. */
452 Fault translateDataWriteReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
454 return thread->getProcessPtr()->pTable->translate(req);
458 /** Old CPU read from memory function. No longer used. */
460 Fault read(Request *req, T &data)
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);
469 if (req->flags & LOCKED) {
470 lockAddrList.insert(req->paddr);
476 error = this->mem->read(req, data);
482 /** CPU read function, forwards read to LSQ. */
484 Fault read(Request *req, T &data, int load_idx)
486 return backEnd->read(req, data, load_idx);
489 /** Old CPU write to memory function. No longer used. */
491 Fault write(Request *req, T &data)
494 #if FULL_SYSTEM && defined(TARGET_ALPHA)
497 // If this is a store conditional, act appropriately
498 if (req->flags & LOCKED) {
501 if (req->flags & UNCACHEABLE) {
502 // Don't update result register (see stq_c in isa_desc)
504 xc->setStCondFailures(0);//Needed? [RGD]
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;
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()
522 else xc->setStCondFailures(0);
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
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);
541 if (req->flags & LOCKED) {
542 if (req->flags & UNCACHEABLE) {
545 if (this->lockFlag) {
546 if (lockAddrList.find(req->paddr) !=
547 lockAddrList.end()) {
561 return this->mem->write(req, (T)htog(data));
564 /** CPU write function, forwards write to LSQ. */
566 Fault write(Request *req, T &data, int store_idx)
568 return backEnd->write(req, data, store_idx);
571 void prefetch(Addr addr, unsigned flags)
573 // need to do this...
576 void writeHint(Addr addr, int size, unsigned flags)
578 // need to do this...
581 Fault copySrcTranslate(Addr src);
583 Fault copy(Addr dest);
585 InstSeqNum globalSeqNum;
590 // @todo: This can be a useful debug function. Implement it.
591 void dumpInsts() { frontEnd->dumpInsts(); }
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();
602 void syscall(uint64_t &callnum);
603 void setSyscallReturn(SyscallReturn return_value, int tid);
606 ThreadContext *tcBase() { return tc; }
608 bool decoupledFrontEnd;
610 InstSeqNum doneSeqNum;
611 InstSeqNum nonSpecSeqNum;
617 TimeBuffer<CommStruct> comm;
621 Stats::Scalar<> quiesceCycles;
623 Checker<DynInstPtr> *checker;
626 #endif // __CPU_OZONE_CPU_HH__