• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

sst/elements/genericProc/FE/ppcFrontEnd/ppcFront.h

00001 // Copyright 2007 Sandia Corporation. Under the terms
00002 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
00003 // Government retains certain rights in this software.
00004 // 
00005 // Copyright (c) 2005-2007, Sandia Corporation
00006 // All rights reserved.
00007 // Copyright (c) 2003-2005, University of Notre Dame
00008 // All rights reserved.
00009 // 
00010 // This file is part of the SST software package. For license
00011 // information, see the LICENSE file in the top level directory of the
00012 // distribution.
00013 
00014 
00015 #ifndef PPCTHREAD_H
00016 #define PPCTHREAD_H
00017 
00018 #include "sst_stdint.h"
00019 #include "thread.h"
00020 #include "pool.h"
00021 #include "processor.h"
00022 #include <utility>
00023 #include <boost/serialization/set.hpp>
00024 
00025 #include "loadInfo.h"
00026 
00027 //#include "sst/boost.h"
00028 #include "sst/core/component.h"
00029 
00030 #include "regs.h"
00031 
00032 #ifdef __APPLE__
00033   #include <architecture/ppc/cframe.h>
00034 #endif
00035 
00036 static const unsigned int ppcMaxStackSize=32*1024;
00037 
00038 #define ppcSimStackBase memory::segRange[GlobalDynamic][0]
00039 #define ppcInitStackBase  memory::segRange[GlobalDynamic][0]+0x1000
00040 #define getStackIdx(SA) (SA - memory::segRange[GlobalDynamic][0])
00041 
00042 instType classifyMask(const unsigned int mask);
00043 
00044 const int altivecWordSize = 16; //in words
00045 const int ppcRegSize = 32+64+(32*altivecWordSize); //int, fp, and altivec registers
00046 
00047 class processor; 
00048 class ppcThread;
00049 
00050 typedef enum { SOFTWARE, CPLUSPLUS, ASM_PPC/*, ASM_X86*/ } fpu_mode_t;
00051 
00052 //: PowerPC instruction
00053 //!SEC:ppcFront
00054 class ppcInstruction : public instruction {
00055   friend class boost::serialization::access;
00056   template<class Archive> 
00057   void serialize(Archive & ar, const unsigned int version )
00058   {
00059       boost::serialization::
00060           void_cast_register(static_cast<ppcInstruction*>(NULL), 
00061                              static_cast<instruction*>(NULL));
00062     ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( instruction );
00063     ar & BOOST_SERIALIZATION_NVP(loadsAlwaysCheckFEB);
00064     ar & BOOST_SERIALIZATION_NVP(storesAlwaysSetFEB);
00065     ar & BOOST_SERIALIZATION_NVP(allowSelfModify);
00066     ar & BOOST_SERIALIZATION_NVP(totalCommitted);
00067     ar & BOOST_SERIALIZATION_NVP(parent);
00068     ar & BOOST_SERIALIZATION_NVP(magicStack);
00069     ar & BOOST_SERIALIZATION_NVP(fpu_mode);
00070     ar & BOOST_SERIALIZATION_NVP(fpu_mode_software);
00071     ar & BOOST_SERIALIZATION_NVP(fpu_mode_cplusplus);
00072     ar & BOOST_SERIALIZATION_NVP(fpu_mode_asm_ppc);
00073     ar & BOOST_SERIALIZATION_NVP(fpu_mode_asm_x86);
00074     ar & BOOST_SERIALIZATION_NVP(debugPrintFPSCR);
00075     ar & BOOST_SERIALIZATION_NVP(_NPC);
00076     ar & BOOST_SERIALIZATION_NVP(_TPC);
00077     ar & BOOST_SERIALIZATION_NVP(_fu);
00078     ar & BOOST_SERIALIZATION_NVP(_specificOp);
00079     ar & BOOST_SERIALIZATION_NVP(_ins);
00080     ar & BOOST_SERIALIZATION_NVP(_outs);
00081     ar & BOOST_SERIALIZATION_NVP(ProgramCounter);
00082     ar & BOOST_SERIALIZATION_NVP(_memEA);
00083     ar & BOOST_SERIALIZATION_NVP(_op);
00084     ar & BOOST_SERIALIZATION_NVP(_exception);
00085     ar & BOOST_SERIALIZATION_NVP(_moveToTarget);
00086     ar & BOOST_SERIALIZATION_NVP(_febTarget);
00087     ar & BOOST_SERIALIZATION_NVP(simOp);
00088     ar & BOOST_SERIALIZATION_NVP(invalid);
00089     ar & BOOST_SERIALIZATION_NVP(aCurrentInstruction);
00090     ar & BOOST_SERIALIZATION_NVP(_state);
00091   }
00092 
00093   friend class ppcThread;
00094   static bool loadsAlwaysCheckFEB;
00095   static bool storesAlwaysSetFEB;
00096   static bool allowSelfModify;
00097   static unsigned totalCommitted;
00098   //: Thread parent
00099   //
00100   // The thread which created this instruction
00101   ppcThread *parent;
00102 
00103   static bool magicStack;
00104 
00105   // FPU Configuration mode
00106   static bool little_endian;
00107   static fpu_mode_t fpu_mode;
00108   static bool fpu_mode_software;   /* software IEEE compliant FPU operations             */
00109   static bool fpu_mode_cplusplus;  /* do op'n using C code (not IEEE compliant FPU)      */
00110   static bool fpu_mode_asm_ppc;    /* Use native PPC assembly when on a PPC              */
00111   static bool fpu_mode_asm_x86;    /* Use native x86 assembly when on intel Architecture */
00112   
00113   // Debugging options for FPSCR (useful for softFloat compatibility)
00114   // - important for compatibility with unit tests.
00115   static bool debugPrintFPSCR;
00116 
00117   //: Helper function
00118   void printRegs();
00119 
00120   simRegister _NPC;
00121   simRegister _TPC;
00122 
00123   int _fu;
00124   int _specificOp;
00125   static const int max_deps = 5;
00126   int _ins[max_deps+1];
00127   int _outs[max_deps+1];
00128   
00129   //: Program Counter
00130   simRegister   ProgramCounter;
00131   //: Effective address
00132   simAddress _memEA;
00133   //: Instruction opcode
00134   instType _op;
00135   //: Exception Type
00136   exceptType _exception;
00137   //: Target address for MOVE_TO exception
00138   simAddress _moveToTarget;
00139   //: Target address for FEB exception
00140   simAddress _febTarget;
00141 
00142   //: Decoded Opcode 
00143   //
00144   // We decode the opcode during instruction issue and then store it
00145   // here so we don't have to decode twice.
00146   int simOp;
00147   //: invald instruction
00148   //
00149   // indicates the instruction is invalid and should be squashed.
00150   bool invalid;
00151 
00152   //: Current Instruction
00153   uint32_t aCurrentInstruction;
00154 
00155   // convenience function to read a double
00156   double ReadMemoryDouble(simAddress addr, processor *proc) {
00157     qword_t qw = proc->ReadMemory64(addr,0);
00158     qw = endian_swap(qw);
00159     double out;
00160     memcpy(&out, &qw, sizeof(double));
00161     return out;
00162   }
00163 
00164   // convenience function to write a double
00165   void WriteMemoryDouble(simAddress addr, processor *proc, double val) {
00166     qword_t valWord;
00167     memcpy(&valWord, &val, sizeof(qword_t));
00168     proc->WriteMemory64(addr, endian_swap(valWord), 0);
00169   }
00170 
00171   ppcInstruction(ppcThread*);
00172   static bool isStack(const simAddress s) {
00173     //if (magicStack) return (s > ppcSimStackBase && s < 0xd0000000);
00174     if (magicStack) return (memory::getAccType(s) == GlobalDynamic);
00175     else return 0;
00176   }
00177   void issueSystemTrap(processor*, uint32_t *At);
00178   bool commitSystemTrap(processor*, uint32_t *At, simRegister &nextPC);
00179 #include "ppcSystemTrapHandler.h"
00180   instType getOp(const simAddress);
00181   string op_args(uint32_t, simRegister*, ppc_regs_t&) const;
00182   instState _state;
00183 
00184   uint8_t CommitReadByte (simAddress sa, bool specRd, processor *proc);
00185   uint16_t CommitReadHalf (simAddress sa, bool specRd, processor *proc);
00186   uint32_t CommitReadWord (simAddress sa, bool specRd, processor *proc);
00187   uint64_t CommitReadDouble (simAddress sa, bool specRd, processor *proc);
00188 
00189   bool CommitWriteByte (simAddress sa, uint8_t dd, bool specRd, processor *proc);
00190   bool CommitWriteHalf (simAddress sa, uint16_t dd, bool specRd, processor *proc);
00191   bool CommitWriteWord (simAddress sa, uint32_t dd, bool specRd, processor *proc);
00192   bool CommitWriteDouble (simAddress sa, uint64_t dd, bool specRd, processor *proc);
00193 
00194  public:
00195   ppcInstruction() : parent(0) {;}
00196   virtual bool fetch(processor*);
00197   virtual bool issue(processor* p) {return issue(p,0);}
00198   virtual bool commit(processor* p) {return commit(p,0);}
00199 
00200   virtual instState state() const {return _state;}
00201   virtual simAddress PC() const;
00202   virtual instType op() const;
00203   virtual simAddress memEA() const;
00204   //: Accessor for exception
00205   virtual exceptType exception() const {return _exception;};
00206   //: Accessor for moveToTarget
00207   virtual simAddress moveToTarget() const {return _moveToTarget;}
00208   //: Accessor for FEB target
00209   virtual simAddress febTarget() const {return _febTarget;}
00210 
00211   virtual simRegister NPC() const {return _NPC;}
00212   virtual simRegister TPC() const {return _TPC;}
00213   virtual bool issue(processor *p, const bool s);
00214   virtual bool commit(processor *p, const bool s);
00215   virtual int fu() const {return _fu;}
00216   virtual int specificOp() const {return _specificOp;}
00217   virtual const int* outDeps() const {return _outs;}
00218   virtual const int* inDeps() const {return _ins;}
00219   virtual bool isReturn() const;
00220   virtual bool isBranchLink() const;
00221   virtual simPID pid() const;
00222 };
00223 
00224 struct  ppc_regs_t;
00225 
00226 //: PowerPC Thread
00227 //
00228 // This thread class uses a 'magic stack' - stack memory references do
00229 // not go through the normal interface.
00230 //
00231 //!SEC:ppcFront
00232 class ppcThread : public thread {
00233   friend class boost::serialization::access;
00234   template<class Archive>
00235   void serialize(Archive & ar, const unsigned int version )
00236   {
00237     boost::serialization::
00238         void_cast_register(static_cast<ppcThread*>(NULL),
00239                            static_cast<thread*>(NULL));
00240     ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(thread);
00241     ar & BOOST_SERIALIZATION_NVP(loadInfo); 
00242     ar & BOOST_SERIALIZATION_NVP(Name);
00243     ar & BOOST_SERIALIZATION_NVP(ShouldExit);
00244     ar & BOOST_SERIALIZATION_NVP(threadIDMap);
00245     ar & BOOST_SERIALIZATION_NVP(nextThreadID);
00246     ar & BOOST_SERIALIZATION_NVP(exitSysCallExitsAll);
00247     ar & BOOST_SERIALIZATION_NVP(realGettimeofday);
00248     ar & BOOST_SERIALIZATION_NVP(verbose);
00249     ar & BOOST_SERIALIZATION_NVP(ThreadID);
00250     ar & BOOST_SERIALIZATION_NVP(isFuture);
00251     ar & BOOST_SERIALIZATION_NVP(SequenceNumber);
00252     ar & BOOST_SERIALIZATION_NVP(_pid);
00253     ar & BOOST_SERIALIZATION_NVP(iPool);
00254     ar & BOOST_SERIALIZATION_NVP(ProgramCounter);
00255     ar & BOOST_SERIALIZATION_NVP(setStack);
00256     ar & BOOST_SERIALIZATION_NVP(ppcRegisters);  
00257     ar & BOOST_SERIALIZATION_NVP(specPPCRegisters); 
00258     ar & BOOST_SERIALIZATION_NVP(packagedRegisters);
00259     ar & BOOST_SERIALIZATION_NVP(outstandingInsts);
00260     ar & BOOST_SERIALIZATION_NVP(condemnedInsts);
00261     ar & BOOST_SERIALIZATION_NVP(registers);
00262     ar & BOOST_SERIALIZATION_NVP(home);
00263     ar & BOOST_SERIALIZATION_NVP(yieldCount);
00264     ar & BOOST_SERIALIZATION_NVP(myFrame);    
00265   }
00266 
00267   LoadInfo loadInfo;
00268 
00269   string Name;
00270   bool ShouldExit;
00271   friend class ppcInstruction;
00272   friend class ppcLoader;
00273   static const bool usingMagicStack() {return ppcInstruction::magicStack;}
00274   static map<uint32_t, ppcThread*> threadIDMap;
00275   static unsigned int nextThreadID;
00276   static bool exitSysCallExitsAll;
00277   //: real gettimofday or not
00278   static bool realGettimeofday;
00279   //: Print more info about instructions
00280   static int verbose;
00281   simAddress ThreadID;
00282   bool isFuture;
00283   uint32_t SequenceNumber;
00284   simPID _pid;
00285   //: instruction pool
00286   static pool<ppcInstruction> iPool;
00287   //: reservation set
00288   //
00289   // set of reserved addresses (for LWARX/STCWX instructions)
00290   typedef pair<simAddress, simPID> addrPair;
00291   typedef map<addrPair, ppcThread*> reservedSetT;
00292   static reservedSetT reservedSet;
00293   addrPair reservedAddr; // for LWARX/STWCX; should probably be attached to the processor rather than here, but...
00294   //: Program Counter
00295   simRegister   ProgramCounter;
00296   bool setStack;
00297   //: PowerPC special registers
00298   ppc_regs_t *ppcRegisters;
00299   ppc_regs_t *specPPCRegisters;
00300   //: Storage space for frames
00301   //
00302   // Threads which need to migrate/travel, package thier frame's state
00303   // into this region before being migrated. Upon arriving at the
00304   // destination, it allocates a new frame and "unpacks" itself.
00305   //
00306   // Also, used for speculative register scratch space
00307   simRegister packagedRegisters[ppcRegSize];
00308 
00309 #if 0
00310   //: Text memory
00311   //
00312   // NOTE: Ideally, this should be replaced by having ppcThread inherit
00313   // from the memory class
00314   //static uint8_t  **textPageArray;
00315   //: Size of instruction pages
00316   static uint32_t PageSize;
00317   //: Instruction page shift
00318   static uint32_t PageShift;
00319   //: Instruction page mask
00320   static uint32_t PageMask;
00321   static uint8_t *GetTextPage (const simAddress sa);
00322 #endif
00323 
00324   typedef deque<ppcInstruction*> instList;
00325   //: Current ppcInstructions
00326   //
00327   // It is an collection of all the outstanding instructions. new
00328   // instructions are placed in the back, and retired out the front.
00329   // Only the top instruction can be retired to ensure proper
00330   // ordering.
00331   //
00332   // Probably this should be a list for performance. Change it at
00333   // some point and also add an accounting feature so the
00334   // numOutstanding() function isn't slow.
00335   instList outstandingInsts;
00336   set<ppcInstruction*> condemnedInsts;
00337   uint numOutstanding() const {return outstandingInsts.size();}
00338   instList &getOutstandingInsts() {return outstandingInsts;}
00339   //: FrameID for thread's register set
00340   frameID registers;
00341   //: Home processor of thread
00342   //
00343   // This is the processor where the thread is executing. 
00344   processor *home;
00345   // yield count
00346   int yieldCount;
00347 
00348   //: my register set
00349   simRegister myFrame[ppcRegSize];
00350   //: Get reference to register set
00351   simRegister *getRegisters() {return myFrame;}
00352   simRegister *getSpecRegisters() {return packagedRegisters;}
00353 
00354   //: copy date to the simulated memory
00355   //
00356   // ppcthread needs its own CopyToSim because some data memory may be
00357   // on the stack.
00358   bool CopyToSIM(simAddress dest, void* source, const unsigned int Bytes);
00359 
00360   //: copy date from the simulated memory
00361   //
00362   // ppcthread needs its own CopyFromSim because some data memory may be
00363   // on the stack.
00364   bool CopyFromSIM(void* dest, const simAddress source, const unsigned int Bytes);
00365 
00366   uint8_t getSpecStackByte(const simAddress sa) {
00367     map<simAddress, uint8_t>::iterator i = specStackData.find(sa);
00368     if (i != specStackData.end()) {
00369       return i->second;
00370     } else {
00371       simAddress s2 = getStackIdx(sa);
00372       if (s2 <= ppcMaxStackSize) {
00373         return stackData[s2];
00374       } else {
00375         return 0;
00376       }
00377     }
00378   }
00379 
00380   void writeSpecStackByte(const simAddress sa, const uint8_t Data) {
00381     specStackData[sa] = Data;
00382   }
00383 
00384   //: Read 1 byte from the "magic" stack
00385   uint8_t readStack8(const simAddress sa, const bool isSpec) {
00386     if (isSpec) {
00387       return getSpecStackByte(sa);
00388     } else {
00389       simAddress s2 = getStackIdx(sa);
00390       return stackData[s2];
00391     }
00392   }
00393   //: Read 2 bytes from the "magic" stack
00394   uint16_t readStack16(const simAddress sa, const bool isSpec) {
00395     if (isSpec) {
00396       uint16_t r = (getSpecStackByte(sa) << 8);
00397       r += getSpecStackByte(sa+1);
00398       return r;
00399     } else {
00400       simAddress s2 = getStackIdx(sa);
00401       uint16_t *t = (uint16_t*)&stackData[s2];
00402       return (uint16_t)(*t);
00403     }
00404   }
00405   //: Read 4 bytes from the "magic" stack
00406   uint32_t readStack32(const simAddress sa, const bool isSpec) {
00407     if (isSpec) {
00408       uint32_t r = (getSpecStackByte(sa) << 24);
00409       r += getSpecStackByte(sa+1) << 16;
00410       r += getSpecStackByte(sa+2) << 8;
00411       r += getSpecStackByte(sa+3);
00412       return r;
00413     } else {
00414       simAddress s2 = getStackIdx(sa);
00415       if (s2 >= ppcMaxStackSize) {
00416         printf("overstack %p %d > %d\n",
00417                 (void*)(size_t)sa,s2,ppcMaxStackSize);
00418       }
00419       uint32_t *t = (uint32_t*)&stackData[s2];
00420       return (uint32_t)(*t);
00421     }
00422   }
00423   bool writeStack8(const simAddress, const uint8_t, const bool isSpec);
00424   bool writeStack16(const simAddress, const uint16_t, const bool isSpec);
00425   bool writeStack32(const simAddress, const uint32_t, const bool isSpec);
00426 
00427   typedef pair<simAddress,simAddress> adrRange;
00428   static vector<adrRange> constData;
00429 
00430  public:
00431   static vector<thread*> init(processor *p, SST::Component::Params_t& paramsC);
00432   static void deleteThread(thread *t);
00433 #if 0
00434   static bool WriteTextByte(simAddress bDestination, uint8_t Byte); 
00435   static uint32_t ReadTextWord(const simAddress bDestination);
00436 #endif
00437 
00438   ppcThread( processor* hme, simPID, string name = "");
00439   ppcThread() {;}
00440   virtual ~ppcThread();
00441   //: Accessor for program counter
00442   simRegister GetProgramCounter() {return(ProgramCounter);}
00443   //: Magic Stack storage
00444   uint8_t         stackData[ppcMaxStackSize];
00445   //: speculative stack
00446   map<simAddress, uint8_t> specStackData;
00447 
00448 #if 0
00449   //: Program Text
00450   static uint8_t *progText;
00451   static simAddress lastTextAddr;
00452   static vector<simAddress> textRanges;
00453 #endif  
00454 
00455   static bool isText (simAddress addr) {
00456 #if 1
00457     return true;
00458 #else
00459     if (addr > lastTextAddr)
00460       return false;
00461 
00462     int ranges = textRanges.size() >> 1;
00463     for (int i  = 0; i < ranges; i += 2) {
00464       if ((addr >= textRanges[i]) && (addr < textRanges[i+1]))
00465         return true;
00466     }
00467     return false;
00468 #endif
00469   }
00470 
00471 #if 0
00472   static bool writeText (simAddress addr, uint8_t *data, unsigned int size) {
00473     if (lastTextAddr < (addr + size)) {
00474       lastTextAddr = addr + size;
00475       progText = (uint8_t*)realloc(progText, lastTextAddr);
00476     }
00477     textRanges.push_back(addr);
00478     textRanges.push_back(addr + size);
00479 
00480     for (int i = 0; i < size; i++) {
00481       progText[i+addr] = data[i];
00482     }
00483     return true;
00484   }
00485   static bool readText (simAddress addr, uint8_t *buffer, unsigned int size) {
00486     if (addr > lastTextAddr)
00487       return false;
00488     for (int i = 0; i < size; i++) {
00489       buffer[i] = progText[addr+i];
00490     }
00491     return true;
00492   }
00493 #endif  
00494 
00495   virtual instruction* getNextInstruction();
00496   virtual bool squash(instruction * i);
00497   virtual bool retire(instruction *); 
00498   virtual void assimilate(processor *);
00499   virtual void packageToSend(processor *);
00500 
00501   virtual simAddress getStartPC();
00502   virtual bool isPCValid(const simAddress);
00503   virtual instruction* getNextInstruction(const simAddress);
00504   virtual void squashSpec();
00505   virtual void prepareSpec();
00506   virtual bool condemn(instruction*);
00507   simPID pid() const {return _pid;};
00508   virtual void changePid(const simPID p){ _pid = p;}
00509   int getInstructionSize() {return 4;}
00510 
00511   simRegister getStack() const {
00512     if (home) {
00513       return  myFrame[1];
00514     } else {
00515       return packagedRegisters[1];
00516     }
00517   }
00518 
00519   bool isConstSection(const simAddress, const simPID) const;
00520 };
00521 
00522 #endif 

Generated on Fri Oct 22 2010 11:02:21 for SST by  doxygen 1.7.1