mem: write combining for ruby protocols
This patch adds support for write-combining in ruby.
This commit is contained in:
parent
d658b6e1cc
commit
28e353e040
10 changed files with 343 additions and 0 deletions
|
@ -39,12 +39,25 @@ external_type(Addr, primitive="yes");
|
||||||
external_type(Cycles, primitive="yes", default="Cycles(0)");
|
external_type(Cycles, primitive="yes", default="Cycles(0)");
|
||||||
external_type(Tick, primitive="yes", default="0");
|
external_type(Tick, primitive="yes", default="0");
|
||||||
|
|
||||||
|
structure(WriteMask, external="yes", desc="...") {
|
||||||
|
void clear();
|
||||||
|
bool cmpMask(WriteMask);
|
||||||
|
bool isEmpty();
|
||||||
|
bool isFull();
|
||||||
|
bool isOverlap(WriteMask);
|
||||||
|
void orMask(WriteMask);
|
||||||
|
void fillMask();
|
||||||
|
}
|
||||||
|
|
||||||
structure(DataBlock, external = "yes", desc="..."){
|
structure(DataBlock, external = "yes", desc="..."){
|
||||||
void clear();
|
void clear();
|
||||||
|
void copyPartial(DataBlock, int, int);
|
||||||
|
void copyPartial(DataBlock, WriteMask);
|
||||||
void atomicPartial(DataBlock, WriteMask);
|
void atomicPartial(DataBlock, WriteMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool testAndRead(Addr addr, DataBlock datablk, Packet *pkt);
|
bool testAndRead(Addr addr, DataBlock datablk, Packet *pkt);
|
||||||
|
bool testAndReadMask(Addr addr, DataBlock datablk, WriteMask mask, Packet *pkt);
|
||||||
bool testAndWrite(Addr addr, DataBlock datablk, Packet *pkt);
|
bool testAndWrite(Addr addr, DataBlock datablk, Packet *pkt);
|
||||||
|
|
||||||
// AccessPermission
|
// AccessPermission
|
||||||
|
|
|
@ -126,6 +126,8 @@ structure(RubyRequest, desc="...", interface="Message", external="yes") {
|
||||||
int Size, desc="size in bytes of access";
|
int Size, desc="size in bytes of access";
|
||||||
PrefetchBit Prefetch, desc="Is this a prefetch request";
|
PrefetchBit Prefetch, desc="Is this a prefetch request";
|
||||||
int contextId, desc="this goes away but must be replace with Nilay";
|
int contextId, desc="this goes away but must be replace with Nilay";
|
||||||
|
WriteMask writeMask, desc="Writethrough mask";
|
||||||
|
DataBlock WTData, desc="Writethrough data block";
|
||||||
int wfid, desc="Writethrough wavefront";
|
int wfid, desc="Writethrough wavefront";
|
||||||
HSAScope scope, desc="HSA scope";
|
HSAScope scope, desc="HSA scope";
|
||||||
HSASegment segment, desc="HSA segment";
|
HSASegment segment, desc="HSA segment";
|
||||||
|
|
|
@ -121,6 +121,7 @@ MakeInclude('common/IntVec.hh')
|
||||||
MakeInclude('common/MachineID.hh')
|
MakeInclude('common/MachineID.hh')
|
||||||
MakeInclude('common/NetDest.hh')
|
MakeInclude('common/NetDest.hh')
|
||||||
MakeInclude('common/Set.hh')
|
MakeInclude('common/Set.hh')
|
||||||
|
MakeInclude('common/WriteMask.hh')
|
||||||
MakeInclude('filters/AbstractBloomFilter.hh')
|
MakeInclude('filters/AbstractBloomFilter.hh')
|
||||||
MakeInclude('network/MessageBuffer.hh')
|
MakeInclude('network/MessageBuffer.hh')
|
||||||
MakeInclude('structures/Prefetcher.hh')
|
MakeInclude('structures/Prefetcher.hh')
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mem/ruby/common/DataBlock.hh"
|
#include "mem/ruby/common/DataBlock.hh"
|
||||||
|
|
||||||
|
#include "mem/ruby/common/WriteMask.hh"
|
||||||
#include "mem/ruby/system/RubySystem.hh"
|
#include "mem/ruby/system/RubySystem.hh"
|
||||||
|
|
||||||
DataBlock::DataBlock(const DataBlock &cp)
|
DataBlock::DataBlock(const DataBlock &cp)
|
||||||
|
@ -56,6 +58,25 @@ DataBlock::equal(const DataBlock& obj) const
|
||||||
return !memcmp(m_data, obj.m_data, RubySystem::getBlockSizeBytes());
|
return !memcmp(m_data, obj.m_data, RubySystem::getBlockSizeBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
void
|
||||||
DataBlock::print(std::ostream& out) const
|
DataBlock::print(std::ostream& out) const
|
||||||
{
|
{
|
||||||
|
@ -77,6 +98,12 @@ DataBlock::getData(int offset, int len) const
|
||||||
return &m_data[offset];
|
return &m_data[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t*
|
||||||
|
DataBlock::getDataMod(int offset)
|
||||||
|
{
|
||||||
|
return &m_data[offset];
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DataBlock::setData(const uint8_t *data, int offset, int len)
|
DataBlock::setData(const uint8_t *data, int offset, int len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
class WriteMask;
|
||||||
|
|
||||||
class DataBlock
|
class DataBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -58,8 +60,12 @@ class DataBlock
|
||||||
void clear();
|
void clear();
|
||||||
uint8_t getByte(int whichByte) const;
|
uint8_t getByte(int whichByte) const;
|
||||||
const uint8_t *getData(int offset, int len) const;
|
const uint8_t *getData(int offset, int len) const;
|
||||||
|
uint8_t *getDataMod(int offset);
|
||||||
void setByte(int whichByte, uint8_t data);
|
void setByte(int whichByte, uint8_t data);
|
||||||
void setData(const uint8_t *data, int offset, int len);
|
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;
|
bool equal(const DataBlock& obj) const;
|
||||||
void print(std::ostream& out) const;
|
void print(std::ostream& out) const;
|
||||||
|
|
||||||
|
|
|
@ -41,3 +41,4 @@ Source('Histogram.cc')
|
||||||
Source('IntVec.cc')
|
Source('IntVec.cc')
|
||||||
Source('NetDest.cc')
|
Source('NetDest.cc')
|
||||||
Source('SubBlock.cc')
|
Source('SubBlock.cc')
|
||||||
|
Source('WriteMask.cc')
|
||||||
|
|
46
src/mem/ruby/common/WriteMask.cc
Normal file
46
src/mem/ruby/common/WriteMask.cc
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
202
src/mem/ruby/common/WriteMask.hh
Normal file
202
src/mem/ruby/common/WriteMask.hh
Normal file
|
@ -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__
|
|
@ -40,6 +40,7 @@
|
||||||
#include "mem/protocol/RubyRequestType.hh"
|
#include "mem/protocol/RubyRequestType.hh"
|
||||||
#include "mem/ruby/common/Address.hh"
|
#include "mem/ruby/common/Address.hh"
|
||||||
#include "mem/ruby/common/DataBlock.hh"
|
#include "mem/ruby/common/DataBlock.hh"
|
||||||
|
#include "mem/ruby/common/WriteMask.hh"
|
||||||
|
|
||||||
class RubyRequest : public Message
|
class RubyRequest : public Message
|
||||||
{
|
{
|
||||||
|
@ -54,6 +55,8 @@ class RubyRequest : public Message
|
||||||
uint8_t* data;
|
uint8_t* data;
|
||||||
PacketPtr pkt;
|
PacketPtr pkt;
|
||||||
ContextID m_contextId;
|
ContextID m_contextId;
|
||||||
|
WriteMask m_writeMask;
|
||||||
|
DataBlock m_WTData;
|
||||||
int m_wfid;
|
int m_wfid;
|
||||||
HSAScope m_scope;
|
HSAScope m_scope;
|
||||||
HSASegment m_segment;
|
HSASegment m_segment;
|
||||||
|
@ -99,6 +102,8 @@ class RubyRequest : public Message
|
||||||
data(_data),
|
data(_data),
|
||||||
pkt(_pkt),
|
pkt(_pkt),
|
||||||
m_contextId(_core_id),
|
m_contextId(_core_id),
|
||||||
|
m_writeMask(_wm_size,_wm_mask),
|
||||||
|
m_WTData(_Data),
|
||||||
m_wfid(_proc_id),
|
m_wfid(_proc_id),
|
||||||
m_scope(_scope),
|
m_scope(_scope),
|
||||||
m_segment(_segment)
|
m_segment(_segment)
|
||||||
|
@ -125,6 +130,8 @@ class RubyRequest : public Message
|
||||||
data(_data),
|
data(_data),
|
||||||
pkt(_pkt),
|
pkt(_pkt),
|
||||||
m_contextId(_core_id),
|
m_contextId(_core_id),
|
||||||
|
m_writeMask(_wm_size,_wm_mask,_atomicOps),
|
||||||
|
m_WTData(_Data),
|
||||||
m_wfid(_proc_id),
|
m_wfid(_proc_id),
|
||||||
m_scope(_scope),
|
m_scope(_scope),
|
||||||
m_segment(_segment)
|
m_segment(_segment)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||||
|
* Copyright (c) 2013 Advanced Micro Devices, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
#include "mem/ruby/common/BoolVec.hh"
|
#include "mem/ruby/common/BoolVec.hh"
|
||||||
#include "mem/ruby/common/DataBlock.hh"
|
#include "mem/ruby/common/DataBlock.hh"
|
||||||
#include "mem/ruby/common/TypeDefines.hh"
|
#include "mem/ruby/common/TypeDefines.hh"
|
||||||
|
#include "mem/ruby/common/WriteMask.hh"
|
||||||
|
|
||||||
inline Cycles zero_time() { return Cycles(0); }
|
inline Cycles zero_time() { return Cycles(0); }
|
||||||
|
|
||||||
|
@ -88,6 +90,12 @@ inline int max_tokens()
|
||||||
* range for the data block contains the address which the packet needs to
|
* range for the data block contains the address which the packet needs to
|
||||||
* read, then the data from the data block is written to the packet. True is
|
* read, then the data from the data block is written to the packet. True is
|
||||||
* returned if the data block was read, otherwise false is returned.
|
* returned if the data block was read, otherwise false is returned.
|
||||||
|
*
|
||||||
|
* This is used during a functional access "search the world" operation. The
|
||||||
|
* functional access looks in every place that might hold a valid data block
|
||||||
|
* and, if it finds one, checks to see if it is holding the address the access
|
||||||
|
* is searching for. During the access check, the WriteMask could be in any
|
||||||
|
* state, including empty.
|
||||||
*/
|
*/
|
||||||
inline bool
|
inline bool
|
||||||
testAndRead(Addr addr, DataBlock& blk, Packet *pkt)
|
testAndRead(Addr addr, DataBlock& blk, Packet *pkt)
|
||||||
|
@ -108,6 +116,36 @@ testAndRead(Addr addr, DataBlock& blk, Packet *pkt)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function accepts an address, a data block, a write mask and a packet.
|
||||||
|
* If the valid address range for the data block contains the address which
|
||||||
|
* the packet needs to read, then the data from the data block is written to
|
||||||
|
* the packet. True is returned if any part of the data block was read,
|
||||||
|
* otherwise false is returned.
|
||||||
|
*/
|
||||||
|
inline bool
|
||||||
|
testAndReadMask(Addr addr, DataBlock& blk, WriteMask& mask, Packet *pkt)
|
||||||
|
{
|
||||||
|
Addr pktLineAddr = makeLineAddress(pkt->getAddr());
|
||||||
|
Addr lineAddr = makeLineAddress(addr);
|
||||||
|
|
||||||
|
if (pktLineAddr == lineAddr) {
|
||||||
|
uint8_t *data = pkt->getPtr<uint8_t>();
|
||||||
|
unsigned int size_in_bytes = pkt->getSize();
|
||||||
|
unsigned startByte = pkt->getAddr() - lineAddr;
|
||||||
|
bool was_read = false;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < size_in_bytes; ++i) {
|
||||||
|
if (mask.test(i + startByte)) {
|
||||||
|
was_read = true;
|
||||||
|
data[i] = blk.getByte(i + startByte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return was_read;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function accepts an address, a data block and a packet. If the address
|
* This function accepts an address, a data block and a packet. If the address
|
||||||
* range for the data block contains the address which the packet needs to
|
* range for the data block contains the address which the packet needs to
|
||||||
|
|
Loading…
Reference in a new issue