summaryrefslogtreecommitdiff
path: root/cpu/beta_cpu/alpha_full_cpu.hh
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/beta_cpu/alpha_full_cpu.hh')
-rw-r--r--cpu/beta_cpu/alpha_full_cpu.hh263
1 files changed, 263 insertions, 0 deletions
diff --git a/cpu/beta_cpu/alpha_full_cpu.hh b/cpu/beta_cpu/alpha_full_cpu.hh
new file mode 100644
index 000000000..065b2fc4e
--- /dev/null
+++ b/cpu/beta_cpu/alpha_full_cpu.hh
@@ -0,0 +1,263 @@
+// Todo: Find all the stuff in ExecContext and ev5 that needs to be
+// specifically designed for this CPU.
+// Read and write are horribly hacked up between not being sure where to
+// copy their code from, and Ron's memory changes.
+
+#ifndef __CPU_BETA_CPU_ALPHA_FULL_CPU_HH__
+#define __CPU_BETA_CPU_ALPHA_FULL_CPU_HH__
+
+// To include: comm, full cpu, ITB/DTB if full sys,
+#include "cpu/beta_cpu/full_cpu.hh"
+
+template <class Impl>
+class AlphaFullCPU : public FullBetaCPU<Impl>
+{
+ public:
+ typedef typename Impl::ISA AlphaISA;
+ typedef typename Impl::Params Params;
+
+ public:
+ AlphaFullCPU(Params &params);
+
+#ifdef FULL_SYSTEM
+ AlphaITB *itb;
+ AlphaDTB *dtb;
+#endif
+
+ public:
+ void regStats();
+
+#ifdef FULL_SYSTEM
+ //Note that the interrupt stuff from the base CPU might be somewhat
+ //ISA specific (ie NumInterruptLevels). These functions might not
+ //be needed in FullCPU though.
+// void post_interrupt(int int_num, int index);
+// void clear_interrupt(int int_num, int index);
+// void clear_interrupts();
+
+ Fault translateInstReq(MemReqPtr &req)
+ {
+ return itb->translate(req);
+ }
+
+ Fault translateDataReadReq(MemReqPtr &req)
+ {
+ return dtb->translate(req, false);
+ }
+
+ Fault translateDataWriteReq(MemReqPtr &req)
+ {
+ return dtb->translate(req, true);
+ }
+
+#else
+ Fault dummyTranslation(MemReqPtr &req)
+ {
+#if 0
+ assert((req->vaddr >> 48 & 0xffff) == 0);
+#endif
+
+ // put the asid in the upper 16 bits of the paddr
+ req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
+ req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
+ return No_Fault;
+ }
+
+ Fault translateInstReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+
+ Fault translateDataReadReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+
+ Fault translateDataWriteReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+
+#endif
+
+ // Later on may want to remove this misc stuff from the regfile and
+ // have it handled at this level. Might prove to be an issue when
+ // trying to rename source/destination registers...
+ uint64_t readUniq()
+ {
+ return this->regFile.readUniq();
+ }
+
+ void setUniq(uint64_t val)
+ {
+ this->regFile.setUniq(val);
+ }
+
+ uint64_t readFpcr()
+ {
+ return this->regFile.readFpcr();
+ }
+
+ void setFpcr(uint64_t val)
+ {
+ this->regFile.setFpcr(val);
+ }
+
+#ifdef FULL_SYSTEM
+ uint64_t *getIpr();
+ uint64_t readIpr(int idx, Fault &fault);
+ Fault setIpr(int idx, uint64_t val);
+ int readIntrFlag();
+ void setIntrFlag(int val);
+ Fault hwrei();
+ bool inPalMode() { return AlphaISA::PcPAL(this->regFile.readPC()); }
+ bool inPalMode(uint64_t PC)
+ { return AlphaISA::PcPAL(PC); }
+
+ void trap(Fault fault);
+ bool simPalCheck(int palFunc);
+
+ void processInterrupts();
+#endif
+
+
+#ifndef FULL_SYSTEM
+ // Need to change these into regfile calls that directly set a certain
+ // register. Actually, these functions should handle most of this
+ // functionality by themselves; should look up the rename and then
+ // set the register.
+ IntReg getSyscallArg(int i)
+ {
+ return this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i];
+ }
+
+ // used to shift args for indirect syscall
+ void setSyscallArg(int i, IntReg val)
+ {
+ this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val;
+ }
+
+ void setSyscallReturn(int64_t return_value)
+ {
+ // check for error condition. Alpha syscall convention is to
+ // indicate success/failure in reg a3 (r19) and put the
+ // return value itself in the standard return value reg (v0).
+ const int RegA3 = 19; // only place this is used
+ if (return_value >= 0) {
+ // no error
+ this->xc->regs.intRegFile[RegA3] = 0;
+ this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value;
+ } else {
+ // got an error, return details
+ this->xc->regs.intRegFile[RegA3] = (IntReg) -1;
+ this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value;
+ }
+ }
+
+ void syscall(short thread_num);
+ void squashStages();
+
+#endif
+
+ void copyToXC();
+ void copyFromXC();
+
+ public:
+#ifdef FULL_SYSTEM
+ bool palShadowEnabled;
+
+ // Not sure this is used anywhere.
+ void intr_post(RegFile *regs, Fault fault, Addr pc);
+ // Actually used within exec files. Implement properly.
+ void swapPALShadow(bool use_shadow);
+ // Called by CPU constructor. Can implement as I please.
+ void initCPU(RegFile *regs);
+ // Called by initCPU. Implement as I please.
+ void initIPRs(RegFile *regs);
+
+ void halt() { panic("Halt not implemented!\n"); }
+#endif
+
+
+ template <class T>
+ Fault read(MemReqPtr &req, T &data)
+ {
+#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
+ if (req->flags & LOCKED) {
+ MiscRegFile *cregs = &req->xc->regs.miscRegs;
+ cregs->lock_addr = req->paddr;
+ cregs->lock_flag = true;
+ }
+#endif
+
+ Fault error;
+ error = this->mem->read(req, data);
+ data = htoa(data);
+ return error;
+ }
+
+ template <class T>
+ Fault read(MemReqPtr &req, T &data, int load_idx)
+ {
+ return this->iew.ldstQueue.read(req, data, load_idx);
+ }
+
+ template <class T>
+ Fault write(MemReqPtr &req, T &data)
+ {
+#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
+
+ MiscRegFile *cregs;
+
+ // If this is a store conditional, act appropriately
+ if (req->flags & LOCKED) {
+ cregs = &this->xc->regs.miscRegs;
+
+ if (req->flags & UNCACHEABLE) {
+ // Don't update result register (see stq_c in isa_desc)
+ req->result = 2;
+ req->xc->storeCondFailures = 0;//Needed? [RGD]
+ } else {
+ req->result = cregs->lock_flag;
+ if (!cregs->lock_flag ||
+ ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) {
+ cregs->lock_flag = false;
+ if (((++req->xc->storeCondFailures) % 100000) == 0) {
+ std::cerr << "Warning: "
+ << req->xc->storeCondFailures
+ << " consecutive store conditional failures "
+ << "on cpu " << this->cpu_id
+ << std::endl;
+ }
+ return No_Fault;
+ }
+ else req->xc->storeCondFailures = 0;
+ }
+ }
+
+ // Need to clear any locked flags on other proccessors for
+ // this address. Only do this for succsful Store Conditionals
+ // and all other stores (WH64?). Unsuccessful Store
+ // Conditionals would have returned above, and wouldn't fall
+ // through.
+ for (int i = 0; i < this->system->execContexts.size(); i++){
+ cregs = &this->system->execContexts[i]->regs.miscRegs;
+ if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
+ cregs->lock_flag = false;
+ }
+ }
+
+#endif
+
+ return this->mem->write(req, (T)htoa(data));
+ }
+
+ template <class T>
+ Fault write(MemReqPtr &req, T &data, int store_idx)
+ {
+ return this->iew.ldstQueue.write(req, data, store_idx);
+ }
+
+};
+
+#endif // __CPU_BETA_CPU_ALPHA_FULL_CPU_HH__