diff options
author | Tony Gutierrez <anthony.gutierrez@amd.com> | 2016-01-19 14:05:03 -0500 |
---|---|---|
committer | Tony Gutierrez <anthony.gutierrez@amd.com> | 2016-01-19 14:05:03 -0500 |
commit | 28e353e0403ea379d244a418e8dc8ee0b48187cf (patch) | |
tree | 64bf9dcdf22bf7f60668f790744c11ee8ec2f2bf /src/mem/ruby/common | |
parent | d658b6e1cc22de852fef611e28f448257acc298a (diff) | |
download | gem5-28e353e0403ea379d244a418e8dc8ee0b48187cf.tar.xz |
mem: write combining for ruby protocols
This patch adds support for write-combining in ruby.
Diffstat (limited to 'src/mem/ruby/common')
-rw-r--r-- | src/mem/ruby/common/DataBlock.cc | 27 | ||||
-rw-r--r-- | src/mem/ruby/common/DataBlock.hh | 6 | ||||
-rw-r--r-- | src/mem/ruby/common/SConscript | 1 | ||||
-rw-r--r-- | src/mem/ruby/common/WriteMask.cc | 46 | ||||
-rw-r--r-- | src/mem/ruby/common/WriteMask.hh | 202 |
5 files changed, 282 insertions, 0 deletions
diff --git a/src/mem/ruby/common/DataBlock.cc b/src/mem/ruby/common/DataBlock.cc index fb2e956e0..a4d7f4916 100644 --- a/src/mem/ruby/common/DataBlock.cc +++ b/src/mem/ruby/common/DataBlock.cc @@ -27,6 +27,8 @@ */ #include "mem/ruby/common/DataBlock.hh" + +#include "mem/ruby/common/WriteMask.hh" #include "mem/ruby/system/RubySystem.hh" DataBlock::DataBlock(const DataBlock &cp) @@ -57,6 +59,25 @@ DataBlock::equal(const DataBlock& obj) const } void +DataBlock::copyPartial(const DataBlock &dblk, const WriteMask &mask) +{ + for (int i = 0; i < RubySystem::getBlockSizeBytes(); i++) { + if (mask.getMask(i, 1)) { + m_data[i] = dblk.m_data[i]; + } + } +} + +void +DataBlock::atomicPartial(const DataBlock &dblk, const WriteMask &mask) +{ + for (int i = 0; i < RubySystem::getBlockSizeBytes(); i++) { + m_data[i] = dblk.m_data[i]; + } + mask.performAtomic(m_data); +} + +void DataBlock::print(std::ostream& out) const { using namespace std; @@ -77,6 +98,12 @@ DataBlock::getData(int offset, int len) const return &m_data[offset]; } +uint8_t* +DataBlock::getDataMod(int offset) +{ + return &m_data[offset]; +} + void DataBlock::setData(const uint8_t *data, int offset, int len) { diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index 49ce3624a..d52b6fa72 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -35,6 +35,8 @@ #include <iomanip> #include <iostream> +class WriteMask; + class DataBlock { public: @@ -58,8 +60,12 @@ class DataBlock void clear(); uint8_t getByte(int whichByte) const; const uint8_t *getData(int offset, int len) const; + uint8_t *getDataMod(int offset); void setByte(int whichByte, uint8_t data); void setData(const uint8_t *data, int offset, int len); + void copyPartial(const DataBlock &dblk, int offset, int len); + void copyPartial(const DataBlock &dblk, const WriteMask &mask); + void atomicPartial(const DataBlock & dblk, const WriteMask & mask); bool equal(const DataBlock& obj) const; void print(std::ostream& out) const; diff --git a/src/mem/ruby/common/SConscript b/src/mem/ruby/common/SConscript index 9e809f0d0..a19268cba 100644 --- a/src/mem/ruby/common/SConscript +++ b/src/mem/ruby/common/SConscript @@ -41,3 +41,4 @@ Source('Histogram.cc') Source('IntVec.cc') Source('NetDest.cc') Source('SubBlock.cc') +Source('WriteMask.cc') diff --git a/src/mem/ruby/common/WriteMask.cc b/src/mem/ruby/common/WriteMask.cc new file mode 100644 index 000000000..4585077a6 --- /dev/null +++ b/src/mem/ruby/common/WriteMask.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012-2015 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mem/ruby/common/WriteMask.hh" + +#include <string> + +#include "mem/ruby/system/RubySystem.hh" + +void +WriteMask::print(std::ostream& out) const +{ + std::string str(mSize,'0'); + for (int i = 0; i < mSize; i++) { + str[i] = mMask[i] ? ('1') : ('0'); + } + out << "dirty mask=" + << str + << std::flush; +} + diff --git a/src/mem/ruby/common/WriteMask.hh b/src/mem/ruby/common/WriteMask.hh new file mode 100644 index 000000000..2de02ef74 --- /dev/null +++ b/src/mem/ruby/common/WriteMask.hh @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2012-15 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MEM_RUBY_COMMON_WRITEMASK_HH__ +#define __MEM_RUBY_COMMON_WRITEMASK_HH__ + +#include <cassert> +#include <iomanip> +#include <iostream> +#include <vector> + +#include "mem/ruby/common/TypeDefines.hh" +#include "mem/ruby/system/RubySystem.hh" + +class WriteMask +{ + public: + WriteMask() + : mSize(RubySystem::getBlockSizeBytes()), mMask(mSize, false), + mAtomic(false) + {} + + WriteMask(int size) + : mSize(size), mMask(size, false), mAtomic(false) + {} + + WriteMask(int size, std::vector<bool> & mask) + : mSize(size), mMask(mask), mAtomic(false) + {} + + WriteMask(int size, std::vector<bool> &mask, + std::vector<std::pair<int, AtomicOpFunctor*> > atomicOp) + : mSize(size), mMask(mask), mAtomic(true), mAtomicOp(atomicOp) + {} + + ~WriteMask() + {} + + void + clear() + { + mMask = std::vector<bool>(mSize, false); + } + + bool + test(int offset) + { + assert(offset < mSize); + return mMask[offset] == true; + } + + void + setMask(int offset, int len) + { + assert(mSize >= (offset + len)); + for (int i = 0; i < len; i++) { + mMask[offset + i] = true; + } + } + void + fillMask() + { + for (int i = 0; i < mSize; i++) { + mMask[i] = true; + } + } + + bool + getMask(int offset, int len) const + { + bool tmp = true; + assert(mSize >= (offset + len)); + for (int i = 0; i < len; i++) { + tmp = tmp & mMask.at(offset + i); + } + return tmp; + } + + bool + isOverlap(const WriteMask &readMask) const + { + bool tmp = false; + assert(mSize == readMask.mSize); + for (int i = 0; i < mSize; i++) { + if (readMask.mMask.at(i)) { + tmp = tmp | mMask.at(i); + } + } + return tmp; + } + + bool + cmpMask(const WriteMask &readMask) const + { + bool tmp = true; + assert(mSize == readMask.mSize); + for (int i = 0; i < mSize; i++) { + if (readMask.mMask.at(i)) { + tmp = tmp & mMask.at(i); + } + } + return tmp; + } + + bool isEmpty() const + { + for (int i = 0; i < mSize; i++) { + if (mMask.at(i)) { + return false; + } + } + return true; + } + + bool + isFull() const + { + for (int i = 0; i < mSize; i++) { + if (!mMask.at(i)) { + return false; + } + } + return true; + } + + void + orMask(const WriteMask & writeMask) + { + assert(mSize == writeMask.mSize); + for (int i = 0; i < mSize; i++) { + mMask[i] = (mMask.at(i)) | (writeMask.mMask.at(i)); + } + + if (writeMask.mAtomic) { + mAtomic = true; + mAtomicOp = writeMask.mAtomicOp; + } + } + + void print(std::ostream& out) const; + + void + performAtomic(uint8_t * p) const + { + for (int i = 0; i < mAtomicOp.size(); i++) { + int offset = mAtomicOp[i].first; + AtomicOpFunctor *fnctr = mAtomicOp[i].second; + (*fnctr)(&p[offset]); + } + } + + void + performAtomic(DataBlock & blk) const + { + for (int i = 0; i < mAtomicOp.size(); i++) { + int offset = mAtomicOp[i].first; + uint8_t *p = blk.getDataMod(offset); + AtomicOpFunctor *fnctr = mAtomicOp[i].second; + (*fnctr)(p); + } + } + private: + int mSize; + std::vector<bool> mMask; + bool mAtomic; + std::vector<std::pair<int, AtomicOpFunctor*> > mAtomicOp; +}; + +inline std::ostream& +operator<<(std::ostream& out, const WriteMask& obj) +{ + obj.print(out); + out << std::flush; + return out; +} + +#endif // __MEM_RUBY_COMMON_WRITEMASK_HH__ |