src/Sim/Memory/MemOrderManager/MemOrderOperations.cpp

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
00028 // 
00029 // 
00030 
00031 
00032 #include <pch.h>
00033 
00034 #include "Sim/Memory/MemOrderManager/MemOrderOperations.h"
00035 
00036 #include "SysDeps/Endian.h"
00037 #include "Utility/RuntimeError.h"
00038 
00039 using namespace std;
00040 using namespace Onikiri;
00041 
00042 MemOrderOperations::MemOrderOperations() :
00043     m_targetIsLittleEndian(false),
00044     m_memoryAlignment(1),
00045     m_memoryAlignmentMask(~((u64)0))
00046 {
00047 }
00048 
00049 void MemOrderOperations::SetAlignment( int alignment )
00050 {
00051     ASSERT( alignment > 0 );
00052     m_memoryAlignment = alignment;
00053 
00054     int bits = 0;
00055     for( u64 a = alignment; a != 0; a >>= 1 ){
00056         bits++;
00057     }
00058     bits--;
00059     m_memoryAlignmentMask = shttl::mask( bits, 64-bits );
00060 }
00061 
00062 
00063 //
00064 // store-load forwarding on LS-queue
00065 //
00066 
00067 u64 MemOrderOperations::ReadPreviousAccess( 
00068     const MemAccess& load, const MemAccess& store )
00069 {
00070     //
00071     // ** load access area is sure to be inner of store area.
00072     //
00073     //      store addr               
00074     //           |
00075     // store:    |<----------store-size----------->|
00076     // load :    |<--sh-->|<--load-size-->|
00077     //                    |
00078     //                load-addr       
00079     //
00080     // If a target architecture is big endian, 
00081     // a store value is converted to memory image of the store value (little endian), and 
00082     // load a part of the converted store value and convert it again.
00083     //
00084     //
00085 
00086     u64 storeRegValue = store.value;
00087     u64 storeMemValue = CorrectEndian( storeRegValue, store.size );
00088 
00089     u64 sh   = 8 * (load.address.address - store.address.address);
00090     u64 mask = shttl::mask(0, load.size * 8);
00091 
00092     u64 loadMemValue = (storeMemValue >> sh) & mask;
00093     u64 loadRegValue = CorrectEndian( loadMemValue, load.size );
00094 
00095     return loadRegValue;    
00096 }
00097 
00098 u64 MemOrderOperations::MergePartialAccess( const MemAccess& base, const MemAccess& store )
00099 {
00100     u64 baseAddr   = base.address.address;
00101     u64 storeAddr  = store.address.address;
00102     u64 storeValue = CorrectEndian( store.value, store.sign );
00103     s64 storeSize  = store.size;
00104 
00105     u64 merged = base.value;
00106 
00107     if( baseAddr < storeAddr ){
00108         // base   <----->
00109         // store      <------>
00110         // start      ^
00111         s64 start = storeAddr - baseAddr;
00112         for( int i = 0; i < storeSize; ++i ){
00113             s64 baseOffset  = i + start;
00114             if( baseOffset >= base.size )
00115                 break;
00116             merged = 
00117                 shttl::deposit( merged, baseOffset*8, 8, (storeValue >> (i*8)) & 0xff );
00118         }
00119     }
00120     else{
00121         // base       <----->
00122         // store  <------>
00123         // start      ^
00124         s64 start = baseAddr - storeAddr;
00125         for( int i = 0; i < storeSize; ++i ){
00126             s64 baseOffset  = i - start;
00127             if( baseOffset < 0 )
00128                 continue;
00129             if( baseOffset >= base.size )
00130                 break;
00131             merged = 
00132                 shttl::deposit( merged, baseOffset*8, 8, (storeValue >> (i*8)) & 0xff );
00133         }
00134 
00135     }
00136 
00137     return merged;
00138 }
00139 
00140 // Convert endian for store-load forwarding.
00141 u64 MemOrderOperations::CorrectEndian( u64 src, int size )
00142 {
00143     if( m_targetIsLittleEndian )
00144         return src; // Do not need conversion.
00145 
00146     switch( size ){
00147     case 1:
00148         return (u64)ConvertEndian((u8)src);
00149     case 2:
00150         return (u64)ConvertEndian((u16)src);
00151     case 4:
00152         return (u64)ConvertEndian((u32)src);
00153     case 8:
00154         return (u64)ConvertEndian((u64)src);
00155     default:
00156         THROW_RUNTIME_ERROR( "Invalid size." );
00157         return 0;
00158     }
00159 
00160 }
00161     
00162 // ANZXd
00163 bool MemOrderOperations::IsOverlapped(const MemAccess& access1, const MemAccess& access2) const
00164 {
00165     return IsOverlapped(access1.address.address, access1.size, access2.address.address, access2.size);
00166 }
00167 
00168 bool MemOrderOperations::IsOverlapped(u64 addr1, int size1, u64 addr2, int size2) const
00169 {
00170     return
00171         (addr1 <= addr2 && addr2 < addr1+size1) ||
00172         (addr2 <= addr1 && addr1 < addr2+size2);
00173 }
00174 
00175 bool MemOrderOperations::IsOverlappedInAligned( const MemAccess& access1, const MemAccess& access2 ) const
00176 {
00177     return IsOverlappedInAligned(access1.address.address, access1.size, access2.address.address, access2.size);
00178 }
00179 
00180 bool MemOrderOperations::IsOverlappedInAligned( u64 addr1, int size1, u64 addr2, int size2 ) const
00181 {
00182     return (addr1 & m_memoryAlignmentMask) == (addr2 & m_memoryAlignmentMask);
00183 }
00184 
00185 // Returns whether a 'inner' access is in a 'outer' access or not.
00186 bool MemOrderOperations::IsInnerAccess( const MemAccess& inner, const MemAccess& outer ) const
00187 {
00188     return IsInnerAccess(inner.address.address, inner.size, outer.address.address, outer.size);
00189 }
00190 
00191 bool MemOrderOperations::IsInnerAccess( u64 inner, int innerSize, u64 outer, int outerSize ) const
00192 {
00193     //             inner   inner+size
00194     // inner:        <------->
00195     // outer:     <------------->
00196     //          outer       outer+size
00197     return (outer <= inner) && ((inner + innerSize) <= (outer + outerSize));
00198 }

Onikiri2に対してTue Jun 18 14:34:24 2013に生成されました。  doxygen 1.4.7