00001 
00002 #ifndef MSA_DISTARRAY_H
00003 #define MSA_DISTARRAY_H
00004 
00005 #include <utility>
00006 #include <algorithm>
00007 #include "msa-DistPageMgr.h"
00008 
00009 namespace MSA {
00010 
00011 static const int DEFAULT_SYNC_SINGLE = 0;
00012 static const bool MSA_CLEAR_ALL = true;
00013 
00014 struct MSA_InvalidHandle { };
00015 
00016 template <typename ENTRY>
00017 class Writable
00018 {
00019     ENTRY &e;
00020 
00021 public:
00022     Writable(ENTRY &e_) : e(e_) {}
00023     inline const ENTRY& operator= (const ENTRY& rhs) { e = rhs; return rhs; }
00024 };
00025 
00026 template <class MSA>
00027 class Accumulable
00028 {
00029     typedef typename MSA::T ENTRY;
00030     ENTRY &e;
00031 
00032 public:
00033     Accumulable(ENTRY &e_) : e(e_) {}
00034     template<typename T>
00035     inline void operator+=(const T &rhs)
00036     { MSA::OPS::accumulate(e, rhs); }
00037     template<typename T>
00038     inline void accumulate(const T& rhs)
00039     { MSA::OPS::accumulate(e, rhs); }
00040 };
00041 
00042 template<class MSA> class MSARead;
00043 template<class MSA> class MSAWrite;
00044 template<class MSA> class MSAAccum;
00045 
00046 template<class MSA>
00047 class MSAHandle
00048 {
00049 protected:
00050     MSA *msa;
00051     bool valid;
00052 
00053     inline void checkInvalidate()
00054     {
00055 #if CMK_ERROR_CHECKING
00056         checkValid();
00057         valid = false;
00058 #endif
00059     }
00060 
00061     MSAHandle(MSA *msa_)
00062         : msa(msa_), valid(true)
00063     { }
00064     inline void checkValid()
00065     {
00066 #if CMK_ERROR_CHECKING
00067         if (!valid)
00068             throw MSA_InvalidHandle();
00069 #endif
00070     }
00071 
00072 public:
00073     void syncRelease()
00074     {
00075         checkInvalidate();
00076         if (msa->active)
00077             msa->cache->SyncRelease();
00078         else
00079             CmiAbort("sync from an inactive thread!\n");
00080         msa->active = false;
00081     }
00082 
00083     void syncDone()
00084     {
00085         checkInvalidate();
00086         msa->sync();
00087     }
00088 
00089     MSARead<MSA> syncToRead()
00090     {
00091         checkInvalidate();
00092         msa->sync();
00093         return MSARead<MSA>(msa);
00094     }
00095 
00096     MSAWrite<MSA> syncToWrite()
00097     {
00098         checkInvalidate();
00099         msa->sync();
00100         return MSAWrite<MSA>(msa);
00101     }
00102 
00103     MSAWrite<MSA> syncToReWrite()
00104     {
00105         checkInvalidate();
00106         msa->sync(DEFAULT_SYNC_SINGLE, MSA_CLEAR_ALL);
00107         return MSAWrite<MSA>(msa);
00108     }
00109 
00110     MSAAccum<MSA> syncToAccum()
00111     {
00112         checkInvalidate();
00113         msa->sync();
00114         return MSAAccum<MSA>(msa);
00115     }
00116 
00117     MSAAccum<MSA> syncToEAccum()
00118     {
00119         checkInvalidate();
00120         msa->sync(DEFAULT_SYNC_SINGLE, MSA_CLEAR_ALL);
00121         return MSAAccum<MSA>(msa);
00122     }
00123 
00124     void pup(PUP::er &p)
00125     {
00126         p|valid;
00127         if (valid) {
00128             if (p.isUnpacking())
00129                 msa = new MSA;
00130             p|(*msa);
00131         }
00132         else if (p.isUnpacking())
00133             msa = NULL;
00134     }
00135 
00136     inline int length() { return msa->length(); }
00137 
00138     MSAHandle() : msa(NULL), valid(false) {}
00139 };
00140 
00141 template <class MSA>
00142 class MSARead : public MSAHandle<MSA>
00143 {
00144 protected:
00145     using MSAHandle<MSA>::checkValid;
00146     using MSAHandle<MSA>::checkInvalidate;
00147     using MSAHandle<MSA>::msa;
00148 
00149     typedef typename MSA::T ENTRY;
00150 
00151 public:
00152     MSARead(MSA *msa_)
00153         :  MSAHandle<MSA>(msa_) { }
00154     MSARead() {}
00155 
00156     
00157     inline const ENTRY& get(int x)
00158     {
00159         checkValid();
00160         return msa->get(x);
00161     }
00162     inline const ENTRY& operator()(int x) { return get(x); }
00163     inline const ENTRY& get2(int x)
00164     {
00165         checkValid();
00166         return msa->get2(x);
00167     }
00168 
00169 #ifndef FOR_SUN_CC_ONLY
00170     
00171     inline const ENTRY& get(int x, int y)
00172     {
00173         checkValid();
00174         return msa->get(x, y);
00175     }
00176 #endif
00177     inline const ENTRY& operator()(int x, int y) { return get(x, y); }
00178     inline const ENTRY& get2(int x, int y)
00179     {
00180         checkValid();
00181         return msa->get2(x, y);
00182     }
00183 
00184 #ifndef FOR_SUN_CC_ONLY
00185     
00186     inline const ENTRY& get(int x, int y, int z)
00187     {
00188         checkValid();
00189         return msa->get(x, y, z);
00190     }
00191 #endif
00192     inline const ENTRY& operator()(int x, int y, int z) { return get(x, y, z); }
00193     inline const ENTRY& get2(int x, int y, int z)
00194     {
00195         checkValid();
00196         return msa->get2(x, y, z);
00197     }
00198 
00199     
00200     void read(ENTRY *buf, int x1, int y1, int z1, int x2, int y2, int z2)
00201     {
00202         checkValid();
00203 
00204         CkAssert(x1 <= x2);
00205         CkAssert(y1 <= y2);
00206         CkAssert(z1 <= z2);
00207 
00208         CkAssert(x1 >= msa->xa);
00209         CkAssert(y1 >= msa->ya);
00210         CkAssert(z1 >= msa->za);
00211 
00212         CkAssert(x2 <= msa->xb);
00213         CkAssert(y2 <= msa->yb);
00214         CkAssert(z2 <= msa->zb);
00215 
00216         int i = 0;
00217 
00218         for (int ix = x1; ix <= x2; ++ix)
00219             for (int iy = y1; iy <= y2; ++iy)
00220                 for (int iz = z1; iz <= z2; ++iz)
00221                     buf[i++] = msa->get(ix, iy, iz);
00222     }
00223 };
00224 
00225 template <class MSA>
00226 class MSAWrite : public MSAHandle<MSA>
00227 {
00228 protected:
00229     using MSAHandle<MSA>::checkValid;
00230     using MSAHandle<MSA>::checkInvalidate;
00231     using MSAHandle<MSA>::msa;
00232 
00233     typedef typename MSA::T ENTRY;
00234 
00235 public:
00236     MSAWrite(MSA *msa_)
00237         : MSAHandle<MSA>(msa_) { }
00238     MSAWrite() {}
00239 
00240     
00241     inline Writable<ENTRY> set(int x)
00242     {
00243         checkValid();
00244         return Writable<ENTRY>(msa->set(x));
00245     }
00246     inline Writable<ENTRY> operator()(int x)
00247     {
00248         return set(x);
00249     }
00250 
00251     
00252     inline Writable<ENTRY> set(int x, int y)
00253     {
00254         checkValid();
00255         return Writable<ENTRY>(msa->set(x,y));
00256     }
00257     inline Writable<ENTRY> operator()(int x, int y)
00258     {
00259         return set(x,y);
00260     }
00261 
00262     
00263     inline Writable<ENTRY> set(int x, int y, int z)
00264     {
00265         checkValid();
00266         return Writable<ENTRY>(msa->set(x,y,z));
00267     }
00268     inline Writable<ENTRY> operator()(int x, int y, int z)
00269     {
00270         return set(x,y,z);
00271     }
00272 
00273     void write(int x1, int y1, int z1, int x2, int y2, int z2, const ENTRY *buf)
00274     {
00275         checkValid();
00276 
00277         CkAssert(x1 <= x2);
00278         CkAssert(y1 <= y2);
00279         CkAssert(z1 <= z2);
00280 
00281         CkAssert(x1 >= msa->xa);
00282         CkAssert(y1 >= msa->ya);
00283         CkAssert(z1 >= msa->za);
00284 
00285         CkAssert(x2 <= msa->xb);
00286         CkAssert(y2 <= msa->yb);
00287         CkAssert(z2 <= msa->zb);
00288 
00289         int i = 0;
00290 
00291         for (int ix = x1; ix <= x2; ++ix)
00292             for (int iy = y1; iy <= y2; ++iy)
00293                 for (int iz = z1; iz <= z2; ++iz)
00294                     {
00295                         msa->set(ix, iy, iz) = buf[i++];
00296                     }
00297     }
00298 };
00299 
00300 template<class MSA>
00301 class MSAAccum : public MSAHandle<MSA>
00302 {
00303 protected:
00304     using MSAHandle<MSA>::checkValid;
00305     using MSAHandle<MSA>::checkInvalidate;
00306     using MSAHandle<MSA>::msa;
00307 
00308     typedef typename MSA::T ENTRY;
00309 
00310 public:
00311     MSAAccum(MSA *msa_)
00312         : MSAHandle<MSA>(msa_) { }
00313     MSAAccum() {}
00314 
00315     
00316     inline Accumulable<MSA> accumulate(int x)
00317     {
00318         checkValid();
00319         return Accumulable<MSA>(msa->accumulate(x));
00320     }
00321     inline Accumulable<MSA> operator() (int x)
00322     { return accumulate(x); }
00323 
00324 #ifndef FOR_SUN_CC_ONLY
00325     
00326     inline Accumulable<MSA> accumulate(int x, int y)
00327     {
00328         checkValid();
00329         return Accumulable<MSA>(msa->accumulate(x,y));
00330     }
00331 #endif
00332     inline Accumulable<MSA> operator() (int x, int y)
00333     { return accumulate(x,y); }
00334 
00335 #ifndef FOR_SUN_CC_ONLY
00336     
00337     inline Accumulable<MSA> accumulate(int x, int y, int z)
00338     {
00339         checkValid();
00340         return Accumulable<MSA>(msa->accumulate(x,y,z));
00341     }
00342 #endif
00343     inline Accumulable<MSA> operator() (int x, int y, int z)
00344     { return accumulate(x,y,z); }
00345 
00346 #ifndef FOR_SUN_CC_ONLY
00347     void accumulate(int x1, int y1, int z1, int x2, int y2, int z2, const ENTRY *buf)
00348     {
00349         checkValid();
00350         CkAssert(x1 <= x2);
00351         CkAssert(y1 <= y2);
00352         CkAssert(z1 <= z2);
00353 
00354         CkAssert(x1 >= msa->xa);
00355         CkAssert(y1 >= msa->ya);
00356         CkAssert(z1 >= msa->za);
00357 
00358         CkAssert(x2 <= msa->xb);
00359         CkAssert(y2 <= msa->yb);
00360         CkAssert(z2 <= msa->zb);
00361 
00362         int i = 0;
00363 
00364         for (int ix = x1; ix <= x2; ++ix)
00365             for (int iy = y1; iy <= y2; ++iy)
00366                 for (int iz = z1; iz <= z2; ++iz)
00367                     msa->accumulate(ix, iy, iz, buf[i++]);
00368     }
00369 #endif
00370 };
00371 
00372 
00393 template<class ENTRY, class ENTRY_OPS_CLASS, unsigned int ENTRIES_PER_PAGE=MSA_DEFAULT_ENTRIES_PER_PAGE>
00394 class MSA1D
00395 {
00396 public:
00397     typedef MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CacheGroup_t;
00398     typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
00399     typedef CProxy_MSA_PageArray<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_PageArray_t;
00400 
00401     typedef ENTRY T;
00402     typedef ENTRY_OPS_CLASS OPS;
00403     typedef MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
00404     typedef MSAHandle<thisMSA> Handle;
00405     typedef MSARead<thisMSA> Read;
00406     typedef MSAAccum<thisMSA> Accum;
00407     typedef MSAWrite<thisMSA> Write;
00408     friend class MSAHandle<thisMSA>;
00409     friend class MSARead<thisMSA>;
00410     friend class MSAWrite<thisMSA>;
00411     friend class MSAAccum<thisMSA>;
00412 
00413 protected:
00415     unsigned int nEntries;
00416     bool initHandleGiven;
00417 
00419     CacheGroup_t* cache;
00420     CProxy_CacheGroup_t cg;
00421 
00422     inline const ENTRY* readablePage(unsigned int page)
00423     {
00424         return (const ENTRY*)(cache->readablePage(page));
00425     }
00426 
00427     
00428     inline const ENTRY* readablePage2(unsigned int page)
00429     {
00430         return (const ENTRY*)(cache->readablePage2(page));
00431     }
00432 
00433     
00434     
00435     inline ENTRY* writeablePage(unsigned int page, unsigned int offset)
00436     {
00437         return (ENTRY*)(cache->writeablePage(page, offset));
00438     }
00439 
00440 public:
00441     
00442     inline MSA1D() 
00443         :initHandleGiven(false) 
00444     {}
00445 
00446     virtual void pup(PUP::er &p){
00447         p|nEntries;
00448         p|cg;
00449         if (p.isUnpacking()) cache=cg.ckLocalBranch();
00450     }
00451 
00456     inline MSA1D(unsigned int nEntries_, unsigned int num_wrkrs, 
00457                  unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES) 
00458         : nEntries(nEntries_), initHandleGiven(false)
00459     {
00460         
00461         unsigned int nPages = (nEntries + ENTRIES_PER_PAGE - 1)/ENTRIES_PER_PAGE;
00462         CProxy_PageArray_t pageArray = CProxy_PageArray_t::ckNew(nPages);
00463         cg = CProxy_CacheGroup_t::ckNew(nPages, pageArray, maxBytes, nEntries, num_wrkrs);
00464         pageArray.setCacheProxy(cg);
00465         pageArray.ckSetReductionClient(new CkCallback(CkIndex_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>::SyncDone(NULL), cg));
00466         cache = cg.ckLocalBranch();
00467     }
00468 
00469     
00470     inline MSA1D(CProxy_CacheGroup_t cg_) : cg(cg_), initHandleGiven(false)
00471     {
00472         cache = cg.ckLocalBranch();
00473         nEntries = cache->getNumEntries();
00474     }
00475 
00476     inline ~MSA1D()
00477     {
00478         
00479         
00480         
00481         
00482                 cache->unroll();
00483  
00484     }
00485 
00490     inline void changePE()
00491     {
00492         cache = cg.ckLocalBranch();
00493 
00494         
00495     }
00496 
00497     
00499     inline unsigned int length() const { return nEntries; }
00500 
00501     inline const CProxy_CacheGroup_t &getCacheGroup() const { return cg; }
00502 
00503     
00504     
00505     inline unsigned int getNumEntriesPerPage() const { return ENTRIES_PER_PAGE; }
00506 
00508     inline unsigned int getPageIndex(unsigned int idx)
00509     {
00510         return idx / ENTRIES_PER_PAGE;
00511     }
00512 
00514     inline unsigned int getOffsetWithinPage(unsigned int idx)
00515     {
00516         return idx % ENTRIES_PER_PAGE;
00517     }
00518 
00519     
00520 
00521     
00522     
00523     
00524     
00525     
00526     
00527     inline void enroll(int num_workers)
00528     {
00529         
00530         
00531         
00532         
00533         cache->enroll(num_workers);
00534     }
00535 
00536     
00537     
00538     
00539     
00540     inline ENTRY& getPageBottom(unsigned int idx, MSA_Page_Fault_t accessMode)
00541     {
00542         if (accessMode==Read_Fault) {
00543             unsigned int page = idx / ENTRIES_PER_PAGE;
00544             return const_cast<ENTRY&>(readablePage(page)[0]);
00545         } else {
00546             CkAssert(accessMode==Write_Fault || accessMode==Accumulate_Fault);
00547             unsigned int page = idx / ENTRIES_PER_PAGE;
00548             unsigned int offset = idx % ENTRIES_PER_PAGE;
00549             ENTRY* e=writeablePage(page, offset);
00550             return e[0];
00551         }
00552     }
00553 
00554     inline void FreeMem()
00555     {
00556         cache->FreeMem();
00557     }
00558 
00562     inline void Prefetch(unsigned int start, unsigned int end)
00563     {
00564         unsigned int page1 = start / ENTRIES_PER_PAGE;
00565         unsigned int page2 = end / ENTRIES_PER_PAGE;
00566         cache->Prefetch(page1, page2);
00567     }
00568 
00570     inline int WaitAll()    { return cache->WaitAll(); }
00571 
00573     inline void Unlock()    { return cache->UnlockPages(); }
00574 
00581     inline void Unlock(unsigned int start, unsigned int end)
00582     {
00583         unsigned int page1 = start / ENTRIES_PER_PAGE;
00584         unsigned int page2 = end / ENTRIES_PER_PAGE;
00585         cache->UnlockPages(page1, page2);
00586     }
00587 
00588     inline Write getInitialWrite()
00589     {
00590         if (initHandleGiven)
00591             throw MSA_InvalidHandle();
00592 
00593         initHandleGiven = true;
00594         return Write(this);
00595     }
00596 
00597     inline Accum getInitialAccum()
00598     {
00599         if (initHandleGiven)
00600             throw MSA_InvalidHandle();
00601 
00602         initHandleGiven = true;
00603         return Accum(this);
00604     }
00605 
00606   
00607   
00608 protected:
00611     inline const ENTRY& get(unsigned int idx)
00612     {
00613         unsigned int page = idx / ENTRIES_PER_PAGE;
00614         unsigned int offset = idx % ENTRIES_PER_PAGE;
00615         return readablePage(page)[offset];
00616     }
00617 
00618     inline const ENTRY& operator[](unsigned int idx)
00619     {
00620         return get(idx);
00621     }
00622 
00627     inline const ENTRY& get2(unsigned int idx)
00628     {
00629         unsigned int page = idx / ENTRIES_PER_PAGE;
00630         unsigned int offset = idx % ENTRIES_PER_PAGE;
00631         return readablePage2(page)[offset];
00632     }
00633 
00637     inline ENTRY& set(unsigned int idx)
00638     {
00639         unsigned int page = idx / ENTRIES_PER_PAGE;
00640         unsigned int offset = idx % ENTRIES_PER_PAGE;
00641         ENTRY* e=writeablePage(page, offset);
00642         return e[offset];
00643     }
00644 
00649     inline ENTRY& accumulate(unsigned int idx)
00650     {
00651         unsigned int page = idx / ENTRIES_PER_PAGE;
00652         unsigned int offset = idx % ENTRIES_PER_PAGE;
00653         return cache->accumulate(page, offset);
00654     }
00655     
00659     inline void accumulate(unsigned int idx, const ENTRY& ent)
00660     {
00661         ENTRY_OPS_CLASS::accumulate(accumulate(idx),ent);
00662     }
00663 
00665     inline void sync(int single=0, bool clear = false)
00666     {
00667         cache->SyncReq(single, clear);
00668     }
00669 };
00670 
00671 
00672 
00673 
00674 template<class ENTRY, class ENTRY_OPS_CLASS, unsigned int ENTRIES_PER_PAGE=MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_Array_Layout_t ARRAY_LAYOUT=MSA_ROW_MAJOR>
00675 class MSA2D : public MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>
00676 {
00677 public:
00678     typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
00679     typedef MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> super;
00680 
00681     typedef ENTRY T;
00682     typedef ENTRY_OPS_CLASS OPS;
00683     typedef MSA2D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
00684     typedef MSAHandle<thisMSA> Handle;
00685     typedef MSARead<thisMSA> Read;
00686     typedef MSAAccum<thisMSA> Accum;
00687     typedef MSAWrite<thisMSA> Write;
00688     friend class MSAHandle<thisMSA>;
00689     friend class MSARead<thisMSA>;
00690     friend class MSAWrite<thisMSA>;
00691     friend class MSAAccum<thisMSA>;
00692 
00693 protected:
00694     unsigned int rows, cols;
00695 
00696 public:
00697     
00698     inline MSA2D() : super() {}
00699     virtual void pup(PUP::er &p) {
00700        super::pup(p);
00701        p|rows; p|cols;
00702     };
00703 
00704     inline MSA2D(unsigned int rows_, unsigned int cols_, unsigned int numwrkrs,
00705                  unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES)
00706         :super(rows_*cols_, numwrkrs, maxBytes)
00707     {
00708         rows = rows_; cols = cols_;
00709     }
00710 
00711     inline MSA2D(unsigned int rows_, unsigned int cols_, CProxy_CacheGroup_t cg_)
00712         : rows(rows_), cols(cols_), super(cg_)
00713     {}
00714 
00715     
00716     inline unsigned int getIndex(unsigned int row, unsigned int col)
00717     {
00718         unsigned int index;
00719 
00720         if(ARRAY_LAYOUT==MSA_ROW_MAJOR)
00721             index = row*cols + col;
00722         else
00723             index = col*rows + row;
00724 
00725         return index;
00726     }
00727 
00728     
00729     inline unsigned int getPageIndex(unsigned int row, unsigned int col)
00730     {
00731         return getIndex(row, col)/ENTRIES_PER_PAGE;
00732     }
00733 
00734     inline unsigned int getOffsetWithinPage(unsigned int row, unsigned int col)
00735     {
00736         return getIndex(row, col)%ENTRIES_PER_PAGE;
00737     }
00738 
00739     inline unsigned int getRows(void) const {return rows;}
00740     inline unsigned int getCols(void) const {return cols;}
00741     inline unsigned int getColumns(void) const {return cols;}
00742     inline MSA_Array_Layout_t getArrayLayout() const {return ARRAY_LAYOUT;}
00743 
00744     inline void Prefetch(unsigned int start, unsigned int end)
00745     {
00746         
00747         if(start > end)
00748         {
00749             unsigned int temp = start;
00750             start = end;
00751             end = temp;
00752         }
00753 
00754         unsigned int index1 = (ARRAY_LAYOUT==MSA_ROW_MAJOR) ? getIndex(start, 0) : getIndex(0, start);
00755         unsigned int index2 = (ARRAY_LAYOUT==MSA_ROW_MAJOR) ? getIndex(end, cols-1) : getIndex(rows-1, end);
00756 
00757         MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>::Prefetch(index1, index2);
00758     }
00759 
00760     
00761     inline void UnlockPages(unsigned int start, unsigned int end)
00762     {
00763         if(start > end)
00764         {
00765             unsigned int temp = start;
00766             start = end;
00767             end = temp;
00768         }
00769 
00770         unsigned int index1 = (ARRAY_LAYOUT==MSA_ROW_MAJOR) ? getIndex(start, 0) : getIndex(0, start);
00771         unsigned int index2 = (ARRAY_LAYOUT==MSA_ROW_MAJOR) ? getIndex(end, cols-1) : getIndex(rows-1, end);
00772 
00773         MSA1D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE>::Unlock(index1, index2);
00774     }
00775 
00776     inline Write getInitialWrite()
00777     {
00778         if (super::initHandleGiven)
00779             throw MSA_InvalidHandle();
00780 
00781         super::initHandleGiven = true;
00782         return Write(this);
00783     }
00784 
00785     inline Accum getInitialAccum()
00786     {
00787         if (super::initHandleGiven)
00788             throw MSA_InvalidHandle();
00789 
00790         super::initHandleGiven = true;
00791         return Accum(this);
00792     }
00793 
00794 protected:
00795     inline const ENTRY& get(unsigned int row, unsigned int col)
00796     {
00797         return super::get(getIndex(row, col));
00798     }
00799 
00800     
00801     inline const ENTRY& get2(unsigned int row, unsigned int col)
00802     {
00803         return super::get2(getIndex(row, col));
00804     }
00805 
00806     
00807     inline ENTRY& set(unsigned int row, unsigned int col)
00808     {
00809         return super::set(getIndex(row, col));
00810     }
00811 };
00812 
00833 template<class ENTRY, class ENTRY_OPS_CLASS, unsigned int ENTRIES_PER_PAGE>
00834 class MSA3D
00835 {
00837     int xa, xb, ya, yb, za, zb;
00839     unsigned dim_x, dim_y, dim_z;
00840 
00841 public:
00842     typedef MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CacheGroup_t;
00843     typedef CProxy_MSA_CacheGroup<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_CacheGroup_t;
00844     typedef CProxy_MSA_PageArray<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> CProxy_PageArray_t;
00845 
00846     typedef ENTRY T;
00847     typedef ENTRY_OPS_CLASS OPS;
00848     typedef MSA3D<ENTRY, ENTRY_OPS_CLASS, ENTRIES_PER_PAGE> thisMSA;
00849     typedef MSAHandle<thisMSA> Handle;
00850     typedef MSARead<thisMSA> Read;
00851     typedef MSAAccum<thisMSA> Accum;
00852     typedef MSAWrite<thisMSA> Write;
00853     friend class MSAHandle<thisMSA>;
00854     friend class MSARead<thisMSA>;
00855     friend class MSAWrite<thisMSA>;
00856     friend class MSAAccum<thisMSA>;
00857 
00858 protected:
00860     unsigned int nEntries;
00861     bool initHandleGiven;
00862 
00864     CacheGroup_t* cache;
00865     CProxy_CacheGroup_t cg;
00866 
00867     inline const ENTRY* readablePage(unsigned int page)
00868     {
00869         return (const ENTRY*)(cache->readablePage(page));
00870     }
00871 
00872     
00873     inline const ENTRY* readablePage2(unsigned int page)
00874     {
00875         return (const ENTRY*)(cache->readablePage2(page));
00876     }
00877 
00878     
00879     
00880     inline ENTRY* writeablePage(unsigned int page, unsigned int offset)
00881     {
00882         return (ENTRY*)(cache->writeablePage(page, offset));
00883     }
00884 
00885 public:
00886     
00887     inline MSA3D() 
00888         :initHandleGiven(false) 
00889     {}
00890 
00891     virtual void pup(PUP::er &p){
00892         p|xa; p|xb;
00893         p|ya; p|yb;
00894         p|za; p|zb;
00895         p|dim_x;
00896         p|dim_y;
00897         p|dim_z;
00898         p|nEntries;
00899         p|cg;
00900         if (p.isUnpacking()) cache=cg.ckLocalBranch();
00901     }
00902 
00909     inline MSA3D(unsigned x, unsigned y, unsigned z, unsigned int num_wrkrs, 
00910                  unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES)
00911         : xa(0), ya(0), za(0), xb(x-1), yb(y-1), zb(z-1), dim_x(x), dim_y(y), dim_z(z),
00912           initHandleGiven(false)
00913     {
00914         unsigned nEntries = x*y*z;
00915         unsigned int nPages = (nEntries + ENTRIES_PER_PAGE - 1)/ENTRIES_PER_PAGE;
00916         CProxy_PageArray_t pageArray = CProxy_PageArray_t::ckNew(nPages);
00917         cg = CProxy_CacheGroup_t::ckNew(nPages, pageArray, maxBytes, nEntries, num_wrkrs);
00918         pageArray.setCacheProxy(cg);
00919         
00920         cache = cg.ckLocalBranch();
00921     }
00922 
00929     inline MSA3D(int xa_, int xb_, int ya_, int yb_, int za_, int zb_,
00930                  unsigned int num_wrkrs, unsigned int maxBytes=MSA_DEFAULT_MAX_BYTES)
00931         : xa(xa_), xb(xb_), ya(ya_), yb(yb_), za(za_), zb(zb_),
00932           dim_x(xb-xa+1), dim_y(yb-ya+1), dim_z(zb-za+1),
00933           initHandleGiven(false)
00934     {
00935         unsigned nEntries = dim_x*dim_y*dim_z;
00936         unsigned int nPages = (nEntries + ENTRIES_PER_PAGE - 1)/ENTRIES_PER_PAGE;
00937         CProxy_PageArray_t pageArray = CProxy_PageArray_t::ckNew(nPages);
00938         cg = CProxy_CacheGroup_t::ckNew(nPages, pageArray, maxBytes, nEntries, num_wrkrs);
00939         pageArray.setCacheProxy(cg);
00940         
00941         cache = cg.ckLocalBranch();
00942     }
00943 
00944     inline ~MSA3D()
00945     {
00946         
00947         
00948         
00949         
00950         
00951         
00952     }
00953 
00958     inline void changePE()
00959     {
00960         cache = cg.ckLocalBranch();
00961 
00962         
00963     }
00964 
00965     
00966 
00967     inline const CProxy_CacheGroup_t &getCacheGroup() const { return cg; }
00968 
00969     
00970     
00971     inline unsigned int getNumEntriesPerPage() const { return ENTRIES_PER_PAGE; }
00972 
00973     inline unsigned int index(unsigned x, unsigned y, unsigned z)
00974     {
00975         x -= xa;
00976         y -= ya;
00977         z -= za;
00978         CkAssert(x < dim_x);
00979         CkAssert(y < dim_y);
00980         CkAssert(z < dim_z);
00981         return ((x*dim_y) + y) * dim_z + z;
00982     }
00983     
00985     inline unsigned int getPageIndex(unsigned int idx)
00986     {
00987         return idx / ENTRIES_PER_PAGE;
00988     }
00989 
00991     inline unsigned int getOffsetWithinPage(unsigned int idx)
00992     {
00993         return idx % ENTRIES_PER_PAGE;
00994     }
00995 
00996     
00997 
00998     
00999     
01000     
01001     
01002     
01003     
01004     inline void enroll(int num_workers)
01005     {
01006         
01007         
01008         
01009         
01010         cache->enroll(num_workers);
01011     }
01012 
01013     void enroll()
01014     {
01015         cache->enroll();
01016     }
01017 
01018     
01019     
01020     
01021     
01022     inline ENTRY& getPageBottom(unsigned int idx, MSA_Page_Fault_t accessMode)
01023     {
01024         if (accessMode==Read_Fault) {
01025             unsigned int page = idx / ENTRIES_PER_PAGE;
01026             return const_cast<ENTRY&>(readablePage(page)[0]);
01027         } else {
01028             CkAssert(accessMode==Write_Fault || accessMode==Accumulate_Fault);
01029             unsigned int page = idx / ENTRIES_PER_PAGE;
01030             unsigned int offset = idx % ENTRIES_PER_PAGE;
01031             ENTRY* e=writeablePage(page, offset);
01032             return e[0];
01033         }
01034     }
01035 
01036     inline void FreeMem()
01037     {
01038         cache->FreeMem();
01039     }
01040 
01044     inline void Prefetch(unsigned int start, unsigned int end)
01045     {
01046         unsigned int page1 = start / ENTRIES_PER_PAGE;
01047         unsigned int page2 = end / ENTRIES_PER_PAGE;
01048         cache->Prefetch(page1, page2);
01049     }
01050 
01052     inline int WaitAll()    { return cache->WaitAll(); }
01053 
01055     inline void Unlock()    { return cache->UnlockPages(); }
01056 
01063     inline void Unlock(unsigned int start, unsigned int end)
01064     {
01065         unsigned int page1 = start / ENTRIES_PER_PAGE;
01066         unsigned int page2 = end / ENTRIES_PER_PAGE;
01067         cache->UnlockPages(page1, page2);
01068     }
01069 
01070     inline Write getInitialWrite()
01071     {
01072         if (initHandleGiven)
01073             CmiAbort("Trying to get an MSA's initial handle a second time");
01074 
01075         initHandleGiven = true;
01076         return Write(this);
01077     }
01078 
01079     inline Accum getInitialAccum()
01080     {
01081         if (initHandleGiven)
01082             CmiAbort("Trying to get an MSA's initial handle a second time");
01083 
01084         initHandleGiven = true;
01085         return Accum(this);
01086     }
01087 
01088   
01089   
01090 protected:
01093     inline const ENTRY& get(unsigned x, unsigned y, unsigned z)
01094     {
01095         unsigned int idx = index(x,y,z);
01096         unsigned int page = idx / ENTRIES_PER_PAGE;
01097         unsigned int offset = idx % ENTRIES_PER_PAGE;
01098         return readablePage(page)[offset];
01099     }
01100 
01105     inline const ENTRY& get2(unsigned x, unsigned y, unsigned z)
01106     {
01107         unsigned int idx = index(x,y,z);
01108         unsigned int page = idx / ENTRIES_PER_PAGE;
01109         unsigned int offset = idx % ENTRIES_PER_PAGE;
01110         return readablePage2(page)[offset];
01111     }
01112 
01116     inline ENTRY& set(unsigned x, unsigned y, unsigned z)
01117     {
01118         unsigned int idx = index(x,y,z);
01119         unsigned int page = idx / ENTRIES_PER_PAGE;
01120         unsigned int offset = idx % ENTRIES_PER_PAGE;
01121         ENTRY* e=writeablePage(page, offset);
01122         return e[offset];
01123     }
01124 
01129     inline ENTRY& accumulate(unsigned x, unsigned y, unsigned z)
01130     {
01131         unsigned int idx = index(x,y,z);
01132         unsigned int page = idx / ENTRIES_PER_PAGE;
01133         unsigned int offset = idx % ENTRIES_PER_PAGE;
01134         return cache->accumulate(page, offset);
01135     }
01136     
01140     inline void accumulate(unsigned x, unsigned y, unsigned z, const ENTRY& ent)
01141     {
01142         ENTRY_OPS_CLASS::accumulate(accumulate(x,y,z),ent);
01143     }
01144 
01146     inline void sync(int single=0, bool clear = false)
01147     {
01148         cache->SyncReq(single, clear);
01149     }
01150 };
01151 
01152 }
01153 #endif