diff options
author | Giacomo Gabrielli <giacomo.gabrielli@arm.com> | 2017-07-07 14:13:11 +0100 |
---|---|---|
committer | Giacomo Gabrielli <giacomo.gabrielli@arm.com> | 2019-05-11 12:48:58 +0000 |
commit | c58cb8c9dbeef377da180f1fdaaa1c0eadf85550 (patch) | |
tree | 7591abeb888d8c8e645332749bcaea627628f9bf /src/mem/packet.hh | |
parent | d0e4cdc9c36466a3dbef8c9f9f509cce8f1a6c34 (diff) | |
download | gem5-c58cb8c9dbeef377da180f1fdaaa1c0eadf85550.tar.xz |
cpu,mem: Add support for partial loads/stores and wide mem. accesses
This changeset adds support for partial (or masked) loads/stores, i.e.
loads/stores that can disable accesses to individual bytes within the
target address range. In addition, this changeset extends the code to
crack memory accesses across most CPU models (TimingSimpleCPU still
TBD), so that arbitrarily wide memory accesses are supported. These
changes are required for supporting ISAs with wide vectors.
Additional authors:
- Gabor Dozsa <gabor.dozsa@arm.com>
- Tiago Muck <tiago.muck@arm.com>
Change-Id: Ibad33541c258ad72925c0b1d5abc3e5e8bf92d92
Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/13518
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
Diffstat (limited to 'src/mem/packet.hh')
-rw-r--r-- | src/mem/packet.hh | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 93b3ad5de..130cc41ad 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -1092,6 +1092,7 @@ class Packet : public Printable getPtr() { assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); + assert(!isMaskedWrite()); return (T*)data; } @@ -1180,10 +1181,11 @@ class Packet : public Printable // same pointer from source to destination and back assert(p != getPtr<uint8_t>() || flags.isSet(STATIC_DATA)); - if (p != getPtr<uint8_t>()) + if (p != getPtr<uint8_t>()) { // for packet with allocated dynamic data, we copy data from // one to the other, e.g. a forwarded response to a response std::memcpy(getPtr<uint8_t>(), p, getSize()); + } } /** @@ -1203,7 +1205,19 @@ class Packet : public Printable void writeData(uint8_t *p) const { - std::memcpy(p, getConstPtr<uint8_t>(), getSize()); + if (!isMaskedWrite()) { + std::memcpy(p, getConstPtr<uint8_t>(), getSize()); + } else { + assert(req->getByteEnable().size() == getSize()); + // Write only the enabled bytes + const uint8_t *base = getConstPtr<uint8_t>(); + for (int i = 0; i < getSize(); i++) { + if (req->getByteEnable()[i]) { + p[i] = *(base + i); + } + // Disabled bytes stay untouched + } + } } /** @@ -1268,6 +1282,17 @@ class Packet : public Printable bool trySatisfyFunctional(PacketPtr other) { + if (other->isMaskedWrite()) { + // Do not forward data if overlapping with a masked write + if (_isSecure == other->isSecure() && + getAddr() <= (other->getAddr() + other->getSize() - 1) && + other->getAddr() <= (getAddr() + getSize() - 1)) { + warn("Trying to check against a masked write, skipping." + " (addr: 0x%x, other addr: 0x%x)", getAddr(), + other->getAddr()); + } + return false; + } // all packets that are carrying a payload should have a valid // data pointer return trySatisfyFunctional(other, other->getAddr(), other->isSecure(), @@ -1296,6 +1321,12 @@ class Packet : public Printable return cmd == MemCmd::CleanEvict || cmd == MemCmd::WritebackClean; } + bool + isMaskedWrite() const + { + return (cmd == MemCmd::WriteReq && !req->getByteEnable().empty()); + } + /** * Check a functional request against a memory value represented * by a base/size pair and an associated data array. If the |